From c978583863052bdfb5ba961f197ba12a54aecc81 Mon Sep 17 00:00:00 2001 From: DMSDeveloper Date: Sun, 22 Apr 2018 23:24:05 +1000 Subject: [PATCH] recording v1 --- src/platform/windows/asio/device.rs | 6 + src/platform/windows/asio/stream.rs | 409 ++++++++++++++-------------- 2 files changed, 208 insertions(+), 207 deletions(-) diff --git a/src/platform/windows/asio/device.rs b/src/platform/windows/asio/device.rs index 5e85ae8..e301742 100644 --- a/src/platform/windows/asio/device.rs +++ b/src/platform/windows/asio/device.rs @@ -182,6 +182,12 @@ impl Iterator for Devices { // so returning first in list as default pub fn default_input_device() -> Option { let mut driver_list = sys::get_driver_list(); + for dn in &driver_list{ + if dn == "ASIO4ALL v2"{ + println!("Defaulted to ASIO4ALL **remove from production**"); + return Some(Device{ driver_name: dn.clone() }); + } + } match driver_list.pop() { Some(dn) => Some(Device{ driver_name: dn }), None => None, diff --git a/src/platform/windows/asio/stream.rs b/src/platform/windows/asio/stream.rs index 90f8caa..b93953d 100644 --- a/src/platform/windows/asio/stream.rs +++ b/src/platform/windows/asio/stream.rs @@ -9,6 +9,7 @@ use std::marker::PhantomData; use super::Device; use std::cell::Cell; use UnknownTypeOutputBuffer; +use UnknownTypeInputBuffer; use std::sync::{Arc, Mutex}; use std::mem; use self::itertools::Itertools; @@ -23,7 +24,7 @@ pub struct EventLoop { pub struct StreamId(usize); pub struct InputBuffer<'a, T: 'a> { - marker: PhantomData<&'a T>, + buffer: &'a mut [T], } pub struct OutputBuffer<'a, T: 'a> { buffer: &'a mut [T], @@ -42,8 +43,7 @@ impl EventLoop { &self, device: &Device, format: &Format, - ) -> Result { - /* + ) -> Result { let stream_type = sys::get_data_type(&device.driver_name).expect("Couldn't load data type"); match sys::prepare_stream(&device.driver_name) { Ok(stream) => { @@ -57,7 +57,6 @@ impl EventLoop { let bytes_per_channel = format.data_type.sample_size(); let num_channels = format.channels.clone(); - // Get stream types sys::set_callback(move |index| unsafe { if let Some(ref asio_stream) = *asio_stream.lock().unwrap() { @@ -70,192 +69,67 @@ impl EventLoop { match callbacks.first_mut() { Some(callback) => { macro_rules! try_callback { - ($SampleFormat:ident, - $SampleType:ty, - $SampleTypeIdent:ident, - $AsioType:ty, - $AsioTypeIdent:ident) => { - // Buffer that is filled by cpal. - let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples]; - // Call in block because of mut borrow - { - } - // Function for deinterleaving because - // cpal writes to buffer interleaved - fn interleave(channels: Vec>) -> Vec<$SampleType>{ - let mut buffer: Vec<$SampleType> = Vec::new(); - let length = channels[0].len(); - for i in 0..length{ - for channel in channels{ - buffer.push(channel[i]); - } + ($SampleFormat:ident, + $SampleType:ty, + $SampleTypeIdent:ident, + $AsioType:ty, + $AsioTypeIdent:ident) => { + // Buffer that is filled by cpal. + let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples]; + // Call in block because of mut borrow + { + } + // Function for deinterleaving because + // cpal writes to buffer interleaved + fn interleave(channels: Vec>) -> Vec<$SampleType>{ + let mut buffer: Vec<$SampleType> = Vec::new(); + let length = channels[0].len(); + for i in 0..length{ + for channel in &channels{ + buffer.push(channel[i]); } - buffer } - // Deinter all the channels - let deinter_channels = deinterleave(&mut cpal_buffer[..], - num_channels as usize); - - // For each channel write the cpal data to - // the asio buffer - // Also need to check for Endian - for (i, channel) in deinter_channels.into_iter().enumerate(){ - let buff_ptr = (asio_stream - .buffer_infos[i] - .buffers[index as usize] as *mut $AsioType) - .offset(asio_stream.buffer_size as isize * i as isize); - let asio_buffer: &'static mut [$AsioType] = - std::slice::from_raw_parts_mut( - buff_ptr, - asio_stream.buffer_size as usize); - for (asio_s, cpal_s) in asio_buffer.iter_mut() - .zip(&channel){ - *asio_s = (*cpal_s as i64 * - ::std::$AsioTypeIdent::MAX as i64 / - ::std::$SampleTypeIdent::MAX as i64) as $AsioType; - } + buffer + } + let mut channels: Vec> = vec![Vec::new(); num_channels as usize]; + // For each channel write the cpal data to + // the asio buffer + // Also need to check for Endian + for (i, channel) in channels.iter_mut().enumerate(){ + let buff_ptr = (asio_stream + .buffer_infos[i] + .buffers[index as usize] as *mut $AsioType) + .offset(asio_stream.buffer_size as isize * i as isize); + let asio_buffer: &'static mut [$AsioType] = + std::slice::from_raw_parts_mut( + buff_ptr, + asio_stream.buffer_size as usize); + for asio_s in asio_buffer.iter(){ + channel.push( (*asio_s as i64 * + ::std::$SampleTypeIdent::MAX as i64 / + ::std::$AsioTypeIdent::MAX as i64) as $SampleType); } + } + + // interleave all the channels + let inter_buffer = interleave(channels); - let buff = InputBuffer{ - buffer: &mut cpal_buffer - }; - callback( - StreamId(count), - StreamData::Input{ - buffer: UnknownTypeInputBuffer::$SampleFormat( - ::InputBuffer{ - target: Some(super::super::InputBuffer::Asio(buff)) - }) - } - ); + let buff = InputBuffer{ + buffer: &mut cpal_buffer }; - } - // Generic over types - // TODO check for endianess - match stream_type { - sys::AsioSampleType::ASIOSTInt32LSB => { - try_callback!(I16, i16, i16, i32, i32); - } - sys::AsioSampleType::ASIOSTInt16LSB => { - try_callback!(I16, i16, i16, i16, i16); - } - sys::AsioSampleType::ASIOSTFloat32LSB => { - try_callback!(F32, f32, f32, f32, f32); - } - sys::AsioSampleType::ASIOSTFloat32LSB => { - try_callback!(F32, f32, f32, f64, f64); - } - _ => println!("unsupported format {:?}", stream_type), - } - } - None => return (), - } - } - }); - Ok(StreamId(count)) - } - Err(ref e) => { - println!("Error preparing stream: {}", e); - Err(CreationError::DeviceNotAvailable) - } - } - */ - unimplemented!() - } - - pub fn build_output_stream( - &self, - device: &Device, - format: &Format, - ) -> Result { - let stream_type = sys::get_data_type(&device.driver_name).expect("Couldn't load data type"); - match sys::prepare_stream(&device.driver_name) { - Ok(stream) => { - { - *self.asio_stream.lock().unwrap() = Some(stream); - } - let count = self.stream_count.get(); - self.stream_count.set(count + 1); - let asio_stream = self.asio_stream.clone(); - let callbacks = self.callbacks.clone(); - let bytes_per_channel = format.data_type.sample_size(); - let num_channels = format.channels.clone(); - - // Get stream types - - sys::set_callback(move |index| unsafe { - if let Some(ref asio_stream) = *asio_stream.lock().unwrap() { - // Number of samples needed total - let cpal_num_samples = - (asio_stream.buffer_size as usize) * num_channels as usize; - let mut callbacks = callbacks.lock().unwrap(); - - // Assuming only one callback, probably needs to change - match callbacks.first_mut() { - Some(callback) => { - macro_rules! try_callback { - ($SampleFormat:ident, - $SampleType:ty, - $SampleTypeIdent:ident, - $AsioType:ty, - $AsioTypeIdent:ident) => { - // Buffer that is filled by cpal. - let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples]; - // Call in block because of mut borrow - { - let buff = OutputBuffer{ - buffer: &mut cpal_buffer - }; - callback( - StreamId(count), - StreamData::Output{ - buffer: UnknownTypeOutputBuffer::$SampleFormat( - ::OutputBuffer{ - target: Some(super::super::OutputBuffer::Asio(buff)) - }) - } - ); + callback( + StreamId(count), + StreamData::Input{ + buffer: UnknownTypeInputBuffer::$SampleFormat( + ::InputBuffer{ + buffer: Some(super::super::InputBuffer::Asio(buff)) + }) } - // Function for deinterleaving because - // cpal writes to buffer interleaved - fn deinterleave(data_slice: &mut [$SampleType], - num_channels: usize) -> Vec>{ - let mut channels: Vec> = Vec::new(); - for i in 0..num_channels{ - let mut it = data_slice.iter().skip(i).cloned(); - let channel = it.step(num_channels).collect(); - channels.push(channel); - } - channels - } - // Deinter all the channels - let deinter_channels = deinterleave(&mut cpal_buffer[..], - num_channels as usize); - - // For each channel write the cpal data to - // the asio buffer - // Also need to check for Endian - for (i, channel) in deinter_channels.into_iter().enumerate(){ - let buff_ptr = (asio_stream - .buffer_infos[i] - .buffers[index as usize] as *mut $AsioType) - .offset(asio_stream.buffer_size as isize * i as isize); - let asio_buffer: &'static mut [$AsioType] = - std::slice::from_raw_parts_mut( - buff_ptr, - asio_stream.buffer_size as usize); - for (asio_s, cpal_s) in asio_buffer.iter_mut() - .zip(&channel){ - *asio_s = (*cpal_s as i64 * - ::std::$AsioTypeIdent::MAX as i64 / - ::std::$SampleTypeIdent::MAX as i64) as $AsioType; - } - - } - }; + ); } + }; // Generic over types // TODO check for endianess match stream_type { @@ -287,42 +161,163 @@ impl EventLoop { } } - pub fn play_stream(&self, stream: StreamId) { - sys::play(); - } +pub fn build_output_stream( + &self, + device: &Device, + format: &Format, + ) -> Result { + let stream_type = sys::get_data_type(&device.driver_name).expect("Couldn't load data type"); + match sys::prepare_stream(&device.driver_name) { + Ok(stream) => { + { + *self.asio_stream.lock().unwrap() = Some(stream); + } + let count = self.stream_count.get(); + self.stream_count.set(count + 1); + let asio_stream = self.asio_stream.clone(); + let callbacks = self.callbacks.clone(); + let bytes_per_channel = format.data_type.sample_size(); + let num_channels = format.channels.clone(); - pub fn pause_stream(&self, stream: StreamId) { - sys::stop(); - } - pub fn destroy_stream(&self, stream_id: StreamId) { - let mut asio_stream_lock = self.asio_stream.lock().unwrap(); - let old_stream = mem::replace(&mut *asio_stream_lock, None); - if let Some(old_stream) = old_stream { - sys::destroy_stream(old_stream); + // Get stream types + + sys::set_callback(move |index| unsafe { + if let Some(ref asio_stream) = *asio_stream.lock().unwrap() { + // Number of samples needed total + let cpal_num_samples = + (asio_stream.buffer_size as usize) * num_channels as usize; + let mut callbacks = callbacks.lock().unwrap(); + + // Assuming only one callback, probably needs to change + match callbacks.first_mut() { + Some(callback) => { + macro_rules! try_callback { + ($SampleFormat:ident, + $SampleType:ty, + $SampleTypeIdent:ident, + $AsioType:ty, + $AsioTypeIdent:ident) => { + // Buffer that is filled by cpal. + let mut cpal_buffer: Vec<$SampleType> = vec![0 as $SampleType; cpal_num_samples]; + // Call in block because of mut borrow + { + let buff = OutputBuffer{ + buffer: &mut cpal_buffer + }; + callback( + StreamId(count), + StreamData::Output{ + buffer: UnknownTypeOutputBuffer::$SampleFormat( + ::OutputBuffer{ + target: Some(super::super::OutputBuffer::Asio(buff)) + }) + } + ); + } + // Function for deinterleaving because + // cpal writes to buffer interleaved + fn deinterleave(data_slice: &mut [$SampleType], + num_channels: usize) -> Vec>{ + let mut channels: Vec> = Vec::new(); + for i in 0..num_channels{ + let mut it = data_slice.iter().skip(i).cloned(); + let channel = it.step(num_channels).collect(); + channels.push(channel); + } + channels + } + // Deinter all the channels + let deinter_channels = deinterleave(&mut cpal_buffer[..], + num_channels as usize); + + // For each channel write the cpal data to + // the asio buffer + // Also need to check for Endian + for (i, channel) in deinter_channels.into_iter().enumerate(){ + let buff_ptr = (asio_stream + .buffer_infos[i] + .buffers[index as usize] as *mut $AsioType) + .offset(asio_stream.buffer_size as isize * i as isize); + let asio_buffer: &'static mut [$AsioType] = + std::slice::from_raw_parts_mut( + buff_ptr, + asio_stream.buffer_size as usize); + for (asio_s, cpal_s) in asio_buffer.iter_mut() + .zip(&channel){ + *asio_s = (*cpal_s as i64 * + ::std::$AsioTypeIdent::MAX as i64 / + ::std::$SampleTypeIdent::MAX as i64) as $AsioType; + } + + } + }; + } + // Generic over types + // TODO check for endianess + match stream_type { + sys::AsioSampleType::ASIOSTInt32LSB => { + try_callback!(I16, i16, i16, i32, i32); + } + sys::AsioSampleType::ASIOSTInt16LSB => { + try_callback!(I16, i16, i16, i16, i16); + } + sys::AsioSampleType::ASIOSTFloat32LSB => { + try_callback!(F32, f32, f32, f32, f32); + } + sys::AsioSampleType::ASIOSTFloat32LSB => { + try_callback!(F32, f32, f32, f64, f64); + } + _ => println!("unsupported format {:?}", stream_type), + } + } + None => return (), + } + } + }); + Ok(StreamId(count)) } - } - pub fn run(&self, mut callback: F) -> ! - where - F: FnMut(StreamId, StreamData) + Send, - { - let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback; - self.callbacks - .lock() - .unwrap() - .push(unsafe { mem::transmute(callback) }); - loop { - // Might need a sleep here to prevent the loop being - // removed in --release + Err(ref e) => { + println!("Error preparing stream: {}", e); + Err(CreationError::DeviceNotAvailable) } } } +pub fn play_stream(&self, stream: StreamId) { + sys::play(); +} + +pub fn pause_stream(&self, stream: StreamId) { + sys::stop(); +} +pub fn destroy_stream(&self, stream_id: StreamId) { + let mut asio_stream_lock = self.asio_stream.lock().unwrap(); + let old_stream = mem::replace(&mut *asio_stream_lock, None); + if let Some(old_stream) = old_stream { + sys::destroy_stream(old_stream); + } +} +pub fn run(&self, mut callback: F) -> ! +where +F: FnMut(StreamId, StreamData) + Send, +{ + let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback; + self.callbacks + .lock() + .unwrap() + .push(unsafe { mem::transmute(callback) }); + loop { + // Might need a sleep here to prevent the loop being + // removed in --release + } +} +} + impl<'a, T> InputBuffer<'a, T> { pub fn buffer(&self) -> &[T] { - unimplemented!() + &self.buffer } pub fn finish(self) { - unimplemented!() } }