Compute device configs for cpal
This commit is contained in:
parent
ff692ee084
commit
1fc437068a
1 changed files with 95 additions and 5 deletions
|
@ -1,16 +1,20 @@
|
|||
use anyhow::{Context, Result};
|
||||
use cpal::traits::*;
|
||||
use cpal::{traits::*, Device, SampleFormat, StreamConfig};
|
||||
|
||||
use super::super::config::WrapperConfig;
|
||||
use super::Backend;
|
||||
use crate::buffer::Buffer;
|
||||
use crate::context::Transport;
|
||||
use crate::midi::NoteEvent;
|
||||
use crate::plugin::Plugin;
|
||||
use crate::plugin::{AuxiliaryIOConfig, BusConfig, Plugin};
|
||||
|
||||
/// Uses CPAL for audio and midir for MIDI.
|
||||
pub struct Cpal {
|
||||
// TODO:
|
||||
bus_config: BusConfig,
|
||||
input_device: Option<Device>,
|
||||
input_config: Option<StreamConfig>,
|
||||
output_device: Device,
|
||||
output_config: StreamConfig,
|
||||
// TODO: MIDI
|
||||
}
|
||||
|
||||
|
@ -34,7 +38,7 @@ impl Cpal {
|
|||
// No input device is connected unless requested by the user to avoid feedback loops
|
||||
let input_device = config
|
||||
.input_device
|
||||
.map(|name| -> Result<cpal::Device> {
|
||||
.map(|name| -> Result<Device> {
|
||||
let device = host
|
||||
.input_devices()
|
||||
.context("No audio input devices available")?
|
||||
|
@ -77,6 +81,92 @@ impl Cpal {
|
|||
.context("No default audio output device available")?,
|
||||
};
|
||||
|
||||
anyhow::bail!("Not yet implemented");
|
||||
let bus_config = BusConfig {
|
||||
num_input_channels: config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS),
|
||||
num_output_channels: config.output_channels.unwrap_or(P::DEFAULT_OUTPUT_CHANNELS),
|
||||
// TODO: Support these in the standalone
|
||||
aux_input_busses: AuxiliaryIOConfig::default(),
|
||||
aux_output_busses: AuxiliaryIOConfig::default(),
|
||||
};
|
||||
let requested_sample_rate = cpal::SampleRate(config.sample_rate as u32);
|
||||
let requested_buffer_size = cpal::BufferSize::Fixed(config.period_size);
|
||||
|
||||
let input_config = input_device
|
||||
.as_ref()
|
||||
.map(|device| -> Result<StreamConfig> {
|
||||
let input_configs: Vec<_> = device
|
||||
.supported_input_configs()
|
||||
.context("Could not get supported audio input configurations")?
|
||||
.filter(|c| match c.buffer_size() {
|
||||
cpal::SupportedBufferSize::Range { min, max } => {
|
||||
c.channels() as u32 == bus_config.num_input_channels
|
||||
&& (c.min_sample_rate()..=c.max_sample_rate())
|
||||
.contains(&requested_sample_rate)
|
||||
&& (min..=max).contains(&&config.period_size)
|
||||
}
|
||||
cpal::SupportedBufferSize::Unknown => false,
|
||||
})
|
||||
.collect();
|
||||
let input_config_range = input_configs
|
||||
.iter()
|
||||
// Prefer floating point samples to avoid conversions
|
||||
.find(|c| c.sample_format() == SampleFormat::F32)
|
||||
.or_else(|| input_configs.first())
|
||||
.cloned()
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"The audio input device does not support {} audio channels at a \
|
||||
sample rate of {} Hz and a period size of {} samples",
|
||||
bus_config.num_input_channels, config.sample_rate, config.period_size,
|
||||
)
|
||||
})?;
|
||||
|
||||
// We already checked that these settings are valid
|
||||
Ok(StreamConfig {
|
||||
channels: input_config_range.channels(),
|
||||
sample_rate: requested_sample_rate,
|
||||
buffer_size: requested_buffer_size.clone(),
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let output_configs: Vec<_> = output_device
|
||||
.supported_output_configs()
|
||||
.context("Could not get supported audio output configurations")?
|
||||
.filter(|c| match c.buffer_size() {
|
||||
cpal::SupportedBufferSize::Range { min, max } => {
|
||||
c.channels() as u32 == bus_config.num_output_channels
|
||||
&& (c.min_sample_rate()..=c.max_sample_rate())
|
||||
.contains(&requested_sample_rate)
|
||||
&& (min..=max).contains(&&config.period_size)
|
||||
}
|
||||
cpal::SupportedBufferSize::Unknown => false,
|
||||
})
|
||||
.collect();
|
||||
let output_config_range = output_configs
|
||||
.iter()
|
||||
.find(|c| c.sample_format() == SampleFormat::F32)
|
||||
.or_else(|| output_configs.first())
|
||||
.cloned()
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"The audio output device does not support {} audio channels at a sample rate \
|
||||
of {} Hz and a period size of {} samples",
|
||||
bus_config.num_output_channels, config.sample_rate, config.period_size,
|
||||
)
|
||||
})?;
|
||||
let output_config = StreamConfig {
|
||||
channels: output_config_range.channels(),
|
||||
sample_rate: requested_sample_rate,
|
||||
buffer_size: requested_buffer_size,
|
||||
};
|
||||
|
||||
Ok(Cpal {
|
||||
bus_config,
|
||||
input_device,
|
||||
input_config,
|
||||
output_device,
|
||||
output_config,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue