From b2635a52c5016a07205dc55d9f4f2bd6a36e3e4e Mon Sep 17 00:00:00 2001 From: Ronald Kinard Date: Wed, 1 Jun 2016 01:28:59 -0500 Subject: [PATCH 1/3] [osx] Add get_period to Voice --- src/coreaudio/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreaudio/mod.rs b/src/coreaudio/mod.rs index e3b6598..2366f0e 100644 --- a/src/coreaudio/mod.rs +++ b/src/coreaudio/mod.rs @@ -160,6 +160,11 @@ impl Voice { unimplemented!() } + #[inline] + pub fn get_period(&self) -> usize { + 0 + } + #[inline] pub fn get_pending_samples(&self) -> usize { if let Some(ready) = self.update_last_ready() { From e9b8f46f739b8a709249fd452e98890da0234949 Mon Sep 17 00:00:00 2001 From: Ronald Kinard Date: Tue, 14 Jun 2016 23:38:52 -0500 Subject: [PATCH 2/3] [osx] Return correct Voice period. --- src/coreaudio/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreaudio/mod.rs b/src/coreaudio/mod.rs index 2366f0e..5b7c7e2 100644 --- a/src/coreaudio/mod.rs +++ b/src/coreaudio/mod.rs @@ -162,7 +162,7 @@ impl Voice { #[inline] pub fn get_period(&self) -> usize { - 0 + self.get_pending_samples() } #[inline] From 4d2767ee4226a16d01c9bbd534babc16dc85aecc Mon Sep 17 00:00:00 2001 From: Ronald Kinard Date: Tue, 28 Jun 2016 18:09:54 -0500 Subject: [PATCH 3/3] [osx] Correct implementation of get_pending_samples --- src/coreaudio/mod.rs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/coreaudio/mod.rs b/src/coreaudio/mod.rs index 5b7c7e2..4dd6e0d 100644 --- a/src/coreaudio/mod.rs +++ b/src/coreaudio/mod.rs @@ -3,6 +3,7 @@ extern crate libc; use std::sync::mpsc::{channel, Sender, Receiver}; use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::cell::RefCell; use std::mem; use std::cmp; @@ -47,6 +48,7 @@ pub struct Buffer<'a, T: 'a> { samples: Vec, num_channels: NumChannels, marker: PhantomData<&'a T>, + pending_samples: Arc } impl<'a, T> Buffer<'a, T> { @@ -62,10 +64,12 @@ impl<'a, T> Buffer<'a, T> { #[inline] pub fn finish(self) { - let Buffer { samples_sender, samples, num_channels, .. } = self; + let Buffer { samples_sender, samples, num_channels, pending_samples, .. } = self; // TODO: At the moment this assumes the Vec is a Vec. // Need to add T: Sample and use Sample::to_vec_f32. + let num_samples = samples.len(); let samples = unsafe { mem::transmute(samples) }; + pending_samples.fetch_add(num_samples, Ordering::SeqCst); match samples_sender.send((samples, num_channels)) { Err(_) => panic!("Failed to send samples to audio unit callback."), Ok(()) => (), @@ -82,7 +86,8 @@ pub struct Voice { ready_receiver: Receiver<(NumChannels, NumFrames)>, samples_sender: Sender<(Vec, NumChannels)>, underflow: Arc>>, - last_ready: Arc>>> + last_ready: Arc>>>, + pending_samples: Arc } unsafe impl Sync for Voice {} @@ -98,6 +103,10 @@ impl Voice { let underflow = Arc::new(Mutex::new(RefCell::new(false))); let uf_clone = underflow.clone(); + let pending_samples: Arc = Arc::new(AtomicUsize::new(0)); + + let pending_samples_c = pending_samples.clone(); + let audio_unit_result = AudioUnit::new(IOType::HalOutput); if let Ok(mut audio_unit) = audio_unit_result { @@ -112,11 +121,14 @@ impl Voice { *(uf.borrow_mut()) = num_frames > samples.len() / num_channels; } else { return Err("Couldn't lock underflow flag field.".to_string()) } + pending_samples_c.fetch_sub(samples.len(), Ordering::SeqCst); + for (i, frame) in samples.chunks(num_channels).enumerate() { for (channel, sample) in channels.iter_mut().zip(frame.iter()) { channel[i] = *sample; } } + break; }; } @@ -129,7 +141,8 @@ impl Voice { ready_receiver: ready_receiver, samples_sender: samples_sender, underflow: underflow, - last_ready: Arc::new(Mutex::new(RefCell::new(None))) + last_ready: Arc::new(Mutex::new(RefCell::new(None))), + pending_samples: pending_samples }) } } @@ -146,7 +159,8 @@ impl Voice { samples_sender: self.samples_sender.clone(), samples: vec![unsafe { mem::uninitialized() }; buffer_size], num_channels: channels as usize, - marker: PhantomData + marker: PhantomData, + pending_samples: self.pending_samples.clone() } } @@ -162,11 +176,6 @@ impl Voice { #[inline] pub fn get_period(&self) -> usize { - self.get_pending_samples() - } - - #[inline] - pub fn get_pending_samples(&self) -> usize { if let Some(ready) = self.update_last_ready() { (ready.0 * ready.1) as usize } else { @@ -174,6 +183,11 @@ impl Voice { } } + #[inline] + pub fn get_pending_samples(&self) -> usize { + self.pending_samples.load(Ordering::Relaxed) + } + /// Attempts to store the most recent ready message into the internal /// ref cell, then return the last ready message. If the last ready hasn't /// been reset with `clear_last_ready`, then it will not be set and the