From 7058517e8cafdb2ead3858031629e699c3dde466 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Wed, 26 Aug 2026 18:44:37 +0200 Subject: [PATCH] More resampling --- src-tauri/src/commands/audio.rs | 47 ++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src-tauri/src/commands/audio.rs b/src-tauri/src/commands/audio.rs index 39ed47d..b74e1a4 100644 --- a/src-tauri/src/commands/audio.rs +++ b/src-tauri/src/commands/audio.rs @@ -135,7 +135,10 @@ pub fn connect_to_vc( while input_buffer.len() >= 1024 { let input: Vec = input_buffer.drain(..1024).collect(); - let mut output = vec![0.0f32; 1024]; + let output_len = + ((1024.0 * 44100.0 / input_config.sample_rate as f32).ceil()) as usize; + + let mut output = vec![0.0f32; output_len]; if let Err(e) = input_resampler.resample(&input, &mut output) { eprintln!("[vc] failed to resample input: {e}"); @@ -157,7 +160,7 @@ pub fn connect_to_vc( .map_err(|e| e.to_string())?; let output_socket = socket.clone(); - let mut output_config: cpal::StreamConfig = output_device + let output_config: cpal::StreamConfig = output_device .default_output_config() .map_err(|e| e.to_string())? .into(); @@ -170,20 +173,23 @@ pub fn connect_to_vc( .map_err(|e| format!("{e:?}"))?, ); - output_config.channels = 1; - // shared ring buffer between the UDP-receiving task and the playback callback - let (audio_tx, audio_rx) = std::sync::mpsc::channel::<[f32; 1024]>(); + let (audio_tx, audio_rx) = std::sync::mpsc::channel::>(); let output_stream = output_device .build_output_stream( - output_config, + output_config.clone(), move |data: &mut [f32], _| { if let Ok(pcm) = audio_rx.try_recv() { - eprintln!("[vc] playing {} samples", pcm.len()); for (out, sample) in data.iter_mut().zip(pcm.iter()) { *out = *sample; } + + // If CPAL asks for more samples than we received, + // fill the remainder with silence. + if pcm.len() < data.len() { + data[pcm.len()..].fill(0.0); + } } else { data.fill(0.0); } @@ -211,14 +217,24 @@ pub fn connect_to_vc( while output_buffer.len() >= 1024 { let input: Vec = output_buffer.drain(..1024).collect(); - let mut pcm_out = [0.0f32; 1024]; + let output_len = + ((1024.0 * output_config.sample_rate as f32 / 44100.0).ceil()) as usize; + + let mut pcm_out = vec![0.0f32; output_len]; if let Err(e) = output_resampler.resample(&input, &mut pcm_out) { eprintln!("[vc] failed to resample output: {e}"); continue; } - if audio_tx.send(pcm_out).is_err() { + if audio_tx + .send(if output_config.channels > 1 { + stereo_to_mono(&pcm_out) + } else { + pcm_out + }) + .is_err() + { return; } } @@ -244,3 +260,16 @@ pub fn disconnect_from_vc(voice_state: State) -> Result<(), String> *voice_state.session.lock().unwrap() = None; // dropping stops both cpal streams Ok(()) } + +fn stereo_to_mono(stereo_data: &[f32]) -> Vec { + let mut mono_data = Vec::with_capacity(stereo_data.len() / 2); + + for chunk in stereo_data.chunks_exact(2) { + let left = chunk[0]; + let right = chunk[1]; + let mono_sample = (left + right) / 2.0; + mono_data.push(mono_sample); + } + + mono_data +}