Ошибка при записи звука в файл с помощью 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 и в том, как он взаимодействует с ржавчиной, надеюсь, кто-то может помочь указать мне правильное направление. Заранее спасибо!

0 ответов

Другие вопросы по тегам