fixes, remove transmute
This commit is contained in:
parent
7950045240
commit
ab3b76ad75
|
@ -5,7 +5,6 @@ pub mod errors;
|
||||||
use self::errors::{AsioDriverError, AsioError, AsioErrorWrapper};
|
use self::errors::{AsioDriverError, AsioError, AsioErrorWrapper};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
|
||||||
use std::os::raw::{c_char, c_double, c_long, c_void};
|
use std::os::raw::{c_char, c_double, c_long, c_void};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use std::sync::{Mutex, MutexGuard};
|
||||||
|
@ -478,15 +477,17 @@ impl Drivers {
|
||||||
/// buffers.
|
/// buffers.
|
||||||
/// The prefered buffer size from ASIO is used.
|
/// The prefered buffer size from ASIO is used.
|
||||||
fn create_buffers(
|
fn create_buffers(
|
||||||
&self, buffer_infos: Vec<AsioBufferInfo>,
|
&self, mut buffer_infos: Vec<AsioBufferInfo>,
|
||||||
) -> Result<(Vec<AsioBufferInfo>, c_long), AsioDriverError> {
|
) -> Result<(Vec<AsioBufferInfo>, c_long), AsioDriverError> {
|
||||||
let num_channels = buffer_infos.len();
|
let num_channels = buffer_infos.len();
|
||||||
let 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,
|
||||||
asio_message: asio_message,
|
asio_message: asio_message,
|
||||||
buffer_switch_time_info: buffer_switch_time_info,
|
buffer_switch_time_info: buffer_switch_time_info,
|
||||||
};
|
};
|
||||||
|
// To pass as ai::ASIOCallbacks
|
||||||
|
let callbacks: *mut _ = &mut callbacks;
|
||||||
|
|
||||||
let mut min_b_size: c_long = 0;
|
let mut min_b_size: c_long = 0;
|
||||||
let mut max_b_size: c_long = 0;
|
let mut max_b_size: c_long = 0;
|
||||||
|
@ -509,22 +510,14 @@ impl Drivers {
|
||||||
&mut grans,
|
&mut grans,
|
||||||
).expect("Failed getting buffers");
|
).expect("Failed getting buffers");
|
||||||
if pref_b_size > 0 {
|
if pref_b_size > 0 {
|
||||||
// Convert Rust structs to opaque ASIO structs
|
|
||||||
let mut buffer_info_convert =
|
|
||||||
mem::transmute::<Vec<AsioBufferInfo>, Vec<ai::ASIOBufferInfo>>(buffer_infos);
|
|
||||||
let mut callbacks_convert =
|
|
||||||
mem::transmute::<AsioCallbacks, ai::ASIOCallbacks>(callbacks);
|
|
||||||
drivers
|
drivers
|
||||||
.asio_create_buffers(
|
.asio_create_buffers(
|
||||||
buffer_info_convert.as_mut_ptr(),
|
//buffer_info_convert.as_mut_ptr(),
|
||||||
|
buffer_infos.as_mut_ptr() as *mut _,
|
||||||
num_channels as i32,
|
num_channels as i32,
|
||||||
pref_b_size,
|
pref_b_size,
|
||||||
&mut callbacks_convert,
|
callbacks as *mut _,
|
||||||
).map(|_| {
|
).map(|_| {
|
||||||
let buffer_infos = mem::transmute::<
|
|
||||||
Vec<ai::ASIOBufferInfo>,
|
|
||||||
Vec<AsioBufferInfo>,
|
|
||||||
>(buffer_info_convert);
|
|
||||||
(buffer_infos, pref_b_size)
|
(buffer_infos, pref_b_size)
|
||||||
}).map_err(|e| {
|
}).map_err(|e| {
|
||||||
AsioDriverError::BufferError(format!(
|
AsioDriverError::BufferError(format!(
|
||||||
|
@ -616,18 +609,14 @@ pub fn clean_up() {
|
||||||
/// Starts input and output streams playing
|
/// Starts input and output streams playing
|
||||||
pub fn play() {
|
pub fn play() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO handle result instead of printing
|
get_drivers().asio_start().expect("Failed to start asio playing");
|
||||||
let result = get_drivers().asio_start();
|
|
||||||
println!("start result: {:?}", result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stops input and output streams playing
|
/// Stops input and output streams playing
|
||||||
pub fn stop() {
|
pub fn stop() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO handle result instead of printing
|
get_drivers().asio_stop().expect("Failed to stop asio");
|
||||||
let result = get_drivers().asio_stop();
|
|
||||||
println!("stop result: {:?}", result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +632,7 @@ impl AsioWrapper {
|
||||||
/// Load the driver.
|
/// Load the driver.
|
||||||
/// Unloads the previous driver.
|
/// Unloads the previous driver.
|
||||||
/// Sets state to Loaded on success.
|
/// Sets state to Loaded on success.
|
||||||
unsafe fn load(&mut self, raw: *mut i8) -> bool {
|
unsafe fn load(&mut self, raw: *mut c_char) -> bool {
|
||||||
use self::AsioState::*;
|
use self::AsioState::*;
|
||||||
self.clean_up();
|
self.clean_up();
|
||||||
if ai::load_asio_driver(raw) {
|
if ai::load_asio_driver(raw) {
|
||||||
|
@ -752,7 +741,7 @@ impl AsioWrapper {
|
||||||
/// will be destoryed.
|
/// will be destoryed.
|
||||||
unsafe fn asio_create_buffers(
|
unsafe fn asio_create_buffers(
|
||||||
&mut self, buffer_info_convert: *mut ai::ASIOBufferInfo, num_channels: i32,
|
&mut self, buffer_info_convert: *mut ai::ASIOBufferInfo, num_channels: i32,
|
||||||
pref_b_size: c_long, callbacks_convert: &mut ai::ASIOCallbacks,
|
pref_b_size: c_long, callbacks_convert: *mut ai::ASIOCallbacks,
|
||||||
) -> Result<(), AsioError> {
|
) -> Result<(), AsioError> {
|
||||||
use self::AsioState::*;
|
use self::AsioState::*;
|
||||||
match self.state {
|
match self.state {
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
|
/// The cpal::os module provides operating-system-specific
|
||||||
|
/// functionality. If you are using this module within a
|
||||||
|
/// cross-platform project, you may wish to use
|
||||||
|
/// cfg(target_os = "<os_name>") to ensure that you only
|
||||||
|
/// use the OS-specific items when compiling for that OS.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/// This allows you to choose either Wasapi or ASIO
|
||||||
|
/// as your back end. Wasapi is the default.
|
||||||
|
/// The CPAL_ASIO_DIR must be set to the ASIO SDK
|
||||||
|
/// directory for use_asio_backend to be available.
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -6,22 +10,23 @@ pub enum BackEnd {
|
||||||
Asio,
|
Asio,
|
||||||
}
|
}
|
||||||
|
|
||||||
//static BACKEND: BackEnd = BackEnd::Asio;
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref BACK_END: Mutex<BackEnd> = Mutex::new(BackEnd::Wasapi);
|
static ref BACK_END: Mutex<BackEnd> = Mutex::new(BackEnd::Wasapi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See which beackend is currently set.
|
||||||
pub fn which_backend() -> BackEnd {
|
pub fn which_backend() -> BackEnd {
|
||||||
(*BACK_END.lock().unwrap()).clone()
|
(*BACK_END.lock().unwrap()).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(asio)]
|
#[cfg(asio)]
|
||||||
|
/// Choose ASIO as the backend
|
||||||
pub fn use_asio_backend() -> Result<(), BackEndError> {
|
pub fn use_asio_backend() -> Result<(), BackEndError> {
|
||||||
*BACK_END.lock().unwrap() = BackEnd::Asio;
|
*BACK_END.lock().unwrap() = BackEnd::Asio;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Choose Wasapi as the backend
|
||||||
pub fn use_wasapi_backend() -> Result<(), BackEndError> {
|
pub fn use_wasapi_backend() -> Result<(), BackEndError> {
|
||||||
*BACK_END.lock().unwrap() = BackEnd::Wasapi;
|
*BACK_END.lock().unwrap() = BackEnd::Wasapi;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -15,6 +15,10 @@ pub fn interleave<T>(channels: &[Vec<T>], target: &mut Vec<T>)
|
||||||
where
|
where
|
||||||
T: Copy,
|
T: Copy,
|
||||||
{
|
{
|
||||||
|
assert!(
|
||||||
|
target.len() % channels.len() == 0,
|
||||||
|
"the length of the interleaved buffer must be a multiple of the expected number of channels"
|
||||||
|
);
|
||||||
assert!(!channels.is_empty());
|
assert!(!channels.is_empty());
|
||||||
target.clear();
|
target.clear();
|
||||||
let frames = channels[0].len();
|
let frames = channels[0].len();
|
||||||
|
@ -32,6 +36,10 @@ pub fn deinterleave<T>(cpal_buffer: &[T], asio_channels: &mut [Vec<T>])
|
||||||
where
|
where
|
||||||
T: Copy,
|
T: Copy,
|
||||||
{
|
{
|
||||||
|
assert!(
|
||||||
|
cpal_buffer.len() % asio_channels.len() == 0,
|
||||||
|
"the length of the interleaved buffer must be a multiple of the expected number of channels"
|
||||||
|
);
|
||||||
for ch in asio_channels.iter_mut() {
|
for ch in asio_channels.iter_mut() {
|
||||||
ch.clear();
|
ch.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{deinterleave, deinterleave_index, interleave};
|
use super::{deinterleave, interleave};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn interleave_two() {
|
fn interleave_two() {
|
||||||
|
@ -6,7 +6,7 @@ fn interleave_two() {
|
||||||
let goal = vec![1, 2, 1, 2, 1, 2, 1, 2];
|
let goal = vec![1, 2, 1, 2, 1, 2, 1, 2];
|
||||||
let mut result = vec![0; 8];
|
let mut result = vec![0; 8];
|
||||||
|
|
||||||
interleave(&a[..], &mut result[..]);
|
interleave(&a[..], &mut result);
|
||||||
|
|
||||||
assert_eq!(goal, result);
|
assert_eq!(goal, result);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ fn interleave_three() {
|
||||||
let goal = vec![1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3];
|
let goal = vec![1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||||
let mut result = vec![0; 12];
|
let mut result = vec![0; 12];
|
||||||
|
|
||||||
interleave(&a[..], &mut result[..]);
|
interleave(&a[..], &mut result);
|
||||||
|
|
||||||
assert_eq!(goal, result);
|
assert_eq!(goal, result);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ fn interleave_none() {
|
||||||
let goal = Vec::<i32>::new();
|
let goal = Vec::<i32>::new();
|
||||||
let mut result = Vec::<i32>::new();
|
let mut result = Vec::<i32>::new();
|
||||||
|
|
||||||
interleave(&a[..], &mut result[..]);
|
interleave(&a[..], &mut result);
|
||||||
|
|
||||||
assert_eq!(goal, result);
|
assert_eq!(goal, result);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ fn interleave_two_diff() {
|
||||||
let goal = vec![1, 5, 2, 6, 3, 7, 4, 8];
|
let goal = vec![1, 5, 2, 6, 3, 7, 4, 8];
|
||||||
let mut result = vec![0; 8];
|
let mut result = vec![0; 8];
|
||||||
|
|
||||||
interleave(&a[..], &mut result[..]);
|
interleave(&a[..], &mut result);
|
||||||
|
|
||||||
assert_eq!(goal, result);
|
assert_eq!(goal, result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,14 @@ use std;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
use CreationError;
|
use CreationError;
|
||||||
use Format;
|
use Format;
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use StreamData;
|
use StreamData;
|
||||||
use UnknownTypeInputBuffer;
|
use UnknownTypeInputBuffer;
|
||||||
use UnknownTypeOutputBuffer;
|
use UnknownTypeOutputBuffer;
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
/// Controls all streams
|
/// Controls all streams
|
||||||
pub struct EventLoop {
|
pub struct EventLoop {
|
||||||
|
@ -26,8 +26,7 @@ pub struct EventLoop {
|
||||||
/// Total stream count
|
/// Total stream count
|
||||||
stream_count: AtomicUsize,
|
stream_count: AtomicUsize,
|
||||||
/// The CPAL callback that the user gives to fill the buffers.
|
/// The CPAL callback that the user gives to fill the buffers.
|
||||||
/// TODO This should probably not be in a Vec as there can only be one
|
callbacks: Arc<Mutex<Option<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
||||||
callbacks: Arc<Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Id for each stream.
|
/// Id for each stream.
|
||||||
|
@ -85,7 +84,7 @@ impl EventLoop {
|
||||||
// This is why the Id's count from one not zero
|
// This is why the Id's count from one not zero
|
||||||
// because at this point there is no streams
|
// because at this point there is no streams
|
||||||
stream_count: AtomicUsize::new(0),
|
stream_count: AtomicUsize::new(0),
|
||||||
callbacks: Arc::new(Mutex::new(Vec::new())),
|
callbacks: Arc::new(Mutex::new(None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +92,9 @@ impl EventLoop {
|
||||||
/// If there is no ASIO Input Stream
|
/// If there is no ASIO Input Stream
|
||||||
/// it will be created.
|
/// it will be created.
|
||||||
fn get_input_stream(
|
fn get_input_stream(
|
||||||
&self, drivers: &sys::Drivers, format: &Format,
|
&self,
|
||||||
|
drivers: &sys::Drivers,
|
||||||
|
format: &Format,
|
||||||
) -> Result<usize, CreationError> {
|
) -> Result<usize, CreationError> {
|
||||||
let Format {
|
let Format {
|
||||||
channels,
|
channels,
|
||||||
|
@ -111,7 +112,7 @@ impl EventLoop {
|
||||||
.set_sample_rate(sample_rate)
|
.set_sample_rate(sample_rate)
|
||||||
.expect("Unsupported sample rate");
|
.expect("Unsupported sample rate");
|
||||||
} else {
|
} else {
|
||||||
panic!("This sample rate {:?} is not supported", sample_rate);
|
return Err(CreationError::FormatNotSupported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Either create a stream if thers none or had back the
|
// Either create a stream if thers none or had back the
|
||||||
|
@ -133,7 +134,7 @@ impl EventLoop {
|
||||||
println!("Error preparing stream: {}", e);
|
println!("Error preparing stream: {}", e);
|
||||||
CreationError::DeviceNotAvailable
|
CreationError::DeviceNotAvailable
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +142,9 @@ impl EventLoop {
|
||||||
/// If there is no ASIO Output Stream
|
/// If there is no ASIO Output Stream
|
||||||
/// it will be created.
|
/// it will be created.
|
||||||
fn get_output_stream(
|
fn get_output_stream(
|
||||||
&self, drivers: &sys::Drivers, format: &Format,
|
&self,
|
||||||
|
drivers: &sys::Drivers,
|
||||||
|
format: &Format,
|
||||||
) -> Result<usize, CreationError> {
|
) -> Result<usize, CreationError> {
|
||||||
let Format {
|
let Format {
|
||||||
channels,
|
channels,
|
||||||
|
@ -182,13 +185,15 @@ impl EventLoop {
|
||||||
println!("Error preparing stream: {}", e);
|
println!("Error preparing stream: {}", e);
|
||||||
CreationError::DeviceNotAvailable
|
CreationError::DeviceNotAvailable
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a new cpal input stream
|
/// Builds a new cpal input stream
|
||||||
pub fn build_input_stream(
|
pub fn build_input_stream(
|
||||||
&self, device: &Device, format: &Format,
|
&self,
|
||||||
|
device: &Device,
|
||||||
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, CreationError> {
|
||||||
let Device { drivers, .. } = device;
|
let Device { drivers, .. } = device;
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
|
@ -212,7 +217,7 @@ impl EventLoop {
|
||||||
SampleFormat::I16 => Buffers {
|
SampleFormat::I16 => Buffers {
|
||||||
i16_buff: I16Buffer {
|
i16_buff: I16Buffer {
|
||||||
cpal: vec![0 as i16; cpal_num_samples],
|
cpal: vec![0 as i16; cpal_num_samples],
|
||||||
channel: (0 .. num_channels)
|
channel: (0..num_channels)
|
||||||
.map(|_| Vec::with_capacity(channel_len))
|
.map(|_| Vec::with_capacity(channel_len))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
|
@ -222,7 +227,7 @@ impl EventLoop {
|
||||||
i16_buff: I16Buffer::default(),
|
i16_buff: I16Buffer::default(),
|
||||||
f32_buff: F32Buffer {
|
f32_buff: F32Buffer {
|
||||||
cpal: vec![0 as f32; cpal_num_samples],
|
cpal: vec![0 as f32; cpal_num_samples],
|
||||||
channel: (0 .. num_channels)
|
channel: (0..num_channels)
|
||||||
.map(|_| Vec::with_capacity(channel_len))
|
.map(|_| Vec::with_capacity(channel_len))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
|
@ -253,27 +258,35 @@ impl EventLoop {
|
||||||
|
|
||||||
// Theres only a single callback because theres only one event loop
|
// Theres only a single callback because theres only one event loop
|
||||||
// TODO is 64bit necessary. Might be using more memory then needed
|
// TODO is 64bit necessary. Might be using more memory then needed
|
||||||
match callbacks.first_mut() {
|
match callbacks.as_mut() {
|
||||||
Some(callback) => {
|
Some(callback) => {
|
||||||
// Macro to convert sample from ASIO to CPAL type
|
// Macro to convert sample from ASIO to CPAL type
|
||||||
macro_rules! convert_sample {
|
macro_rules! convert_sample {
|
||||||
// Unsigned types required different conversion
|
// floats types required different conversion
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
u16,
|
f32,
|
||||||
$SampleTypeIdent:ident,
|
$SampleTypeIdent:ident,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
((*$Sample as f64 + $AsioTypeIdent::MAX as f64)
|
(*$Sample as f64
|
||||||
/ (::std::u16::MAX as f64
|
/ ::std::$SampleTypeIdent::MAX as f64) as f32
|
||||||
/ ::std::AsioTypeIdent::MAX as f64)) as u16
|
};
|
||||||
|
($AsioTypeIdent:ident,
|
||||||
|
f64,
|
||||||
|
$SampleTypeIdent:ident,
|
||||||
|
$Sample:expr
|
||||||
|
) => {
|
||||||
|
*$Sample as f64
|
||||||
|
/ ::std::$SampleTypeIdent::MAX as f64
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
$SampleType:ty,
|
$SampleType:ty,
|
||||||
$SampleTypeIdent:ident,
|
$SampleTypeIdent:ident,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
(*$Sample as i64 * ::std::$SampleTypeIdent::MAX as i64
|
(*$Sample as i64 * ::std::$SampleTypeIdent::MAX as i64
|
||||||
/ ::std::$AsioTypeIdent::MAX as i64) as $SampleType
|
/ ::std::$AsioTypeIdent::MAX as i64)
|
||||||
|
as $SampleType
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
// This creates gets the buffer and interleaves it.
|
// This creates gets the buffer and interleaves it.
|
||||||
|
@ -293,7 +306,8 @@ impl EventLoop {
|
||||||
// For each channel write the asio buffer to
|
// For each channel write the asio buffer to
|
||||||
// the cpal buffer
|
// the cpal buffer
|
||||||
|
|
||||||
for (i, channel) in $Buffers.channel.iter_mut().enumerate()
|
for (i, channel) in
|
||||||
|
$Buffers.channel.iter_mut().enumerate()
|
||||||
{
|
{
|
||||||
let buff_ptr = asio_stream.buffer_infos[i].buffers
|
let buff_ptr = asio_stream.buffer_infos[i].buffers
|
||||||
[index as usize]
|
[index as usize]
|
||||||
|
@ -340,7 +354,9 @@ impl EventLoop {
|
||||||
buffer: UnknownTypeInputBuffer::$SampleFormat(
|
buffer: UnknownTypeInputBuffer::$SampleFormat(
|
||||||
::InputBuffer {
|
::InputBuffer {
|
||||||
buffer: Some(
|
buffer: Some(
|
||||||
super::super::InputBuffer::Asio(buff),
|
super::super::InputBuffer::Asio(
|
||||||
|
buff,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -363,7 +379,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
convert_endian_to
|
convert_endian_to
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt16LSB => {
|
sys::AsioSampleType::ASIOSTInt16LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -377,7 +393,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
convert_endian_to
|
convert_endian_to
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt32MSB => {
|
sys::AsioSampleType::ASIOSTInt32MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -391,7 +407,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
convert_endian_to
|
convert_endian_to
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt16MSB => {
|
sys::AsioSampleType::ASIOSTInt16MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -405,7 +421,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
convert_endian_to
|
convert_endian_to
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -419,7 +435,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -433,7 +449,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat32MSB => {
|
sys::AsioSampleType::ASIOSTFloat32MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -447,7 +463,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat64MSB => {
|
sys::AsioSampleType::ASIOSTFloat64MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -461,10 +477,10 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
_ => println!("unsupported format {:?}", stream_type),
|
_ => println!("unsupported format {:?}", stream_type),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => return (),
|
None => return (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,7 +496,9 @@ impl EventLoop {
|
||||||
|
|
||||||
/// Create the an output cpal stream.
|
/// Create the an output cpal stream.
|
||||||
pub fn build_output_stream(
|
pub fn build_output_stream(
|
||||||
&self, device: &Device, format: &Format,
|
&self,
|
||||||
|
device: &Device,
|
||||||
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, CreationError> {
|
||||||
let Device { drivers, .. } = device;
|
let Device { drivers, .. } = device;
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
|
@ -499,7 +517,7 @@ impl EventLoop {
|
||||||
SampleFormat::I16 => Buffers {
|
SampleFormat::I16 => Buffers {
|
||||||
i16_buff: I16Buffer {
|
i16_buff: I16Buffer {
|
||||||
cpal: vec![0 as i16; cpal_num_samples],
|
cpal: vec![0 as i16; cpal_num_samples],
|
||||||
channel: (0 .. num_channels)
|
channel: (0..num_channels)
|
||||||
.map(|_| Vec::with_capacity(channel_len))
|
.map(|_| Vec::with_capacity(channel_len))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
|
@ -509,7 +527,7 @@ impl EventLoop {
|
||||||
i16_buff: I16Buffer::default(),
|
i16_buff: I16Buffer::default(),
|
||||||
f32_buff: F32Buffer {
|
f32_buff: F32Buffer {
|
||||||
cpal: vec![0 as f32; cpal_num_samples],
|
cpal: vec![0 as f32; cpal_num_samples],
|
||||||
channel: (0 .. num_channels)
|
channel: (0..num_channels)
|
||||||
.map(|_| Vec::with_capacity(channel_len))
|
.map(|_| Vec::with_capacity(channel_len))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
|
@ -538,39 +556,46 @@ impl EventLoop {
|
||||||
// Convert sample depending on the sample type
|
// Convert sample depending on the sample type
|
||||||
macro_rules! convert_sample {
|
macro_rules! convert_sample {
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
$AsioType:ty,
|
f32,
|
||||||
u16,
|
$SampleTypeIdent:ident,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
((*$Sample as i64 * ::std::$AsioTypeIdent::MAX as i64
|
(*$Sample as f64
|
||||||
/ ::std::u16::MAX as i64)
|
/ ::std::$SampleTypeIdent::MAX as f64) as f32
|
||||||
- $AsioTypeIdent::MAX as i64) as $AsioType
|
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
$AsioType:ty,
|
f64,
|
||||||
$SampleTypeIdent:ident,
|
$SampleTypeIdent:ident,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
|
*$Sample as f64
|
||||||
|
/ ::std::$SampleTypeIdent::MAX as f64
|
||||||
|
};
|
||||||
|
($AsioTypeIdent:ident,
|
||||||
|
$AsioType:ty,
|
||||||
|
$SampleTypeIdent:ident,
|
||||||
|
$Sample:expr
|
||||||
|
) => {
|
||||||
(*$Sample as i64 * ::std::$AsioTypeIdent::MAX as i64
|
(*$Sample as i64 * ::std::$AsioTypeIdent::MAX as i64
|
||||||
/ ::std::$SampleTypeIdent::MAX as i64) as $AsioType
|
/ ::std::$SampleTypeIdent::MAX as i64) as $AsioType
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Theres only a single callback because theres only one event loop
|
// Theres only a single callback because theres only one event loop
|
||||||
match callbacks.first_mut() {
|
match callbacks.as_mut() {
|
||||||
Some(callback) => {
|
Some(callback) => {
|
||||||
macro_rules! try_callback {
|
macro_rules! try_callback {
|
||||||
($SampleFormat:ident,
|
($SampleFormat:ident,
|
||||||
$SampleType:ty,
|
$SampleType:ty,
|
||||||
$SampleTypeIdent:ident,
|
$SampleTypeIdent:ident,
|
||||||
$AsioType:ty,
|
$AsioType:ty,
|
||||||
$AsioTypeIdent:ident,
|
$AsioTypeIdent:ident,
|
||||||
$Buffers:expr,
|
$Buffers:expr,
|
||||||
$BuffersType:ty,
|
$BuffersType:ty,
|
||||||
$BuffersTypeIdent:ident,
|
$BuffersTypeIdent:ident,
|
||||||
$Endianness:expr,
|
$Endianness:expr,
|
||||||
$ConvertEndian:expr
|
$ConvertEndian:expr
|
||||||
) => {
|
) => {
|
||||||
let mut my_buffers = $Buffers;
|
let mut my_buffers = $Buffers;
|
||||||
{
|
{
|
||||||
// Wrap the cpal buffer
|
// Wrap the cpal buffer
|
||||||
|
@ -675,7 +700,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
convert_endian_from
|
convert_endian_from
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt16LSB => {
|
sys::AsioSampleType::ASIOSTInt16LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -689,7 +714,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
convert_endian_from
|
convert_endian_from
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt32MSB => {
|
sys::AsioSampleType::ASIOSTInt32MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -703,7 +728,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
convert_endian_from
|
convert_endian_from
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTInt16MSB => {
|
sys::AsioSampleType::ASIOSTInt16MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
I16,
|
I16,
|
||||||
|
@ -717,7 +742,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
convert_endian_from
|
convert_endian_from
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -731,7 +756,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -745,7 +770,7 @@ impl EventLoop {
|
||||||
Endian::Little,
|
Endian::Little,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat32MSB => {
|
sys::AsioSampleType::ASIOSTFloat32MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -759,7 +784,7 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat64MSB => {
|
sys::AsioSampleType::ASIOSTFloat64MSB => {
|
||||||
try_callback!(
|
try_callback!(
|
||||||
F32,
|
F32,
|
||||||
|
@ -773,10 +798,10 @@ impl EventLoop {
|
||||||
Endian::Big,
|
Endian::Big,
|
||||||
|a, _| a
|
|a, _| a
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
_ => println!("unsupported format {:?}", stream_type),
|
_ => println!("unsupported format {:?}", stream_type),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => return (),
|
None => return (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,10 +867,10 @@ impl EventLoop {
|
||||||
F: FnMut(StreamId, StreamData) + Send,
|
F: FnMut(StreamId, StreamData) + Send,
|
||||||
{
|
{
|
||||||
let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback;
|
let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback;
|
||||||
self.callbacks
|
// Transmute needed to convince the compiler that the callback has a static lifetime
|
||||||
|
*self.callbacks
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap() = Some(unsafe { mem::transmute(callback) });
|
||||||
.push(unsafe { mem::transmute(callback) });
|
|
||||||
loop {
|
loop {
|
||||||
// A sleep here to prevent the loop being
|
// A sleep here to prevent the loop being
|
||||||
// removed in --release
|
// removed in --release
|
||||||
|
|
Loading…
Reference in New Issue