implemented buffersizes for asio

This commit is contained in:
JoshuaBatty 2020-05-22 13:30:13 +02:00
parent 6edee6c6c2
commit 9e660da433
11 changed files with 142 additions and 65 deletions

View File

@ -19,6 +19,7 @@ pub enum AsioError {
HardwareStuck, HardwareStuck,
NoRate, NoRate,
ASE_NoMemory, ASE_NoMemory,
InvalidBufferSize,
UnknownError, UnknownError,
} }
@ -63,6 +64,7 @@ impl fmt::Display for AsioError {
"sample clock or rate cannot be determined or is not present" "sample clock or rate cannot be determined or is not present"
), ),
AsioError::ASE_NoMemory => write!(f, "not enough memory for completing the request"), AsioError::ASE_NoMemory => write!(f, "not enough memory for completing the request"),
AsioError::InvalidBufferSize => write!(f, "buffersize out of range for device"),
AsioError::UnknownError => write!(f, "Error not in SDK"), AsioError::UnknownError => write!(f, "Error not in SDK"),
} }
} }
@ -94,6 +96,7 @@ impl Error for AsioError {
AsioError::HardwareStuck => "hardware is not running when sample position is inquired", AsioError::HardwareStuck => "hardware is not running when sample position is inquired",
AsioError::NoRate => "sample clock or rate cannot be determined or is not present", AsioError::NoRate => "sample clock or rate cannot be determined or is not present",
AsioError::ASE_NoMemory => "not enough memory for completing the request", AsioError::ASE_NoMemory => "not enough memory for completing the request",
AsioError::InvalidBufferSize => "buffersize out of range for device",
AsioError::UnknownError => "Error not in SDK", AsioError::UnknownError => "Error not in SDK",
} }
} }

View File

@ -385,6 +385,14 @@ impl Driver {
Ok(channel) Ok(channel)
} }
/// Get the min and max supported buffersize of the driver.
pub fn buffersize_range(&self) -> Result<(c_long, c_long), AsioError> {
let buffer_sizes = asio_get_buffer_sizes()?;
let min = buffer_sizes.min;
let max = buffer_sizes.max;
Ok((min, max))
}
/// Get current sample rate of the driver. /// Get current sample rate of the driver.
pub fn sample_rate(&self) -> Result<c_double, AsioError> { pub fn sample_rate(&self) -> Result<c_double, AsioError> {
let mut rate: c_double = 0.0; let mut rate: c_double = 0.0;
@ -431,8 +439,10 @@ impl Driver {
/// ///
/// This will destroy any already allocated buffers. /// This will destroy any already allocated buffers.
/// ///
/// The preferred buffer size from ASIO is used. /// If buffersize is None then the preferred buffer size from ASIO is used,
fn create_buffers(&self, buffer_infos: &mut [AsioBufferInfo]) -> Result<c_long, AsioError> { /// otherwise the desired buffersize is used if the requeted size is within
/// the range of accepted buffersizes for the device.
fn create_buffers(&self, buffer_infos: &mut [AsioBufferInfo], buffer_size: Option<i32>) -> Result<c_long, AsioError> {
let num_channels = buffer_infos.len(); let num_channels = buffer_infos.len();
// To pass as ai::ASIOCallbacks // To pass as ai::ASIOCallbacks
@ -449,6 +459,17 @@ impl Driver {
); );
} }
let buffer_size = match buffer_size {
Some(v) => {
if v <= buffer_sizes.max {
v
} else {
return Err(AsioError::InvalidBufferSize)
}
},
None => buffer_sizes.pref,
};
// Ensure the driver is in the `Initialized` state. // Ensure the driver is in the `Initialized` state.
if let DriverState::Running = *state { if let DriverState::Running = *state {
state.stop()?; state.stop()?;
@ -460,23 +481,27 @@ impl Driver {
asio_result!(ai::ASIOCreateBuffers( asio_result!(ai::ASIOCreateBuffers(
buffer_infos.as_mut_ptr() as *mut _, buffer_infos.as_mut_ptr() as *mut _,
num_channels as i32, num_channels as i32,
buffer_sizes.pref, buffer_size,
&mut callbacks as *mut _ as *mut _, &mut callbacks as *mut _ as *mut _,
))?; ))?;
} }
*state = DriverState::Prepared; *state = DriverState::Prepared;
Ok(buffer_sizes.pref) Ok(buffer_size)
} }
/// Creates the streams. /// Creates the streams.
/// ///
/// `buffer_size` sets the desired buffer_size. If None is passed in, then the
/// default buffersize for the device is used.
///
/// Both input and output streams need to be created together as a single slice of /// Both input and output streams need to be created together as a single slice of
/// `ASIOBufferInfo`. /// `ASIOBufferInfo`.
fn create_streams( fn create_streams(
&self, &self,
mut input_buffer_infos: Vec<AsioBufferInfo>, mut input_buffer_infos: Vec<AsioBufferInfo>,
mut output_buffer_infos: Vec<AsioBufferInfo>, mut output_buffer_infos: Vec<AsioBufferInfo>,
buffer_size: Option<i32>,
) -> Result<AsioStreams, AsioError> { ) -> Result<AsioStreams, AsioError> {
let (input, output) = match ( let (input, output) = match (
input_buffer_infos.is_empty(), input_buffer_infos.is_empty(),
@ -489,7 +514,7 @@ impl Driver {
let mut all_buffer_infos = input_buffer_infos; let mut all_buffer_infos = input_buffer_infos;
all_buffer_infos.append(&mut output_buffer_infos); all_buffer_infos.append(&mut output_buffer_infos);
// Create the buffers. On success, split the output and input again. // Create the buffers. On success, split the output and input again.
let buffer_size = self.create_buffers(&mut all_buffer_infos)?; let buffer_size = self.create_buffers(&mut all_buffer_infos, buffer_size)?;
let output_buffer_infos = all_buffer_infos.split_off(split_point); let output_buffer_infos = all_buffer_infos.split_off(split_point);
let input_buffer_infos = all_buffer_infos; let input_buffer_infos = all_buffer_infos;
let input = Some(AsioStream { let input = Some(AsioStream {
@ -504,7 +529,7 @@ impl Driver {
} }
// Just input // Just input
(false, true) => { (false, true) => {
let buffer_size = self.create_buffers(&mut input_buffer_infos)?; let buffer_size = self.create_buffers(&mut input_buffer_infos, buffer_size)?;
let input = Some(AsioStream { let input = Some(AsioStream {
buffer_infos: input_buffer_infos, buffer_infos: input_buffer_infos,
buffer_size, buffer_size,
@ -514,7 +539,7 @@ impl Driver {
} }
// Just output // Just output
(true, false) => { (true, false) => {
let buffer_size = self.create_buffers(&mut output_buffer_infos)?; let buffer_size = self.create_buffers(&mut output_buffer_infos, buffer_size)?;
let input = None; let input = None;
let output = Some(AsioStream { let output = Some(AsioStream {
buffer_infos: output_buffer_infos, buffer_infos: output_buffer_infos,
@ -536,18 +561,22 @@ impl Driver {
/// For this reason we take the output stream if it exists. /// For this reason we take the output stream if it exists.
/// ///
/// `num_channels` is the desired number of input channels. /// `num_channels` is the desired number of input channels.
///
/// `buffer_size` sets the desired buffer_size. If None is passed in, then the
/// default buffersize for the device is used.
/// ///
/// This returns a full AsioStreams with both input and output if output was active. /// This returns a full AsioStreams with both input and output if output was active.
pub fn prepare_input_stream( pub fn prepare_input_stream(
&self, &self,
output: Option<AsioStream>, output: Option<AsioStream>,
num_channels: usize, num_channels: usize,
buffer_size: Option<i32>,
) -> Result<AsioStreams, AsioError> { ) -> Result<AsioStreams, AsioError> {
let input_buffer_infos = prepare_buffer_infos(true, num_channels); let input_buffer_infos = prepare_buffer_infos(true, num_channels);
let output_buffer_infos = output let output_buffer_infos = output
.map(|output| output.buffer_infos) .map(|output| output.buffer_infos)
.unwrap_or_else(Vec::new); .unwrap_or_else(Vec::new);
self.create_streams(input_buffer_infos, output_buffer_infos) self.create_streams(input_buffer_infos, output_buffer_infos, buffer_size)
} }
/// Prepare the output stream. /// Prepare the output stream.
@ -559,17 +588,21 @@ impl Driver {
/// ///
/// `num_channels` is the desired number of output channels. /// `num_channels` is the desired number of output channels.
/// ///
/// `buffer_size` sets the desired buffer_size. If None is passed in, then the
/// default buffersize for the device is used.
///
/// This returns a full AsioStreams with both input and output if input was active. /// This returns a full AsioStreams with both input and output if input was active.
pub fn prepare_output_stream( pub fn prepare_output_stream(
&self, &self,
input: Option<AsioStream>, input: Option<AsioStream>,
num_channels: usize, num_channels: usize,
buffer_size: Option<i32>,
) -> Result<AsioStreams, AsioError> { ) -> Result<AsioStreams, AsioError> {
let input_buffer_infos = input let input_buffer_infos = input
.map(|input| input.buffer_infos) .map(|input| input.buffer_infos)
.unwrap_or_else(Vec::new); .unwrap_or_else(Vec::new);
let output_buffer_infos = prepare_buffer_infos(false, num_channels); let output_buffer_infos = prepare_buffer_infos(false, num_channels);
self.create_streams(input_buffer_infos, output_buffer_infos) self.create_streams(input_buffer_infos, output_buffer_infos, buffer_size)
} }
/// Releases buffers allocations. /// Releases buffers allocations.

View File

@ -4,7 +4,9 @@ extern crate cpal;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
let host = cpal::default_host(); //let host = cpal::default_host();
let host =
cpal::host_from_id(cpal::platform::HostId::Asio).expect("failed to initialise ASIO host");
let device = host let device = host
.default_output_device() .default_output_device()
.expect("failed to find a default output device"); .expect("failed to find a default output device");
@ -23,6 +25,9 @@ fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyh
where where
T: cpal::Sample, T: cpal::Sample,
{ {
let mut config: cpal::StreamConfig = config.clone();
config.buffer_size = cpal::BufferSize::Fixed(256);
let sample_rate = config.sample_rate.0 as f32; let sample_rate = config.sample_rate.0 as f32;
let channels = config.channels as usize; let channels = config.channels as usize;
@ -36,7 +41,7 @@ where
let err_fn = |err| eprintln!("an error occurred on stream: {}", err); let err_fn = |err| eprintln!("an error occurred on stream: {}", err);
let stream = device.build_output_stream( let stream = device.build_output_stream(
config, &config,
move |data: &mut [T], _: &cpal::OutputCallbackInfo| { move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
write_data(data, channels, &mut next_value) write_data(data, channels, &mut next_value)
}, },

View File

@ -11,6 +11,7 @@ fn main() -> Result<(), anyhow::Error> {
for host_id in available_hosts { for host_id in available_hosts {
println!("{}", host_id.name()); println!("{}", host_id.name());
let host = cpal::host_from_id(host_id)?; let host = cpal::host_from_id(host_id)?;
let default_in = host.default_input_device().map(|e| e.name().unwrap()); let default_in = host.default_input_device().map(|e| e.name().unwrap());
let default_out = host.default_output_device().map(|e| e.name().unwrap()); let default_out = host.default_output_device().map(|e| e.name().unwrap());
println!(" Default Input Device:\n {:?}", default_in); println!(" Default Input Device:\n {:?}", default_in);

View File

@ -16,8 +16,9 @@ use ringbuf::RingBuffer;
const LATENCY_MS: f32 = 150.0; const LATENCY_MS: f32 = 150.0;
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
let host = cpal::default_host(); //let host = cpal::default_host();
let host =
cpal::host_from_id(cpal::platform::HostId::Asio).expect("failed to initialise ASIO host");
// Default devices. // Default devices.
let input_device = host let input_device = host
.default_input_device() .default_input_device()
@ -30,8 +31,8 @@ fn main() -> Result<(), anyhow::Error> {
// We'll try and use the same configuration between streams to keep it simple. // We'll try and use the same configuration between streams to keep it simple.
let mut config: cpal::StreamConfig = input_device.default_input_config()?.into(); let mut config: cpal::StreamConfig = input_device.default_input_config()?.into();
config.buffer_size = cpal::BufferSize::Fixed(1024); //config.buffer_size = cpal::BufferSize::Fixed(1024);
// Create a delay in case the input and output devices aren't synced. // Create a delay in case the input and output devices aren't synced.
let latency_frames = (LATENCY_MS / 1_000.0) * config.sample_rate.0 as f32; let latency_frames = (LATENCY_MS / 1_000.0) * config.sample_rate.0 as f32;
let latency_samples = latency_frames as usize * config.channels as usize; let latency_samples = latency_frames as usize * config.channels as usize;
@ -44,10 +45,10 @@ fn main() -> Result<(), anyhow::Error> {
for _ in 0..latency_samples { for _ in 0..latency_samples {
// The ring buffer has twice as much space as necessary to add latency here, // The ring buffer has twice as much space as necessary to add latency here,
// so this should never fail // so this should never fail
producer.push(0.0).unwrap(); producer.push(0).unwrap();
} }
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| { let input_data_fn = move |data: &[i16], _: &cpal::InputCallbackInfo| {
println!("data len = {}", data.len()); println!("data len = {}", data.len());
let mut output_fell_behind = false; let mut output_fell_behind = false;
for &sample in data { for &sample in data {
@ -60,14 +61,14 @@ fn main() -> Result<(), anyhow::Error> {
} }
}; };
let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { let output_data_fn = move |data: &mut [i16], _: &cpal::OutputCallbackInfo| {
let mut input_fell_behind = None; let mut input_fell_behind = None;
for sample in data { for sample in data {
*sample = match consumer.pop() { *sample = match consumer.pop() {
Ok(s) => s, Ok(s) => s,
Err(err) => { Err(err) => {
input_fell_behind = Some(err); input_fell_behind = Some(err);
0.0 0
} }
}; };
} }

View File

@ -3,10 +3,11 @@ extern crate libc;
use self::alsa::poll::Descriptors; use self::alsa::poll::Descriptors;
use crate::{ use crate::{
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError, BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data,
BufferSize, DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError, DefaultStreamConfigError, DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo,
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange, PauseStreamError, PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError,
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, SupportedBufferSizeRange, SupportedStreamConfig, SupportedStreamConfigRange,
SupportedStreamConfigsError,
}; };
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;

View File

@ -12,6 +12,7 @@ use DeviceNameError;
use DevicesError; use DevicesError;
use SampleFormat; use SampleFormat;
use SampleRate; use SampleRate;
use SupportedBufferSizeRange;
use SupportedStreamConfig; use SupportedStreamConfig;
use SupportedStreamConfigRange; use SupportedStreamConfigRange;
use SupportedStreamConfigsError; use SupportedStreamConfigsError;
@ -77,9 +78,13 @@ impl Device {
continue; continue;
} }
for channels in 1..f.channels + 1 { for channels in 1..f.channels + 1 {
f.channels = channels; supported_configs.push(SupportedStreamConfigRange {
f.sample_rate = rate; channels,
supported_configs.push(SupportedStreamConfigRange::from(f.clone())); min_sample_rate: rate,
max_sample_rate: rate,
buffer_size: f.buffer_size.clone(),
sample_format: f.sample_format.clone(),
})
} }
} }
Ok(supported_configs.into_iter()) Ok(supported_configs.into_iter())
@ -110,9 +115,13 @@ impl Device {
continue; continue;
} }
for channels in 1..f.channels + 1 { for channels in 1..f.channels + 1 {
f.channels = channels; supported_configs.push(SupportedStreamConfigRange {
f.sample_rate = rate; channels,
supported_configs.push(SupportedStreamConfigRange::from(f.clone())); min_sample_rate: rate,
max_sample_rate: rate,
buffer_size: f.buffer_size.clone(),
sample_format: f.sample_format.clone(),
})
} }
} }
Ok(supported_configs.into_iter()) Ok(supported_configs.into_iter())
@ -122,6 +131,12 @@ impl Device {
pub fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> { pub fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
let channels = self.driver.channels().map_err(default_config_err)?.ins as u16; let channels = self.driver.channels().map_err(default_config_err)?.ins as u16;
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _); let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _);
let (min, max) = self.driver.buffersize_range().map_err(default_config_err)?;
let buffer_size = SupportedBufferSizeRange {
min: min as u32,
max: max as u32,
requires_power_of_two: false,
};
// Map th ASIO sample type to a CPAL sample type // Map th ASIO sample type to a CPAL sample type
let data_type = self.driver.input_data_type().map_err(default_config_err)?; let data_type = self.driver.input_data_type().map_err(default_config_err)?;
let sample_format = convert_data_type(&data_type) let sample_format = convert_data_type(&data_type)
@ -129,6 +144,7 @@ impl Device {
Ok(SupportedStreamConfig { Ok(SupportedStreamConfig {
channels, channels,
sample_rate, sample_rate,
buffer_size,
sample_format, sample_format,
}) })
} }
@ -137,12 +153,19 @@ impl Device {
pub fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> { pub fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
let channels = self.driver.channels().map_err(default_config_err)?.outs as u16; let channels = self.driver.channels().map_err(default_config_err)?.outs as u16;
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _); let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_config_err)? as _);
let (min, max) = self.driver.buffersize_range().map_err(default_config_err)?;
let buffer_size = SupportedBufferSizeRange {
min: min as u32,
max: max as u32,
requires_power_of_two: false,
};
let data_type = self.driver.output_data_type().map_err(default_config_err)?; let data_type = self.driver.output_data_type().map_err(default_config_err)?;
let sample_format = convert_data_type(&data_type) let sample_format = convert_data_type(&data_type)
.ok_or(DefaultStreamConfigError::StreamTypeNotSupported)?; .ok_or(DefaultStreamConfigError::StreamTypeNotSupported)?;
Ok(SupportedStreamConfig { Ok(SupportedStreamConfig {
channels, channels,
sample_rate, sample_rate,
buffer_size,
sample_format, sample_format,
}) })
} }

View File

@ -5,9 +5,9 @@ use self::num_traits::PrimInt;
use super::parking_lot::Mutex; use super::parking_lot::Mutex;
use super::Device; use super::Device;
use crate::{ use crate::{
BackendSpecificError, BuildStreamError, Data, InputCallbackInfo, OutputCallbackInfo, BackendSpecificError, BufferSize, BuildStreamError, Data, InputCallbackInfo,
PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError, OutputCallbackInfo, PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig,
SupportedStreamConfig, StreamError,
}; };
use std; use std;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
@ -482,6 +482,12 @@ impl Device {
}?; }?;
let num_channels = config.channels as usize; let num_channels = config.channels as usize;
let ref mut streams = *self.asio_streams.lock(); let ref mut streams = *self.asio_streams.lock();
let buffer_size = match config.buffer_size {
BufferSize::Fixed(v) => Some(v as i32),
BufferSize::Default => None,
};
// Either create a stream if thers none or had back the // Either create a stream if thers none or had back the
// size of the current one. // size of the current one.
match streams.input { match streams.input {
@ -489,7 +495,7 @@ impl Device {
None => { None => {
let output = streams.output.take(); let output = streams.output.take();
self.driver self.driver
.prepare_input_stream(output, num_channels) .prepare_input_stream(output, num_channels, buffer_size)
.map(|new_streams| { .map(|new_streams| {
let bs = match new_streams.input { let bs = match new_streams.input {
Some(ref inp) => inp.buffer_size as usize, Some(ref inp) => inp.buffer_size as usize,
@ -523,6 +529,12 @@ impl Device {
}?; }?;
let num_channels = config.channels as usize; let num_channels = config.channels as usize;
let ref mut streams = *self.asio_streams.lock(); let ref mut streams = *self.asio_streams.lock();
let buffer_size = match config.buffer_size {
BufferSize::Fixed(v) => Some(v as i32),
BufferSize::Default => None,
};
// Either create a stream if thers none or had back the // Either create a stream if thers none or had back the
// size of the current one. // size of the current one.
match streams.output { match streams.output {
@ -530,7 +542,7 @@ impl Device {
None => { None => {
let output = streams.output.take(); let output = streams.output.take();
self.driver self.driver
.prepare_output_stream(output, num_channels) .prepare_output_stream(output, num_channels, buffer_size)
.map(|new_streams| { .map(|new_streams| {
let bs = match new_streams.output { let bs = match new_streams.output {
Some(ref out) => out.buffer_size as usize, Some(ref out) => out.buffer_size as usize,
@ -645,6 +657,7 @@ fn check_config(
let StreamConfig { let StreamConfig {
channels, channels,
sample_rate, sample_rate,
buffer_size,
} = config; } = config;
// Try and set the sample rate to what the user selected. // Try and set the sample rate to what the user selected.
let sample_rate = sample_rate.0.into(); let sample_rate = sample_rate.0.into();

View File

@ -5,9 +5,10 @@ use self::core_foundation_sys::string::{CFStringGetCString, CFStringGetCStringPt
use self::coreaudio::audio_unit::render_callback::{self, data}; use self::coreaudio::audio_unit::render_callback::{self, data};
use self::coreaudio::audio_unit::{AudioUnit, Element, Scope}; use self::coreaudio::audio_unit::{AudioUnit, Element, Scope};
use self::coreaudio::sys::{ use self::coreaudio::sys::{
kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyBufferFrameSize, kAudioDevicePropertyBufferFrameSizeRange,kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyDeviceNameCFString,
kAudioDevicePropertyScopeOutput, kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyStreamFormat, kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput,
kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyStreamFormat,
kAudioFormatFlagIsFloat, kAudioFormatFlagIsPacked, kAudioFormatLinearPCM, kAudioFormatFlagIsFloat, kAudioFormatFlagIsPacked, kAudioFormatLinearPCM,
kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput, kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput,
@ -20,10 +21,11 @@ use self::coreaudio::sys::{
}; };
use crate::traits::{DeviceTrait, HostTrait, StreamTrait}; use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
use crate::{ use crate::{
BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError, BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data,
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError, DefaultStreamConfigError, DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo,
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange, PauseStreamError, PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError,
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, SupportedBufferSizeRange, SupportedStreamConfig, SupportedStreamConfigRange,
SupportedStreamConfigsError,
}; };
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::CStr; use std::ffi::CStr;
@ -667,16 +669,14 @@ impl Device {
let asbd = asbd_from_config(config, sample_format); let asbd = asbd_from_config(config, sample_format);
audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?; audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
// Set the buffersize // Set the buffersize
match config.buffer_size { match config.buffer_size {
BufferSize::Fixed(v) => { BufferSize::Fixed(v) => audio_unit.set_property(
audio_unit.set_property( kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyBufferFrameSize, scope,
scope, element,
element, Some(&v),
Some(&v), )?,
)?
},
BufferSize::Default => (), BufferSize::Default => (),
} }
@ -751,16 +751,14 @@ impl Device {
let asbd = asbd_from_config(config, sample_format); let asbd = asbd_from_config(config, sample_format);
audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?; audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
// Set the buffersize // Set the buffersize
match config.buffer_size { match config.buffer_size {
BufferSize::Fixed(v) => { BufferSize::Fixed(v) => audio_unit.set_property(
audio_unit.set_property( kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyBufferFrameSize, scope,
scope, element,
element, Some(&v),
Some(&v), )?,
)?
},
BufferSize::Default => (), BufferSize::Default => (),
} }
@ -900,4 +898,4 @@ fn get_io_buffer_frame_size_range(
max: buffer_size_range.mMaximum as u32, max: buffer_size_range.mMaximum as u32,
requires_power_of_two: false, requires_power_of_two: false,
}) })
} }

View File

@ -319,6 +319,7 @@ unsafe fn format_from_waveformatex_ptr(
_ => return None, _ => return None,
}; };
let format = SupportedStreamConfig { let format = SupportedStreamConfig {
buffer_size: unimplemented!(),
channels: (*waveformatex_ptr).nChannels as _, channels: (*waveformatex_ptr).nChannels as _,
sample_rate: SampleRate((*waveformatex_ptr).nSamplesPerSec), sample_rate: SampleRate((*waveformatex_ptr).nSamplesPerSec),
sample_format, sample_format,
@ -526,7 +527,8 @@ impl Device {
let mut supported_formats = Vec::with_capacity(supported_sample_rates.len()); let mut supported_formats = Vec::with_capacity(supported_sample_rates.len());
for rate in supported_sample_rates { for rate in supported_sample_rates {
format.sample_rate = SampleRate(rate as _); format.sample_rate = SampleRate(rate as _);
supported_formats.push(SupportedStreamConfigRange::from(format.clone())); unimplemented!();
//supported_formats.push(SupportedStreamConfigRange::from(format.clone()));
} }
Ok(supported_formats.into_iter()) Ok(supported_formats.into_iter())
} }

View File

@ -531,10 +531,7 @@ impl SupportedStreamConfigRange {
/// ///
/// **panic!**s if the given `sample_rate` is outside the range specified within this /// **panic!**s if the given `sample_rate` is outside the range specified within this
/// `SupportedStreamConfigRange` instance. /// `SupportedStreamConfigRange` instance.
pub fn with_sample_rate( pub fn with_sample_rate(self, sample_rate: SampleRate) -> SupportedStreamConfig {
self,
sample_rate: SampleRate,
) -> SupportedStreamConfig {
assert!(self.min_sample_rate <= sample_rate && sample_rate <= self.max_sample_rate); assert!(self.min_sample_rate <= sample_rate && sample_rate <= self.max_sample_rate);
SupportedStreamConfig { SupportedStreamConfig {
channels: self.channels, channels: self.channels,