add support for sound devices that only accept 16bit audio

This commit is contained in:
2023-08-23 23:03:23 +02:00
parent 440e150896
commit 805c939097

View File

@@ -328,23 +328,26 @@ fn init_sound(
let mut configs: Vec<_> = device let mut configs: Vec<_> = device
.supported_output_configs()? .supported_output_configs()?
.filter(|config| { .filter(|config| {
config.channels() == 2 && config.sample_format() == cpal::SampleFormat::F32 config.channels() == 2
&& (config.sample_format() == cpal::SampleFormat::F32
|| config.sample_format() == cpal::SampleFormat::I16)
}) })
.collect(); .collect();
configs.sort_by_key(|config| { configs.sort_by_key(|config| {
let rate = 44100 let rate = 44100
.max(config.min_sample_rate().0) .max(config.min_sample_rate().0)
.min(config.max_sample_rate().0); .min(config.max_sample_rate().0);
if rate >= 44100 { let prio = if rate >= 44100 {
rate - 44100 rate - 44100
} else { } else {
(44100 - rate) * 1000 (44100 - rate) * 1000
} };
prio + (config.sample_format() == cpal::SampleFormat::I16) as u32
}); });
let config = configs let config = configs
.into_iter() .into_iter()
.next() .next()
.ok_or_else(|| anyhow!("Could not find float output config"))?; .ok_or_else(|| anyhow!("Could not find float or 16bit signed output config"))?;
let sample_rate = cpal::SampleRate(44100) let sample_rate = cpal::SampleRate(44100)
.max(config.min_sample_rate()) .max(config.min_sample_rate())
.min(config.max_sample_rate()); .min(config.max_sample_rate());
@@ -355,6 +358,7 @@ fn init_sound(
cpal::BufferSize::Fixed(256.max(min).min(max)) cpal::BufferSize::Fixed(256.max(min).min(max))
} }
}; };
let sample_format = config.sample_format();
let config = cpal::StreamConfig { let config = cpal::StreamConfig {
buffer_size, buffer_size,
..config.config() ..config.config()
@@ -384,12 +388,13 @@ fn init_sound(
}) })
}; };
dbg!(sample_format);
let mut sample_index = 0; let mut sample_index = 0;
let mut pending_updates: Vec<RegisterUpdate> = Vec::with_capacity(30); let mut pending_updates: Vec<RegisterUpdate> = Vec::with_capacity(30);
let mut current_time = 0; let mut current_time = 0;
let stream = device.build_output_stream(
&config, let mut callback = move |mut outer_buffer: &mut [f32], _: &_| {
move |mut outer_buffer: &mut [f32], _| {
let mut first_update = true; let mut first_update = true;
while let Ok(update) = rx.try_recv() { while let Ok(update) = rx.try_recv() {
if first_update { if first_update {
@@ -462,8 +467,7 @@ fn init_sound(
resampler.output_index = 0; resampler.output_index = 0;
} else { } else {
for i in 0..copy_size { for i in 0..copy_size {
buffer[i * 2] = buffer[i * 2] = resampler.output_buffers[0][resampler.output_index + i];
resampler.output_buffers[0][resampler.output_index + i];
buffer[i * 2 + 1] = buffer[i * 2 + 1] =
resampler.output_buffers[1][resampler.output_index + i]; resampler.output_buffers[1][resampler.output_index + i];
} }
@@ -479,15 +483,40 @@ fn init_sound(
} }
outer_buffer = &mut outer_buffer[step_size..]; outer_buffer = &mut outer_buffer[step_size..];
current_time = current_time = current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32);
current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32); }
};
let stream = if sample_format == cpal::SampleFormat::F32 {
device.build_output_stream(
&config,
callback,
move |err| {
dbg!(err);
},
None,
)?
} else {
device.build_output_stream(
&config,
move |mut buffer: &mut [i16], info| {
let mut float_buffer = [0f32; 256];
while !buffer.is_empty() {
let step_size = buffer.len().min(float_buffer.len());
let step_buffer = &mut float_buffer[..step_size];
callback(step_buffer, info);
for (dest, src) in buffer.iter_mut().take(step_size).zip(step_buffer.iter()) {
*dest = (src.max(-1.0).min(1.0) * 32767.0) as i16;
}
buffer = &mut buffer[step_size..];
} }
}, },
move |err| { move |err| {
dbg!(err); dbg!(err);
}, },
None, None,
)?; )?
};
Ok(Uw8Sound { stream, tx }) Ok(Uw8Sound { stream, tx })
} }