audio_processor_metronome/
playhead.rs1use audio_processor_traits::AudioProcessorSettings;
25use augmented_playhead::{PlayHead, PlayHeadOptions};
26
27use crate::constants::{DEFAULT_SAMPLE_RATE, DEFAULT_TEMPO};
28
29pub trait MetronomePlayhead {
38 fn reset(&mut self) {}
39 fn set_tempo(&mut self, _tempo: f32) {}
40 fn prepare(&mut self, _settings: &AudioProcessorSettings, _tempo: f32) {}
41 fn accept_samples(&mut self, _samples: u32) {}
42 fn tempo(&self) -> Option<f32> {
43 None
44 }
45
46 fn position_beats(&self) -> f64;
47}
48
49pub struct DefaultMetronomePlayhead {
50 playhead: PlayHead,
51}
52
53impl DefaultMetronomePlayhead {
54 #[cfg(test)]
55 fn playhead(&self) -> &PlayHead {
56 &self.playhead
57 }
58}
59
60impl Default for DefaultMetronomePlayhead {
61 fn default() -> Self {
62 let sample_rate = DEFAULT_SAMPLE_RATE;
63 let tempo = DEFAULT_TEMPO;
64 let playhead = PlayHead::new(PlayHeadOptions::new(
65 Some(sample_rate),
66 Some(tempo),
67 Some(16),
68 ));
69 Self { playhead }
70 }
71}
72
73impl MetronomePlayhead for DefaultMetronomePlayhead {
74 fn reset(&mut self) {
75 self.playhead.set_position_seconds(0.0);
76 }
77
78 fn set_tempo(&mut self, tempo: f32) {
79 self.playhead.set_tempo(tempo);
80 }
81
82 fn prepare(&mut self, settings: &AudioProcessorSettings, tempo: f32) {
83 self.playhead = PlayHead::new(PlayHeadOptions::new(
84 Some(settings.sample_rate()),
85 Some(tempo),
86 self.playhead.options().ticks_per_quarter_note(),
87 ));
88 }
89
90 fn accept_samples(&mut self, samples: u32) {
91 self.playhead.accept_samples(samples)
92 }
93
94 fn tempo(&self) -> Option<f32> {
95 self.playhead.options().tempo()
96 }
97
98 fn position_beats(&self) -> f64 {
99 self.playhead.position_beats()
100 }
101}
102
103#[cfg(test)]
104mod test {
105 use super::{DefaultMetronomePlayhead, MetronomePlayhead};
106 use audio_processor_testing_helpers::assert_f_eq;
107 use audio_processor_traits::AudioProcessorSettings;
108
109 #[test]
110 fn test_default_metronome_playhead_has_expected_values() {
111 let playhead = DefaultMetronomePlayhead::default();
112 assert_f_eq!(playhead.position_beats(), 0.0);
113 assert_eq!(playhead.tempo(), Some(120.0));
114 }
115
116 #[test]
117 fn test_reset_sets_position_to_zero() {
118 let mut playhead = DefaultMetronomePlayhead::default();
119 playhead.accept_samples(100);
120 playhead.reset();
121 assert_f_eq!(playhead.position_beats(), 0.0);
122 }
123
124 #[test]
125 fn test_set_tempo_changes_tempo() {
126 let mut playhead = DefaultMetronomePlayhead::default();
127 playhead.set_tempo(80.0);
128 assert_eq!(playhead.tempo(), Some(80.0));
129 }
130
131 #[test]
132 fn test_prepare_sets_sample_rate_and_tempo() {
133 let mut playhead = DefaultMetronomePlayhead::default();
134 let settings = AudioProcessorSettings::new(22050.0, 2, 2, 512);
135 playhead.prepare(&settings, 100.0);
136
137 assert_eq!(playhead.tempo(), Some(100.0));
138 let sample_rate = playhead.playhead().options().sample_rate().unwrap();
139 assert_f_eq!(sample_rate, 22050.0);
140 }
141
142 #[test]
143 fn test_accept_samples_updates_position() {
144 let mut playhead = DefaultMetronomePlayhead::default();
145 let settings = AudioProcessorSettings::new(44100.0, 2, 2, 512);
146 playhead.prepare(&settings, 120.0);
147 playhead.accept_samples(4410);
148 assert_f_eq!(playhead.position_beats(), 0.2);
149 }
150}