supporting multiple sample formats
This commit is contained in:
+52
-15
@@ -1,5 +1,5 @@
|
|||||||
use cpal::{
|
use cpal::{
|
||||||
Device, FromSample, SampleFormat, SizedSample, StreamConfig, SupportedStreamConfig,
|
Device, FromSample, Sample, SampleFormat, SizedSample, StreamConfig, SupportedStreamConfig,
|
||||||
traits::{DeviceTrait, StreamTrait},
|
traits::{DeviceTrait, StreamTrait},
|
||||||
};
|
};
|
||||||
use ringbuf::{
|
use ringbuf::{
|
||||||
@@ -21,16 +21,16 @@ use crate::models::{
|
|||||||
InputAudioStreamsInfo, InputAudioStreamsProducers,
|
InputAudioStreamsInfo, InputAudioStreamsProducers,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn audio_stream_receiver(
|
fn cpal_build_output_stream<T>(
|
||||||
output_device: Device,
|
output_device: &Device,
|
||||||
output_device_config: SupportedStreamConfig,
|
output_device_config: StreamConfig,
|
||||||
active_input_audio_streams_producers: InputAudioStreamsProducers,
|
|
||||||
active_input_audio_streams_consumers: InputAudioStreamsConsumers,
|
active_input_audio_streams_consumers: InputAudioStreamsConsumers,
|
||||||
active_input_audio_streams_encoders: InputAudioStreamsEncoders,
|
) -> cpal::Stream
|
||||||
active_input_audio_streams_info: InputAudioStreamsInfo,
|
where
|
||||||
udp_socket: Arc<UdpSocket>,
|
T: SizedSample,
|
||||||
) {
|
T: FromSample<f32>,
|
||||||
let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
{
|
||||||
|
let output_data_fn = move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
|
||||||
let mut streams = active_input_audio_streams_consumers.lock().unwrap();
|
let mut streams = active_input_audio_streams_consumers.lock().unwrap();
|
||||||
for sample in data {
|
for sample in data {
|
||||||
let mut mixed_value: f32 = 0.0;
|
let mut mixed_value: f32 = 0.0;
|
||||||
@@ -42,14 +42,51 @@ pub async fn audio_stream_receiver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*sample = mixed_value;
|
*sample = mixed_value.to_sample::<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let err_fn = |err| eprintln!("stream error: {}", err);
|
let err_fn = |err| eprintln!("stream error: {}", err);
|
||||||
let output_stream = output_device
|
|
||||||
.build_output_stream(output_device_config.into(), output_data_fn, err_fn, None)
|
return output_device
|
||||||
|
.build_output_stream(output_device_config, output_data_fn, err_fn, None)
|
||||||
.expect("building output stream failed");
|
.expect("building output stream failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn audio_stream_receiver(
|
||||||
|
output_device: Device,
|
||||||
|
output_device_config: SupportedStreamConfig,
|
||||||
|
active_input_audio_streams_producers: InputAudioStreamsProducers,
|
||||||
|
active_input_audio_streams_consumers: InputAudioStreamsConsumers,
|
||||||
|
active_input_audio_streams_encoders: InputAudioStreamsEncoders,
|
||||||
|
active_input_audio_streams_info: InputAudioStreamsInfo,
|
||||||
|
udp_socket: Arc<UdpSocket>,
|
||||||
|
) {
|
||||||
|
let output_stream = match output_device_config.sample_format() {
|
||||||
|
SampleFormat::F32 => cpal_build_output_stream::<f32>(
|
||||||
|
&output_device,
|
||||||
|
output_device_config.into(),
|
||||||
|
active_input_audio_streams_consumers,
|
||||||
|
),
|
||||||
|
SampleFormat::I32 => cpal_build_output_stream::<i32>(
|
||||||
|
&output_device,
|
||||||
|
output_device_config.into(),
|
||||||
|
active_input_audio_streams_consumers,
|
||||||
|
),
|
||||||
|
SampleFormat::I16 => cpal_build_output_stream::<i16>(
|
||||||
|
&output_device,
|
||||||
|
output_device_config.into(),
|
||||||
|
active_input_audio_streams_consumers,
|
||||||
|
),
|
||||||
|
SampleFormat::U16 => cpal_build_output_stream::<u16>(
|
||||||
|
&output_device,
|
||||||
|
output_device_config.into(),
|
||||||
|
active_input_audio_streams_consumers,
|
||||||
|
),
|
||||||
|
_ => {
|
||||||
|
eprintln!("unsupported output stream format :(");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
output_stream.play().expect("failed to play output stream");
|
output_stream.play().expect("failed to play output stream");
|
||||||
|
|
||||||
@@ -226,7 +263,7 @@ pub async fn audio_stream_spawner(
|
|||||||
cpal_build_input_stream::<u16>(&input_device, input_device_config.into(), producer)
|
cpal_build_input_stream::<u16>(&input_device, input_device_config.into(), producer)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("unsupported stream format :(");
|
eprintln!("unsupported input stream format :(");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-8
@@ -172,7 +172,6 @@ impl DeviceSelectScreen {
|
|||||||
if let Some(default_output_device) = host.default_output_device() {
|
if let Some(default_output_device) = host.default_output_device() {
|
||||||
if let Ok(default_config) = default_output_device.default_output_config() {
|
if let Ok(default_config) = default_output_device.default_output_config() {
|
||||||
if default_config.sample_rate() == SAMPLE_RATE_48K
|
if default_config.sample_rate() == SAMPLE_RATE_48K
|
||||||
&& default_config.sample_format() == SampleFormat::F32
|
|
||||||
&& (default_config.channels() == 1 || default_config.channels() == 2)
|
&& (default_config.channels() == 1 || default_config.channels() == 2)
|
||||||
{
|
{
|
||||||
output_devices.push((default_output_device.clone(), default_config.into()));
|
output_devices.push((default_output_device.clone(), default_config.into()));
|
||||||
@@ -182,9 +181,7 @@ impl DeviceSelectScreen {
|
|||||||
if let Some(output_config) =
|
if let Some(output_config) =
|
||||||
supported_config.try_with_sample_rate(SAMPLE_RATE_48K)
|
supported_config.try_with_sample_rate(SAMPLE_RATE_48K)
|
||||||
{
|
{
|
||||||
if output_config.sample_format() == SampleFormat::F32
|
if output_config.channels() == 1 || output_config.channels() == 2 {
|
||||||
&& (output_config.channels() == 1 || output_config.channels() == 2)
|
|
||||||
{
|
|
||||||
output_devices.push((default_output_device, output_config.into()));
|
output_devices.push((default_output_device, output_config.into()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -197,7 +194,6 @@ impl DeviceSelectScreen {
|
|||||||
for possible_output_device in possible_output_devices {
|
for possible_output_device in possible_output_devices {
|
||||||
if let Ok(default_config) = possible_output_device.default_output_config() {
|
if let Ok(default_config) = possible_output_device.default_output_config() {
|
||||||
if default_config.sample_rate() == SAMPLE_RATE_48K
|
if default_config.sample_rate() == SAMPLE_RATE_48K
|
||||||
&& default_config.sample_format() == SampleFormat::F32
|
|
||||||
&& (default_config.channels() == 1 || default_config.channels() == 2)
|
&& (default_config.channels() == 1 || default_config.channels() == 2)
|
||||||
{
|
{
|
||||||
output_devices
|
output_devices
|
||||||
@@ -210,9 +206,7 @@ impl DeviceSelectScreen {
|
|||||||
if let Some(output_config) =
|
if let Some(output_config) =
|
||||||
supported_config.try_with_sample_rate(SAMPLE_RATE_48K)
|
supported_config.try_with_sample_rate(SAMPLE_RATE_48K)
|
||||||
{
|
{
|
||||||
if output_config.sample_format() == SampleFormat::F32
|
if output_config.channels() == 1 || output_config.channels() == 2 {
|
||||||
&& (output_config.channels() == 1 || output_config.channels() == 2)
|
|
||||||
{
|
|
||||||
output_devices.push((possible_output_device, output_config.into()));
|
output_devices.push((possible_output_device, output_config.into()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user