1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; pub struct ClockUpdater { clock: Arc<AtomicUsize> } impl ClockUpdater { pub fn increment(&mut self, frames: usize) { self.clock.store(self.clock.load(Ordering::Relaxed) + frames, Ordering::Release); } } pub struct ClockConsumer { clock: Arc<AtomicUsize>, rate: u32, tempo: f32 } impl ClockConsumer { pub fn raw_frames(&self) -> usize { self.clock.load(Ordering::Acquire) } pub fn beat(&self) -> f32 { self.tempo / 60. * (self.raw_frames() as f32 / self.rate as f32) } pub fn beat_duration(&self) -> f32 { self.tempo / 60. } } impl Clone for ClockConsumer { fn clone(&self) -> ClockConsumer { ClockConsumer { rate: self.rate, tempo: self.tempo, clock: self.clock.clone() } } } pub fn audio_clock(tempo: f32, rate: u32) -> (ClockUpdater, ClockConsumer) { let c = Arc::new(AtomicUsize::new(0)); (ClockUpdater { clock: c.clone() }, ClockConsumer { clock: c, tempo, rate }) } #[cfg(test)] mod tests { use audio_clock; #[test] fn it_works() { let (mut updater, consumer) = audio_clock(132.0, 44100); updater.increment(128); assert_eq!(consumer.raw_frames(), 128); assert_eq!(consumer.beat_duration(), 132.0 / 60.); assert_eq!(consumer.beat(), consumer.beat_duration() * (consumer.raw_frames() as f32 / 44100. )); updater.increment(64); assert_eq!(consumer.raw_frames(), 128 + 64); assert_eq!(consumer.beat_duration(), 132.0 / 60.); assert_eq!(consumer.beat(), consumer.beat_duration() * (consumer.raw_frames() as f32 / 44100. )); let second_consumer = consumer.clone(); updater.increment(64); assert_eq!(consumer.raw_frames(), 128 + 64 + 64); assert_eq!(consumer.raw_frames(), second_consumer.raw_frames()); assert_eq!(consumer.beat_duration(), second_consumer.beat_duration()); assert_eq!(consumer.beat(), second_consumer.beat()); } }