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