diff --git a/crates/livekit_client/src/livekit_client/playback.rs b/crates/livekit_client/src/livekit_client/playback.rs index c62b8853b4..f14e156125 100644 --- a/crates/livekit_client/src/livekit_client/playback.rs +++ b/crates/livekit_client/src/livekit_client/playback.rs @@ -1,6 +1,7 @@ use anyhow::{Context as _, Result}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait as _}; +use cpal::{Data, FromSample, I24, SampleFormat, SizedSample}; use futures::channel::mpsc::UnboundedSender; use futures::{Stream, StreamExt as _}; use gpui::{ @@ -258,9 +259,15 @@ impl AudioStack { let stream = device .build_input_stream_raw( &config.config(), - cpal::SampleFormat::I16, + config.sample_format(), move |data, _: &_| { - let mut data = data.as_slice::().unwrap(); + let data = + Self::get_sample_data(config.sample_format(), data).log_err(); + let Some(data) = data else { + return; + }; + let mut data = data.as_slice(); + while data.len() > 0 { let remainder = (buf.capacity() - buf.len()).min(data.len()); buf.extend_from_slice(&data[..remainder]); @@ -313,6 +320,33 @@ impl AudioStack { drop(end_on_drop_tx) } } + + fn get_sample_data(sample_format: SampleFormat, data: &Data) -> Result> { + match sample_format { + SampleFormat::I8 => Ok(Self::convert_sample_data::(data)), + SampleFormat::I16 => Ok(data.as_slice::().unwrap().to_vec()), + SampleFormat::I24 => Ok(Self::convert_sample_data::(data)), + SampleFormat::I32 => Ok(Self::convert_sample_data::(data)), + SampleFormat::I64 => Ok(Self::convert_sample_data::(data)), + SampleFormat::U8 => Ok(Self::convert_sample_data::(data)), + SampleFormat::U16 => Ok(Self::convert_sample_data::(data)), + SampleFormat::U32 => Ok(Self::convert_sample_data::(data)), + SampleFormat::U64 => Ok(Self::convert_sample_data::(data)), + SampleFormat::F32 => Ok(Self::convert_sample_data::(data)), + SampleFormat::F64 => Ok(Self::convert_sample_data::(data)), + _ => anyhow::bail!("Unsupported sample format"), + } + } + + fn convert_sample_data>( + data: &Data, + ) -> Vec { + data.as_slice::() + .unwrap() + .iter() + .map(|e| e.to_sample::()) + .collect() + } } use super::LocalVideoTrack;