From ed50bb99233394d62d2cc3c9b8e34a4bbfc812d4 Mon Sep 17 00:00:00 2001 From: Tom Gowan Date: Tue, 30 Oct 2018 16:50:20 +1100 Subject: [PATCH] adding outputs --- asio-sys/src/lib.rs | 4 +- src/platform/windows/asio/device.rs | 8 +-- src/platform/windows/asio/stream.rs | 90 ++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/asio-sys/src/lib.rs b/asio-sys/src/lib.rs index 1626fb9..afefedf 100644 --- a/asio-sys/src/lib.rs +++ b/asio-sys/src/lib.rs @@ -19,7 +19,7 @@ use std::os::raw::c_char; use std::os::raw::c_double; use std::os::raw::c_long; use std::os::raw::c_void; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::sync::MutexGuard; @@ -46,6 +46,8 @@ lazy_static! { } static STREAM_DRIVER_COUNT: AtomicUsize = AtomicUsize::new(0); +pub static SILENCE_FIRST: AtomicBool = AtomicBool::new(false); +pub static SILENCE_SECOND: AtomicBool = AtomicBool::new(false); #[derive(Debug)] pub struct Channel { diff --git a/src/platform/windows/asio/device.rs b/src/platform/windows/asio/device.rs index af64202..67fff78 100644 --- a/src/platform/windows/asio/device.rs +++ b/src/platform/windows/asio/device.rs @@ -45,7 +45,7 @@ impl Device { FormatsEnumerationError> { match self.default_input_format() { Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()), - Err(e) => Err(FormatsEnumerationError::DeviceNotAvailable), + Err(_) => Err(FormatsEnumerationError::DeviceNotAvailable), } } @@ -53,7 +53,7 @@ impl Device { FormatsEnumerationError> { match self.default_output_format() { Ok(f) => Ok(vec![SupportedFormat::from(f)].into_iter()), - Err(e) => Err(FormatsEnumerationError::DeviceNotAvailable), + Err(_) => Err(FormatsEnumerationError::DeviceNotAvailable), } } @@ -127,7 +127,7 @@ impl Iterator for Devices { // Asio doesn't have a concept of default // so returning first in list as default pub fn default_input_device() -> Option { - let mut driver_list = sys::get_driver_list(); + let driver_list = sys::get_driver_list(); // Remove let d_name = driver_list.into_iter() .filter(|d| d == "ASIO4ALL v2") @@ -151,7 +151,7 @@ pub fn default_input_device() -> Option { } pub fn default_output_device() -> Option { - let mut driver_list = sys::get_driver_list(); + let driver_list = sys::get_driver_list(); // Remove let d_name = driver_list.into_iter() .filter(|d| d == "ASIO4ALL v2") diff --git a/src/platform/windows/asio/stream.rs b/src/platform/windows/asio/stream.rs index e6fb083..5392a96 100644 --- a/src/platform/windows/asio/stream.rs +++ b/src/platform/windows/asio/stream.rs @@ -5,11 +5,9 @@ use std; use Format; use CreationError; use StreamData; -use std::marker::PhantomData; use super::Device; -use std::cell::Cell; -use UnknownTypeOutputBuffer; use UnknownTypeInputBuffer; +use UnknownTypeOutputBuffer; use std::sync::{Arc, Mutex}; use std::mem; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -32,9 +30,8 @@ pub struct OutputBuffer<'a, T: 'a> { buffer: &'a mut [T], } -enum Stream{ - Input, - Output, +struct Stream{ + playing: bool, } #[derive(Default)] @@ -68,6 +65,9 @@ impl EventLoop { } } + /// Create a new CPAL Input Stream + /// If there is no ASIO Input Stream + /// it will be created fn get_input_stream(&self, drivers: &sys::Drivers, num_channels: usize) -> Result { let ref mut streams = *self.asio_streams.lock().unwrap(); match streams.input { @@ -130,8 +130,8 @@ impl EventLoop { let count = self.stream_count.load(Ordering::SeqCst); self.stream_count.store(count + 1, Ordering::SeqCst); let asio_streams = self.asio_streams.clone(); + let cpal_streams = self.cpal_streams.clone(); let callbacks = self.callbacks.clone(); - let bytes_per_channel = format.data_type.sample_size(); // Create buffers let channel_len = cpal_num_samples @@ -175,11 +175,19 @@ impl EventLoop { }; sys::set_callback(move |index| unsafe { + //if not playing return early + { + if let Some(s) = cpal_streams.lock().unwrap().get(count - 1){ + if let Some(s) = s{ + if !s.playing { return (); } + } + } + } if let Some(ref asio_stream) = asio_streams.lock().unwrap().input { // Number of samples needed total let mut callbacks = callbacks.lock().unwrap(); - // Assuming only one callback, probably needs to change + // Theres only a single callback because theres only one event loop match callbacks.first_mut() { Some(callback) => { macro_rules! try_callback { @@ -266,7 +274,7 @@ impl EventLoop { } } }); - self.cpal_streams.lock().unwrap().push(Some(Stream::Input)); + self.cpal_streams.lock().unwrap().push(Some(Stream{ playing: false })); StreamId(count) }) } @@ -287,8 +295,8 @@ pub fn build_output_stream( let count = self.stream_count.load(Ordering::SeqCst); self.stream_count.store(count + 1, Ordering::SeqCst); let asio_streams = self.asio_streams.clone(); + let cpal_streams = self.cpal_streams.clone(); let callbacks = self.callbacks.clone(); - let bytes_per_channel = format.data_type.sample_size(); // Create buffers let channel_len = cpal_num_samples / num_channels as usize; @@ -331,11 +339,19 @@ pub fn build_output_stream( }; sys::set_callback(move |index| unsafe { + //if not playing return early + { + if let Some(s) = cpal_streams.lock().unwrap().get(count - 1){ + if let Some(s) = s{ + if !s.playing { return (); } + } + } + } if let Some(ref asio_stream) = asio_streams.lock().unwrap().output { // Number of samples needed total let mut callbacks = callbacks.lock().unwrap(); - // Assuming only one callback, probably needs to change + // Theres only a single callback because theres only one event loop match callbacks.first_mut() { Some(callback) => { macro_rules! try_callback { @@ -349,9 +365,6 @@ pub fn build_output_stream( $BuffersTypeIdent:ident ) => { let mut my_buffers = $Buffers; - // 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 my_buffers.cpal @@ -375,6 +388,25 @@ pub fn build_output_stream( au::deinterleave(&c_buffer[..], channels); } + let silence = match index { + 0 =>{ + if !sys::SILENCE_FIRST.load(Ordering::SeqCst) { + sys::SILENCE_FIRST.store(true, Ordering::SeqCst); + sys::SILENCE_SECOND.store(false, Ordering::SeqCst); + true + }else{false} + }, + 1 =>{ + if !sys::SILENCE_SECOND.load(Ordering::SeqCst) { + sys::SILENCE_SECOND.store(true, Ordering::SeqCst); + sys::SILENCE_FIRST.store(false, Ordering::SeqCst); + true + }else{false} + }, + _ => unreachable!(), + }; + + // For each channel write the cpal data to // the asio buffer // TODO need to check for Endian @@ -388,7 +420,8 @@ pub fn build_output_stream( asio_stream.buffer_size as usize); for (asio_s, cpal_s) in asio_buffer.iter_mut() .zip(channel){ - *asio_s = (*cpal_s as i64 * + if silence { *asio_s = 0.0 as $AsioType; } + *asio_s += (*cpal_s as i64 * ::std::$AsioTypeIdent::MAX as i64 / ::std::$SampleTypeIdent::MAX as i64) as $AsioType; } @@ -422,23 +455,40 @@ pub fn build_output_stream( } } }); - self.cpal_streams.lock().unwrap().push(Some(Stream::Output)); + self.cpal_streams.lock().unwrap().push(Some(Stream{ playing: false })); StreamId(count) }) } -pub fn play_stream(&self, stream: StreamId) { +pub fn play_stream(&self, stream_id: StreamId) { + let mut streams = self.cpal_streams.lock().unwrap(); + if let Some(s) = streams.get_mut(stream_id.0).expect("Bad play stream index") { + s.playing = true; + } + // Calling play when already playing is a no-op sys::play(); } -pub fn pause_stream(&self, stream: StreamId) { - sys::stop(); +pub fn pause_stream(&self, stream_id: StreamId) { + let mut streams = self.cpal_streams.lock().unwrap(); + if let Some(s) = streams.get_mut(stream_id.0).expect("Bad pause stream index") { + s.playing = false; + } + let any_playing = streams + .iter() + .filter(|s| if let Some(s) = s { + s.playing + } else {false} ) + .next(); + if let None = any_playing { + sys::stop(); + } } pub fn destroy_stream(&self, stream_id: StreamId) { let mut streams = self.cpal_streams.lock().unwrap(); - streams.get_mut(stream_id.0 - 1).take(); + streams.get_mut(stream_id.0).take(); let count = self.stream_count.load(Ordering::SeqCst); self.stream_count.store(count - 1, Ordering::SeqCst); if count == 1 {