Ошибка при записи звука в файл с помощью Hound и PortAudio
Для проекта, над которым я недавно работал, мне нужно записать 3 секунды звука, когда пользователь нажимает кнопку, и сохранить его в аудиофайл.
У меня есть portaudio и hound, настроенные и работающие для записи и вывода файла WAV, но он создает файл с именемrecorded.wav
это неиграбельно/повреждено и выдает следующую ошибку.
GetNameFromCategory: USB GUID 0301 -> 'Speakers'
PinNew: Pin name 'Speakers'
PinNew: Releasing topology filter...
Pin created successfully
PinNew: Creating pin 3:
PinNew: Not source/sink
PinNew: Error -9996
Filter (WaveCyclic) created with 2 valid pins (total I/Os: 2)
after paHostApiInitializers[4].
thread 'main' panicked at 'The wave format of the file is not supported.', src\main.rs:36:23
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/ecd44958e0a21110d09862ee080d95a4ca6c52f8/library\std\src\panicking.rs:584
1: core::panicking::panic_fmt
at /rustc/ecd44958e0a21110d09862ee080d95a4ca6c52f8/library\core\src\panicking.rs:142
2: core::panicking::panic_display<alloc::string::String>
at /rustc/ecd44958e0a21110d09862ee080d95a4ca6c52f8\library\core\src\panicking.rs:72
3: music_tool::main
at .\src\main.rs:36
4: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
at /rustc/ecd44958e0a21110d09862ee080d95a4ca6c52f8\library\core\src\ops\function.rs:248
Также вот код, который я запускаю.
extern crate portaudio;
extern crate hound;
use hound::WavWriter;
use std::fs;
use std::io;
use std::mem;
use std::time::{Duration, Instant};
use std::sync::mpsc::channel;
const CHANNELS: i32 = 2;
const SAMPLE_RATE: f64 = 16_000.0;
const FRAMES: u32 = 256;
fn main() {
let pa = match open_audio_port() {
Ok(port) => port,
Err(error) => panic!("{}", String::from(error))
};
//setup_stream(aud
let input_index = match get_input_device_index(&pa) {
Ok(index) => index,
Err(error) => panic!("{}", String::from(error))
};
let input_settings = match get_input_settings(input_index, &pa, SAMPLE_RATE, FRAMES, CHANNELS) {
Ok(settings) => settings,
Err(error) => panic!("{}", String::from(error))
};
let mut wav_writer = match get_wav_writer("recorded.wav", CHANNELS, SAMPLE_RATE) {
Ok(writer) => writer,
Err(error) => panic!("{}", error.to_string()),
};
let (sender, receiver) = channel();
let callback = move |portaudio::InputStreamCallbackArgs { buffer, .. }| {
let _buf = buffer.clone();
sender.send(_buf).unwrap();
portaudio::Continue
};
// Construct a stream with input and output sample types of i32
let mut stream = match pa.open_non_blocking_stream(input_settings, callback) {
Ok(strm) => strm,
Err(error) => panic!("{}", error.to_string()),
};
match stream.start() {
Ok(_) => {}
Err(error) => panic!("{}", error.to_string()),
};
let start = Instant::now();
let time_to_wait = &(5 as u64);
while start.elapsed().as_secs().lt(time_to_wait) {
let recv_data = receiver.recv().unwrap();
for sample in recv_data.iter() {
wav_writer.write_sample(*sample).ok();
}
}
match close_stream(stream){
Ok(_) => {}
Err(error) => panic!("{}", error.to_string()),
};
}
fn get_wav_writer(path: &'static str, channels: i32, sample_rate: f64) -> Result<WavWriter<io::BufWriter<fs::File>>,String> {
let spec = wav_spec(channels, sample_rate);
match hound::WavWriter::create(path, spec) {
Ok(writer) => Ok(writer),
Err(error) => Err (String::from(format!("{}",error))),
}
}
fn wav_spec(channels: i32, sample_rate: f64) -> hound::WavSpec {
hound::WavSpec {
channels: channels as _,
sample_rate: sample_rate as _,
bits_per_sample: (mem::size_of::<i16>()) as _,
sample_format: hound::SampleFormat::Int,
}
}
fn close_stream(mut stream: portaudio::Stream<portaudio::NonBlocking, portaudio::Input<i16>>) -> Result<String, String> {
match stream.stop() {
Ok(_) => {
Ok(String::from("Stream closed"))
},
Err(error) => {
Err(error.to_string())
},
}
}
fn open_audio_port() -> Result<portaudio::PortAudio, String>
{
portaudio::PortAudio::new().or_else(|error| Err(String::from(format!("{}", error))))
}
fn get_input_device_index(audio_port: &portaudio::PortAudio) -> Result<portaudio::DeviceIndex, String>
{
audio_port.default_input_device().or_else(|error| Err(String::from(format!("{}", error))))
}
fn get_input_latency(audio_port: &portaudio::PortAudio, input_index: portaudio::DeviceIndex) -> Result<f64, String>
{
let input_device_information = audio_port.device_info(input_index).or_else(|error| Err(String::from(format!("{}", error))));
Ok(input_device_information.unwrap().default_low_input_latency)
}
fn get_input_stream_parameters(input_index: portaudio::DeviceIndex, latency: f64, channels: i32) -> Result<portaudio::StreamParameters<i16>, String>
{
const INTERLEAVED: bool = true;
Ok(portaudio::StreamParameters::<i16>::new(input_index, channels, INTERLEAVED, latency))
}
fn get_input_settings(input_index: portaudio::DeviceIndex, audio_port: &portaudio::PortAudio, sample_rate: f64, frames: u32, channels: i32) -> Result<portaudio::InputStreamSettings<i16>, String>
{
Ok(
portaudio::InputStreamSettings::new(
(get_input_stream_parameters(
input_index,
(get_input_latency(
&audio_port,
input_index,
))?,
channels
))?,
sample_rate,
frames,
)
)
}
Также мои текущие зависимости и версии в файле cargo.
[dependencies]
hound = "3.5.0"
portaudio = "0.7.0"
Я немного новичок в portaudio и в том, как он взаимодействует с ржавчиной, надеюсь, кто-то может помочь указать мне правильное направление. Заранее спасибо!