rill_core_dsp/
analyzer.rs1use rill_core::traits::algorithm::Algorithm;
4use rill_core::Transcendental;
5
6pub trait Analyzer<T: Transcendental>: Algorithm<T> {
8 type Output;
10
11 fn result(&self) -> &Self::Output;
13
14 fn reset_analysis(&mut self);
16}
17
18pub trait PeakMeter<T: Transcendental>: Analyzer<T, Output = T> {
20 fn decay(&self) -> f32;
22
23 fn set_decay(&mut self, decay: f32);
25
26 fn peak(&self) -> T {
28 *self.result()
29 }
30}
31
32pub trait EnvelopeFollower<T: Transcendental>: Analyzer<T, Output = T> {
34 fn attack(&self) -> f32;
36
37 fn release(&self) -> f32;
39
40 fn set_attack_release(&mut self, attack: f32, release: f32);
42
43 fn envelope(&self) -> T {
45 *self.result()
46 }
47}
48
49pub trait FrequencyDetector<T: Transcendental>: Analyzer<T, Output = f32> {
51 fn min_freq(&self) -> f32;
53
54 fn max_freq(&self) -> f32;
56
57 fn frequency(&self) -> f32 {
59 *self.result()
60 }
61
62 fn closest_midi_note(&self) -> u8 {
64 let freq = self.frequency();
65 if freq <= 0.0 {
66 return 0;
67 }
68 let note = 69.0 + 12.0 * (freq / 440.0).log2();
69 note.round() as u8
70 }
71}
72
73pub trait SpectrumAnalyzer<T: Transcendental>: Analyzer<T, Output = Vec<f32>> {
75 fn fft_size(&self) -> usize;
77
78 fn spectrum(&self) -> &[f32] {
80 self.result()
81 }
82
83 fn amplitude_at(&self, freq: f32, sample_rate: f32) -> f32 {
85 let bin = (freq * self.fft_size() as f32 / sample_rate) as usize;
86 self.result().get(bin).copied().unwrap_or(0.0)
87 }
88}