multi channel support
This commit is contained in:
parent
2ef7008615
commit
4ba291e8be
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
@ -60,11 +62,47 @@ struct DriverWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsioStream {
|
pub struct AsioStream {
|
||||||
pub buffer_infos: [AsioBufferInfo; 2],
|
pub buffer_infos: Vec<AsioBufferInfo>,
|
||||||
//driver: Driver,
|
|
||||||
pub buffer_size: i32,
|
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
|
// This is a direct copy of the ASIOSampleType
|
||||||
// inside ASIO SDK.
|
// inside ASIO SDK.
|
||||||
#[derive(Debug, FromPrimitive)]
|
#[derive(Debug, FromPrimitive)]
|
||||||
|
@ -166,12 +204,17 @@ impl Drivers {
|
||||||
// Make owned CString to send to load driver
|
// 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 mut my_driver_name = CString::new(driver_name).expect("Can't go from str to CString");
|
||||||
let raw = my_driver_name.into_raw();
|
let raw = my_driver_name.into_raw();
|
||||||
|
let mut driver_info = ai::ASIODriverInfo {
|
||||||
|
_bindgen_opaque_blob: [0u32; 43],
|
||||||
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut asio_drivers = ai::AsioDrivers::new();
|
let mut asio_drivers = ai::AsioDrivers::new();
|
||||||
let load_result = asio_drivers.loadDriver(raw);
|
let load_result = asio_drivers.loadDriver(raw);
|
||||||
|
ai::ASIOInit(&mut driver_info);
|
||||||
// Take back ownership
|
// Take back ownership
|
||||||
my_driver_name = CString::from_raw(raw);
|
my_driver_name = CString::from_raw(raw);
|
||||||
if load_result {
|
if load_result {
|
||||||
|
println!("Creating drivers");
|
||||||
*drivers = Some(DriverWrapper{drivers: asio_drivers});
|
*drivers = Some(DriverWrapper{drivers: asio_drivers});
|
||||||
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
STREAM_DRIVER_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
Ok(Drivers{})
|
Ok(Drivers{})
|
||||||
|
@ -196,13 +239,8 @@ impl Drivers {
|
||||||
// Initialize memory for calls
|
// Initialize memory for calls
|
||||||
let mut ins: c_long = 0;
|
let mut ins: c_long = 0;
|
||||||
let mut outs: c_long = 0;
|
let mut outs: c_long = 0;
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ai::ASIOInit(&mut driver_info);
|
println!("Channels result {:?}", result_to_error(ai::ASIOGetChannels(&mut ins, &mut outs)));
|
||||||
ai::ASIOGetChannels(&mut ins, &mut outs);
|
|
||||||
channel = Channel {
|
channel = Channel {
|
||||||
ins: ins as i64,
|
ins: ins as i64,
|
||||||
outs: outs as i64,
|
outs: outs as i64,
|
||||||
|
@ -217,13 +255,9 @@ impl Drivers {
|
||||||
|
|
||||||
// Initialize memory for calls
|
// Initialize memory for calls
|
||||||
let mut rate: c_double = 0.0f64;
|
let mut rate: c_double = 0.0f64;
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ai::ASIOInit(&mut driver_info);
|
println!("sample rate {:?}", result_to_error(ai::get_sample_rate(&mut rate)));
|
||||||
ai::get_sample_rate(&mut rate);
|
|
||||||
sample_rate = SampleRate { rate: rate as u32 };
|
sample_rate = SampleRate { rate: rate as u32 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,13 +276,8 @@ impl Drivers {
|
||||||
type_: 0,
|
type_: 0,
|
||||||
name: [0 as c_char; 32],
|
name: [0 as c_char; 32],
|
||||||
};
|
};
|
||||||
let mut driver_info = ai::ASIODriverInfo {
|
|
||||||
_bindgen_opaque_blob: [0u32; 43],
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ai::ASIOInit(&mut driver_info);
|
println!("data type {:?}", result_to_error(ai::ASIOGetChannelInfo(&mut channel_info)));
|
||||||
ai::ASIOGetChannelInfo(&mut channel_info);
|
|
||||||
data_type = num::FromPrimitive::from_i32(channel_info.type_)
|
data_type = num::FromPrimitive::from_i32(channel_info.type_)
|
||||||
.map_or(Err(ASIOError::TypeError), |t| Ok(t));
|
.map_or(Err(ASIOError::TypeError), |t| Ok(t));
|
||||||
}
|
}
|
||||||
|
@ -256,20 +285,14 @@ impl Drivers {
|
||||||
data_type
|
data_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_input_stream(&self) -> Result<AsioStream, ASIOError> {
|
pub fn prepare_input_stream(&self, num_channels: usize) -> Result<AsioStream, ASIOError> {
|
||||||
let mut buffer_infos = [
|
let mut buffer_infos = vec![
|
||||||
AsioBufferInfo {
|
AsioBufferInfo {
|
||||||
is_input: 1,
|
is_input: 1,
|
||||||
channel_num: 0,
|
channel_num: 0,
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
},
|
}; num_channels
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 1,
|
|
||||||
channel_num: 1,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
let num_channels = 2;
|
|
||||||
|
|
||||||
let mut callbacks = AsioCallbacks {
|
let mut callbacks = AsioCallbacks {
|
||||||
buffer_switch: buffer_switch,
|
buffer_switch: buffer_switch,
|
||||||
|
@ -283,15 +306,10 @@ impl Drivers {
|
||||||
let mut pref_b_size: c_long = 0;
|
let mut pref_b_size: c_long = 0;
|
||||||
let mut grans: 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()));
|
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
ai::ASIOGetBufferSize(
|
ai::ASIOGetBufferSize(
|
||||||
&mut min_b_size,
|
&mut min_b_size,
|
||||||
&mut max_b_size,
|
&mut max_b_size,
|
||||||
|
@ -299,23 +317,21 @@ impl Drivers {
|
||||||
&mut grans,
|
&mut grans,
|
||||||
);
|
);
|
||||||
result = if pref_b_size > 0 {
|
result = if pref_b_size > 0 {
|
||||||
let mut buffer_info_convert = [
|
let mut buffer_info_convert: Vec<ai::ASIOBufferInfo> = buffer_infos.into_iter()
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
.map(|bi| mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(bi))
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
.collect();
|
||||||
];
|
|
||||||
let mut callbacks_convert =
|
let mut callbacks_convert =
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
||||||
let buffer_result = ai::ASIOCreateBuffers(
|
let buffer_result = ai::ASIOCreateBuffers(
|
||||||
buffer_info_convert.as_mut_ptr(),
|
buffer_info_convert.as_mut_ptr(),
|
||||||
num_channels,
|
num_channels as i32,
|
||||||
pref_b_size,
|
pref_b_size,
|
||||||
&mut callbacks_convert,
|
&mut callbacks_convert,
|
||||||
);
|
);
|
||||||
if buffer_result == 0 {
|
if buffer_result == 0 {
|
||||||
let buffer_infos = [
|
let mut buffer_infos: Vec<AsioBufferInfo> = buffer_info_convert.into_iter()
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
.map(|bi| mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(bi))
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
.collect();
|
||||||
];
|
|
||||||
for d in &buffer_infos {
|
for d in &buffer_infos {
|
||||||
println!("after {:?}", d);
|
println!("after {:?}", d);
|
||||||
}
|
}
|
||||||
|
@ -342,22 +358,16 @@ impl Drivers {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the output stream
|
/// 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
|
// Initialize data for FFI
|
||||||
let mut buffer_infos = [
|
let mut buffer_infos = vec![
|
||||||
AsioBufferInfo {
|
AsioBufferInfo {
|
||||||
is_input: 0,
|
is_input: 0,
|
||||||
channel_num: 0,
|
channel_num: 0,
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
buffers: [std::ptr::null_mut(); 2],
|
||||||
},
|
}; num_channels
|
||||||
AsioBufferInfo {
|
|
||||||
is_input: 0,
|
|
||||||
channel_num: 0,
|
|
||||||
buffers: [std::ptr::null_mut(); 2],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let num_channels = 2;
|
|
||||||
let mut callbacks = AsioCallbacks {
|
let mut callbacks = AsioCallbacks {
|
||||||
buffer_switch: buffer_switch,
|
buffer_switch: buffer_switch,
|
||||||
sample_rate_did_change: sample_rate_did_change,
|
sample_rate_did_change: sample_rate_did_change,
|
||||||
|
@ -370,15 +380,9 @@ impl Drivers {
|
||||||
let mut pref_b_size: c_long = 0;
|
let mut pref_b_size: c_long = 0;
|
||||||
let mut grans: 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()));
|
let mut result = Err(ASIOError::NoResult("not implimented".to_owned()));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Initialize ASIO stream
|
|
||||||
ai::ASIOInit(&mut driver_info);
|
|
||||||
// Get the buffer sizes
|
// Get the buffer sizes
|
||||||
// min possilbe size
|
// min possilbe size
|
||||||
// max possible size
|
// max possible size
|
||||||
|
@ -391,23 +395,33 @@ impl Drivers {
|
||||||
&mut grans,
|
&mut grans,
|
||||||
);
|
);
|
||||||
result = if pref_b_size > 0 {
|
result = if pref_b_size > 0 {
|
||||||
|
/*
|
||||||
let mut buffer_info_convert = [
|
let mut buffer_info_convert = [
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[0]),
|
||||||
mem::transmute::<AsioBufferInfo, ai::ASIOBufferInfo>(buffer_infos[1]),
|
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 =
|
let mut callbacks_convert =
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
||||||
let buffer_result = ai::ASIOCreateBuffers(
|
let buffer_result = ai::ASIOCreateBuffers(
|
||||||
buffer_info_convert.as_mut_ptr(),
|
buffer_info_convert.as_mut_ptr(),
|
||||||
num_channels,
|
num_channels as i32,
|
||||||
pref_b_size,
|
pref_b_size,
|
||||||
&mut callbacks_convert,
|
&mut callbacks_convert,
|
||||||
);
|
);
|
||||||
if buffer_result == 0 {
|
if buffer_result == 0 {
|
||||||
|
/*
|
||||||
let buffer_infos = [
|
let buffer_infos = [
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[0]),
|
||||||
mem::transmute::<ai::ASIOBufferInfo, AsioBufferInfo>(buffer_info_convert[1]),
|
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 {
|
for d in &buffer_infos {
|
||||||
println!("after {:?}", d);
|
println!("after {:?}", d);
|
||||||
}
|
}
|
||||||
|
@ -541,3 +555,4 @@ pub fn stop() {
|
||||||
println!("start result: {}", result);
|
println!("start result: {}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,10 +70,10 @@ impl EventLoop {
|
||||||
drivers,
|
drivers,
|
||||||
..
|
..
|
||||||
} = device;
|
} = device;
|
||||||
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
|
||||||
match drivers.prepare_input_stream() {
|
|
||||||
Ok(stream) => {
|
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
match drivers.prepare_input_stream(num_channels as usize) {
|
||||||
|
Ok(stream) => {
|
||||||
let cpal_num_samples =
|
let cpal_num_samples =
|
||||||
(stream.buffer_size as usize) * num_channels as usize;
|
(stream.buffer_size as usize) * num_channels as usize;
|
||||||
{
|
{
|
||||||
|
@ -237,11 +237,10 @@ pub fn build_output_stream(
|
||||||
drivers,
|
drivers,
|
||||||
..
|
..
|
||||||
} = device;
|
} = device;
|
||||||
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
|
||||||
match drivers.prepare_output_stream() {
|
|
||||||
Ok(stream) => {
|
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
match drivers.prepare_output_stream(num_channels as usize) {
|
||||||
|
Ok(stream) => {
|
||||||
let cpal_num_samples =
|
let cpal_num_samples =
|
||||||
(stream.buffer_size as usize) * num_channels as usize;
|
(stream.buffer_size as usize) * num_channels as usize;
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue