multi channel support

This commit is contained in:
Tom Gowan 2018-10-19 14:05:55 +11:00 committed by mitchmindtree
parent 2ef7008615
commit 4ba291e8be
2 changed files with 77 additions and 63 deletions

View File

@ -1,3 +1,5 @@
#![allow(non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
@ -60,11 +62,47 @@ struct DriverWrapper {
}
pub struct AsioStream {
pub buffer_infos: [AsioBufferInfo; 2],
//driver: Driver,
pub buffer_infos: Vec<AsioBufferInfo>,
pub buffer_size: i32,
}
#[derive(Debug)]
enum AsioErrorConvert {
ASE_OK = 0, // This value will be returned whenever the call succeeded
ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
ASE_NotPresent = -1000, // hardware input or output is not present or available
ASE_HWMalfunction, // hardware is malfunctioning (can be returned by any ASIO function)
ASE_InvalidParameter, // input parameter invalid
ASE_InvalidMode, // hardware is in a bad mode or used in a bad mode
ASE_SPNotAdvancing, // hardware is not running when sample position is inquired
ASE_NoClock, // sample clock or rate cannot be determined or is not present
ASE_NoMemory, // not enough memory for completing the request
Invalid,
}
macro_rules! asio_error {
($x:expr, $ae:ident{ $($v:ident),+ }, $inval:ident) => {
match $x {
$(_ if $x == $ae::$v as i32 => $ae::$v,)+
_ => $ae::$inval,
}
};
}
fn result_to_error(result: i32) -> AsioErrorConvert {
asio_error!(result,
AsioErrorConvert{
ASE_OK,
ASE_SUCCESS,
ASE_NotPresent,
ASE_HWMalfunction,
ASE_InvalidParameter,
ASE_InvalidMode,
ASE_SPNotAdvancing,
ASE_NoClock,
ASE_NoMemory}, Invalid)
}
// This is a direct copy of the ASIOSampleType
// inside ASIO SDK.
#[derive(Debug, FromPrimitive)]
@ -166,12 +204,17 @@ impl Drivers {
// Make owned CString to send to load driver
let mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
let raw = my_driver_name.into_raw();
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
unsafe {
let mut asio_drivers = ai::AsioDrivers::new();
let load_result = asio_drivers.loadDriver(raw);
ai::ASIOInit(&mut driver_info);
// Take back ownership
my_driver_name = CString::from_raw(raw);
if load_result {
println!("Creating drivers");
*drivers = Some(DriverWrapper{drivers: asio_drivers});
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
Ok(Drivers{})
@ -196,13 +239,8 @@ impl Drivers {
// Initialize memory for calls
let mut ins: c_long = 0;
let mut outs: c_long = 0;
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
unsafe {
ai::ASIOInit(&mut driver_info);
ai::ASIOGetChannels(&mut ins, &mut outs);
println!("Channels result {:?}", result_to_error(ai::ASIOGetChannels(&mut ins, &mut outs)));
channel = Channel {
ins: ins as i64,
outs: outs as i64,
@ -217,13 +255,9 @@ impl Drivers {
// Initialize memory for calls
let mut rate: c_double = 0.0f64;
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
unsafe {
ai::ASIOInit(&mut driver_info);
ai::get_sample_rate(&mut rate);
println!("sample rate {:?}", result_to_error(ai::get_sample_rate(&mut rate)));
sample_rate = SampleRate { rate: rate as u32 };
}
@ -242,13 +276,8 @@ impl Drivers {
type_: 0,
name: [0 as c_char; 32],
};
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
unsafe {
ai::ASIOInit(&mut driver_info);
ai::ASIOGetChannelInfo(&mut channel_info);
println!("data type {:?}", result_to_error(ai::ASIOGetChannelInfo(&mut channel_info)));
data_type = num::FromPrimitive::from_i32(channel_info.type_)
.map_or(Err(ASIOError::TypeError), |t| Ok(t));
}
@ -256,20 +285,14 @@ impl Drivers {
data_type
}
pub fn prepare_input_stream(&self) -> Result<AsioStream, ASIOError> {
let mut buffer_infos = [
pub fn prepare_input_stream(&self, num_channels: usize) -> Result<AsioStream, ASIOError> {
let mut buffer_infos = vec![
AsioBufferInfo {
is_input: 1,
channel_num: 0,
buffers: [std::ptr::null_mut(); 2],
},
AsioBufferInfo {
is_input: 1,
channel_num: 1,
buffers: [std::ptr::null_mut(); 2],
},
}; num_channels
];
let num_channels = 2;
let mut callbacks = AsioCallbacks {
buffer_switch: buffer_switch,
@ -283,15 +306,10 @@ impl Drivers {
let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0;
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
unsafe {
ai::ASIOInit(&mut driver_info);
ai::ASIOGetBufferSize(
&mut min_b_size,
&mut max_b_size,
@ -299,23 +317,21 @@ impl Drivers {
&mut grans,
);
result = if pref_b_size > 0 {
let mut buffer_info_convert = [
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
];
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos.into_iter()
.map(|bi| mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(bi))
.collect();
let mut callbacks_convert =
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
let buffer_result = ai::ASIOCreateBuffers(
buffer_info_convert.as_mut_ptr(),
num_channels,
num_channels as i32,
pref_b_size,
&mut callbacks_convert,
);
if buffer_result == 0 {
let buffer_infos = [
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
];
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert.into_iter()
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
.collect();
for d in &buffer_infos {
println!("after {:?}", d);
}
@ -342,22 +358,16 @@ impl Drivers {
}
/// Creates the output stream
pub fn prepare_output_stream(&self) -> Result<AsioStream, ASIOError> {
pub fn prepare_output_stream(&self, num_channels: usize) -> Result<AsioStream, ASIOError> {
// Initialize data for FFI
let mut buffer_infos = [
let mut buffer_infos = vec![
AsioBufferInfo {
is_input: 0,
channel_num: 0,
buffers: [std::ptr::null_mut(); 2],
},
AsioBufferInfo {
is_input: 0,
channel_num: 0,
buffers: [std::ptr::null_mut(); 2],
},
}; num_channels
];
let num_channels = 2;
let mut callbacks = AsioCallbacks {
buffer_switch: buffer_switch,
sample_rate_did_change: sample_rate_did_change,
@ -370,15 +380,9 @@ impl Drivers {
let mut pref_b_size: c_long = 0;
let mut grans: c_long = 0;
let mut driver_info = ai::ASIODriverInfo {
_bindgen_opaque_blob: [0u32; 43],
};
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
unsafe {
// Initialize ASIO stream
ai::ASIOInit(&mut driver_info);
// Get the buffer sizes
// min possilbe size
// max possible size
@ -391,23 +395,33 @@ impl Drivers {
&mut grans,
);
result = if pref_b_size > 0 {
/*
let mut buffer_info_convert = [
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
];
*/
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos.into_iter()
.map(|bi| mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(bi))
.collect();
let mut callbacks_convert =
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
let buffer_result = ai::ASIOCreateBuffers(
buffer_info_convert.as_mut_ptr(),
num_channels,
num_channels as i32,
pref_b_size,
&mut callbacks_convert,
);
if buffer_result == 0 {
/*
let buffer_infos = [
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
];
*/
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert.into_iter()
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
.collect();
for d in &buffer_infos {
println!("after {:?}", d);
}
@ -541,3 +555,4 @@ pub fn stop() {
println!("start result: {}", result);
}
}

View File

@ -70,10 +70,10 @@ impl EventLoop {
drivers,
..
} = device;
let num_channels = format.channels.clone();
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
match drivers.prepare_input_stream() {
match drivers.prepare_input_stream(num_channels as usize) {
Ok(stream) => {
let num_channels = format.channels.clone();
let cpal_num_samples =
(stream.buffer_size as usize) * num_channels as usize;
{
@ -237,11 +237,10 @@ pub fn build_output_stream(
drivers,
..
} = device;
let num_channels = format.channels.clone();
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
match drivers.prepare_output_stream() {
match drivers.prepare_output_stream(num_channels as usize) {
Ok(stream) => {
let num_channels = format.channels.clone();
let cpal_num_samples =
(stream.buffer_size as usize) * num_channels as usize;
{