diff --git a/src/commands/run.rs b/src/commands/run.rs index 0abe225..f2f0bf9 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -2,7 +2,7 @@ use std::{io::Read, sync::{Arc, Mutex}}; use cpal::{traits::{DeviceTrait, HostTrait, StreamTrait}, Device}; -use crate::{args::Run, device::virtual_device}; +use crate::{args::Run, device::virtual_device::VirtualDevice}; fn reshape_audio_data(input: &[T], channels: usize) -> Vec> where @@ -25,9 +25,9 @@ where let frames = input[0].len(); let mut output = vec![]; for i in 0..frames { - for j in 0..channels { + (0..channels).for_each(|j| { output.push(input[j][i].clone()); - } + }); } output } @@ -41,7 +41,7 @@ pub fn run(run: Run) { } let mut buf = String::default(); - let mut config = if let Ok(config) = std::fs::File::open(&config) { + let mut config = if let Ok(config) = std::fs::File::open(config) { config } else { eprintln!("Cannot open config file."); @@ -127,7 +127,6 @@ pub fn run(run: Run) { let mut streams = vec![]; - // attach real device to virtual device for input_route in &config.routes.input { match &input_route.device { crate::config::Device::Local { local } => { @@ -136,24 +135,50 @@ pub fn run(run: Run) { .find(|device| device.name().unwrap() == local.name) .unwrap(); let config = device.default_input_config().unwrap(); - println!("input config: {:?}", config); let channels = config.channels(); - let virtual_devices = virtual_devices.iter().filter(|device| device.lock().unwrap().name == input_route.virtual_device).map(|d| d.clone()).collect::>()[0].clone(); - let stream = device.build_input_stream( - &config.into(), - { - move |data, _| { - println!("Data length: {}", data.len()); - let audio_data = reshape_audio_data(&data, channels as usize); + let sample_rate = config.sample_rate().0; + + let virtual_devices = virtual_devices.iter().filter(|device| device.lock().unwrap().name == input_route.virtual_device).cloned().collect::>()[0].clone(); + + let stream = match config.sample_format() { + cpal::SampleFormat::I8 => device.build_input_stream( + &config.into(), + { + move |data: &[i8], _| input_callback(data, channels.into(), sample_rate, virtual_devices.clone()) + }, + move |err| eprintln!("An error occurred on the input stream: {}", err), + None + ), + cpal::SampleFormat::I16 => device.build_input_stream( + &config.into(), + { + move |data: &[i16], _| input_callback(data, channels.into(), sample_rate, virtual_devices.clone()) + }, + move |err| eprintln!("An error occurred on the input stream: {}", err), + None + ), + cpal::SampleFormat::I32 => device.build_input_stream( + &config.into(), + { + move |data: &[i32], _| input_callback(data, channels.into(), sample_rate, virtual_devices.clone()) + }, + move |err| eprintln!("An error occurred on the input stream: {}", err), + None + ), + cpal::SampleFormat::F32 => device.build_input_stream( + &config.into(), + { + move |data: &[f32], _| input_callback(data, channels.into(), sample_rate, virtual_devices.clone()) + }, + move |err| eprintln!("An error occurred on the input stream: {}", err), + None + ), + sample_format => { + eprintln!("Unsupported sample format: {:?}", sample_format); + return; + } + }.unwrap(); - for (i, buffer) in audio_data.iter().enumerate() { - virtual_devices.lock().unwrap().write_input(i as u8, buffer.clone()); - } - } - }, - move |err| eprintln!("An error occurred on the input stream: {}", err), - None - ).unwrap(); stream.play().unwrap(); streams.push(stream); } @@ -171,34 +196,52 @@ pub fn run(run: Run) { .find(|device| device.name().unwrap() == local.name) .unwrap(); let config = device.default_output_config().unwrap(); - println!("output config: {:?}", config); + let channels = config.channels(); - let virtual_device = virtual_devices.iter().filter(|device| device.lock().unwrap().name == output_route.input.virtual_device).map(|d| d.clone()).collect::>()[0].clone(); + let sample_rate = config.sample_rate().0; + + let virtual_device = virtual_devices.iter().filter(|device| device.lock().unwrap().name == output_route.input.virtual_device).cloned().collect::>()[0].clone(); let index = virtual_device.lock().unwrap().add_output(); - let stream = device.build_output_stream( - &config.into(), - { - move |data, _| { - println!("Data length: {}", data.len()); - let mut audio_data = vec![]; - for i in 0..channels { - audio_data.push(virtual_device.lock().unwrap().take_output(index, i as u8, data.len() / channels as usize).unwrap_or_default()); - } - let mut audio_data = to_flat_audio_data(&audio_data); - let data_len = data.len(); - let audio_data_len = audio_data.len(); - if data_len > audio_data_len { - audio_data.extend(vec![0.0; data_len - audio_data_len]); - } + let stream = match config.sample_format() { + cpal::SampleFormat::I8 => device.build_output_stream( + &config.into(), + { + move |data: &mut [i8], _| output_callback(data, channels.into(), sample_rate, virtual_device.clone(), index) + }, + move |err| eprintln!("An error occurred on the output stream: {}", err), + None + ), + cpal::SampleFormat::I16 => device.build_output_stream( + &config.into(), + { + move |data: &mut [i16], _| output_callback(data, channels.into(), sample_rate, virtual_device.clone(), index) + }, + move |err| eprintln!("An error occurred on the output stream: {}", err), + None + ), + cpal::SampleFormat::I32 => device.build_output_stream( + &config.into(), + { + move |data: &mut [i32], _| output_callback(data, channels.into(), sample_rate, virtual_device.clone(), index) + }, + move |err| eprintln!("An error occurred on the output stream: {}", err), + None + ), + cpal::SampleFormat::F32 => device.build_output_stream( + &config.into(), + { + move |data: &mut [f32], _| output_callback(data, channels.into(), sample_rate, virtual_device.clone(), index) + }, + move |err| eprintln!("An error occurred on the output stream: {}", err), + None + ), + sample_format => { + eprintln!("Unsupported sample format: {:?}", sample_format); + return; + } + }.unwrap(); - data.clone_from_slice(&audio_data); - println!("Data: {:?}", data); - } - }, - move |err| eprintln!("An error occurred on the output stream: {}", err), - None - ).unwrap(); stream.play().unwrap(); streams.push(stream); } @@ -210,3 +253,38 @@ pub fn run(run: Run) { std::thread::sleep(std::time::Duration::from_secs(10)); } + +fn input_callback(data: &[T], channels: usize, sample_rate: u32, virtual_device: Arc>) +where + T: Clone + num::cast::ToPrimitive +{ + let data: Vec = data.iter().map(|d| d.to_f32().unwrap()).collect(); + let audio_data = reshape_audio_data(&data, channels); + let audio_data = crate::audio::resampling::resampling(sample_rate, virtual_device.lock().unwrap().sample_rate, audio_data); + + for (i, buffer) in audio_data.iter().enumerate() { + virtual_device.lock().unwrap().write_input(i as u8, buffer.clone()); + } +} + +fn output_callback(data: &mut [T], channels: usize, sample_rate: u32, virtual_device: Arc>, index: usize) +where + T: Clone + num::cast::FromPrimitive +{ + let mut audio_data = vec![]; + for i in 0..channels { + audio_data.push(virtual_device.lock().unwrap().take_output(index, i as u8, data.len() / channels).unwrap_or(vec![0.; data.len() / channels])); + } + let audio_data = crate::audio::resampling::resampling(virtual_device.lock().unwrap().sample_rate, sample_rate, audio_data); + let mut audio_data = to_flat_audio_data(&audio_data); + + let data_len = data.len(); + let audio_data_len = audio_data.len(); + if data_len > audio_data_len { + audio_data.extend(vec![0.0; data_len - audio_data_len]); + } + + let audio_data: Vec = audio_data.iter().map(|d| T::from_f32(*d).unwrap()).collect(); + + data.clone_from_slice(&audio_data); +} \ No newline at end of file