use ctrlc;
use failure::Error;
use portaudio;
use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread,
time::Duration,
};
use webrtc_audio_processing::*;
const SAMPLE_RATE: f64 = 48_000.0;
const FRAMES_PER_BUFFER: u32 = 480;
fn create_processor(
num_capture_channels: i32,
num_render_channels: i32,
) -> Result<Processor, Error> {
let mut processor = Processor::new(&InitializationConfig {
num_capture_channels,
num_render_channels,
..InitializationConfig::default()
})?;
let config = Config {
echo_cancellation: Some(EchoCancellation {
suppression_level: EchoCancellationSuppressionLevel::Low,
stream_delay_ms: Some(0),
enable_delay_agnostic: true,
enable_extended_filter: true,
}),
enable_high_pass_filter: true,
..Config::default()
};
processor.set_config(config);
Ok(processor)
}
fn wait_ctrlc() -> Result<(), Error> {
let running = Arc::new(AtomicBool::new(true));
ctrlc::set_handler({
let running = running.clone();
move || {
running.store(false, Ordering::SeqCst);
}
})?;
while running.load(Ordering::SeqCst) {
thread::sleep(Duration::from_millis(10));
}
Ok(())
}
fn main() -> Result<(), Error> {
let input_channels = 1;
let output_channels = 1;
let mut processor = create_processor(input_channels, output_channels)?;
let pa = portaudio::PortAudio::new()?;
let stream_settings = pa.default_duplex_stream_settings(
input_channels,
output_channels,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
)?;
let mut processed = vec![0f32; FRAMES_PER_BUFFER as usize * input_channels as usize];
let mut stream = pa.open_non_blocking_stream(
stream_settings,
move |portaudio::DuplexStreamCallbackArgs { in_buffer, mut out_buffer, frames, .. }| {
assert_eq!(frames as u32, FRAMES_PER_BUFFER);
processed.copy_from_slice(&in_buffer);
processor.process_capture_frame(&mut processed).unwrap();
out_buffer.copy_from_slice(&processed);
processor.process_render_frame(&mut out_buffer).unwrap();
portaudio::Continue
},
)?;
stream.start()?;
wait_ctrlc()?;
Ok(())
}