bump cpal to 0.15

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2023-04-15 09:41:56 +08:00
parent 16b2e88c1c
commit cb342f86e6
4 changed files with 112 additions and 226 deletions

View File

@@ -644,7 +644,7 @@ impl Client {
// `try_start_clipboard` is called by all session when connection is established. (When handling peer info).
// This function only create one thread with a loop, the loop is shared by all sessions.
// After all sessions are end, the loop exists.
//
//
// If clipboard update is detected, the text will be sent to all sessions by `send_text_clipboard_msg`.
#[cfg(not(any(target_os = "android", target_os = "ios")))]
fn try_start_clipboard(_ctx: Option<ClientClipboardContext>) {
@@ -801,9 +801,17 @@ impl AudioHandler {
let mut config: StreamConfig = config.into();
config.channels = format0.channels as _;
match sample_format {
cpal::SampleFormat::F32 => self.build_output_stream::<f32>(&config, &device)?,
cpal::SampleFormat::I8 => self.build_output_stream::<i8>(&config, &device)?,
cpal::SampleFormat::I16 => self.build_output_stream::<i16>(&config, &device)?,
cpal::SampleFormat::I32 => self.build_output_stream::<i32>(&config, &device)?,
cpal::SampleFormat::I64 => self.build_output_stream::<i64>(&config, &device)?,
cpal::SampleFormat::U8 => self.build_output_stream::<u8>(&config, &device)?,
cpal::SampleFormat::U16 => self.build_output_stream::<u16>(&config, &device)?,
cpal::SampleFormat::U32 => self.build_output_stream::<u32>(&config, &device)?,
cpal::SampleFormat::U64 => self.build_output_stream::<u64>(&config, &device)?,
cpal::SampleFormat::F32 => self.build_output_stream::<f32>(&config, &device)?,
cpal::SampleFormat::F64 => self.build_output_stream::<f64>(&config, &device)?,
f => bail!("unsupported audio format: {:?}", f),
}
self.sample_rate = (format0.sample_rate, config.sample_rate.0);
Ok(())
@@ -880,7 +888,7 @@ impl AudioHandler {
/// Build audio output stream for current device.
#[cfg(not(any(target_os = "android", target_os = "linux")))]
fn build_output_stream<T: cpal::Sample>(
fn build_output_stream<T: cpal::Sample + cpal::SizedSample + cpal::FromSample<f32>>(
&mut self,
config: &StreamConfig,
device: &Device,
@@ -891,6 +899,7 @@ impl AudioHandler {
};
let audio_buffer = self.audio_buffer.0.clone();
let ready = self.ready.clone();
let timeout = None;
let stream = device.build_output_stream(
config,
move |data: &mut [T], _: &_| {
@@ -908,12 +917,13 @@ impl AudioHandler {
let mut input = elems.into_iter();
for sample in data.iter_mut() {
*sample = match input.next() {
Some(x) => T::from(&x),
_ => T::from(&0.),
Some(x) => T::from_sample(x),
_ => T::from_sample(0.),
};
}
},
err_fn,
timeout,
)?;
stream.play()?;
self.audio_stream = Some(Box::new(stream));

View File

@@ -104,7 +104,7 @@ mod cpal_impl {
use super::*;
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
Device, Host, SupportedStreamConfig,
BufferSize, Device, Host, InputCallbackInfo, StreamConfig, SupportedStreamConfig,
};
lazy_static::lazy_static! {
@@ -214,12 +214,9 @@ mod cpal_impl {
}
fn play(sp: &GenericService) -> ResultType<(Box<dyn StreamTrait>, Arc<Message>)> {
use cpal::SampleFormat::*;
let (device, config) = get_device()?;
let sp = sp.clone();
let err_fn = move |err| {
// too many UnknownErrno, will improve later
log::trace!("an error occurred on stream: {}", err);
};
// Sample rate must be one of 8000, 12000, 16000, 24000, or 48000.
let sample_rate_0 = config.sample_rate().0;
let sample_rate = if sample_rate_0 < 12000 {
@@ -233,6 +230,40 @@ mod cpal_impl {
} else {
48000
};
let stream = match config.sample_format() {
I8 => build_input_stream::<i8>(device, &config, sp, sample_rate)?,
I16 => build_input_stream::<i16>(device, &config, sp, sample_rate)?,
I32 => build_input_stream::<i32>(device, &config, sp, sample_rate)?,
I64 => build_input_stream::<i64>(device, &config, sp, sample_rate)?,
U8 => build_input_stream::<u8>(device, &config, sp, sample_rate)?,
U16 => build_input_stream::<u16>(device, &config, sp, sample_rate)?,
U32 => build_input_stream::<u32>(device, &config, sp, sample_rate)?,
U64 => build_input_stream::<u64>(device, &config, sp, sample_rate)?,
F32 => build_input_stream::<f32>(device, &config, sp, sample_rate)?,
F64 => build_input_stream::<f64>(device, &config, sp, sample_rate)?,
f => bail!("unsupported audio format: {:?}", f),
};
stream.play()?;
Ok((
Box::new(stream),
Arc::new(create_format_msg(sample_rate, config.channels())),
))
}
fn build_input_stream<T>(
device: cpal::Device,
config: &cpal::SupportedStreamConfig,
sp: GenericService,
sample_rate: u32,
) -> ResultType<cpal::Stream>
where
T: cpal::SizedSample + dasp::sample::ToSample<f32>,
{
let err_fn = move |err| {
// too many UnknownErrno, will improve later
log::trace!("an error occurred on stream: {}", err);
};
let sample_rate_0 = config.sample_rate().0;
log::debug!("Audio sample rate : {}", sample_rate);
unsafe {
AUDIO_ZERO_COUNT = 0;
@@ -247,54 +278,34 @@ mod cpal_impl {
// https://chromium.googlesource.com/chromium/deps/opus/+/1.1.1/include/opus.h
let encode_len = sample_rate as usize * channels as usize / 100; // 10 ms
INPUT_BUFFER.lock().unwrap().clear();
let mut send_input_stream = move || {
let mut lock = INPUT_BUFFER.lock().unwrap();
while lock.len() >= encode_len {
let frame: Vec<f32> = lock.drain(0..encode_len).collect();
send(
&frame,
sample_rate_0,
sample_rate,
channels,
&mut encoder,
&sp,
);
}
let timeout = None;
let stream_config = StreamConfig {
channels,
sample_rate: config.sample_rate(),
buffer_size: BufferSize::Default,
};
let stream = match config.sample_format() {
cpal::SampleFormat::F32 => device.build_input_stream(
&config.into(),
move |data, _: &_| {
INPUT_BUFFER.lock().unwrap().extend(data);
send_input_stream();
},
err_fn,
)?,
cpal::SampleFormat::I16 => device.build_input_stream(
&config.into(),
move |data: &[i16], _: &_| {
let buffer: Vec<_> = data.iter().map(|s| cpal::Sample::to_f32(s)).collect();
INPUT_BUFFER.lock().unwrap().extend(buffer);
send_input_stream();
},
err_fn,
)?,
cpal::SampleFormat::U16 => device.build_input_stream(
&config.into(),
move |data: &[u16], _: &_| {
let buffer: Vec<_> = data.iter().map(|s| cpal::Sample::to_f32(s)).collect();
INPUT_BUFFER.lock().unwrap().extend(buffer);
send_input_stream();
},
err_fn,
)?,
};
stream.play()?;
Ok((
Box::new(stream),
Arc::new(create_format_msg(sample_rate, channels)),
))
let stream = device.build_input_stream(
&stream_config,
move |data: &[T], _: &InputCallbackInfo| {
let buffer: Vec<f32> = data.iter().map(|s| T::to_sample(*s)).collect();
let mut lock = INPUT_BUFFER.lock().unwrap();
lock.extend(buffer);
while lock.len() >= encode_len {
let frame: Vec<f32> = lock.drain(0..encode_len).collect();
send(
&frame,
sample_rate_0,
sample_rate,
channels,
&mut encoder,
&sp,
);
}
},
err_fn,
timeout,
)?;
Ok(stream)
}
}