Skip to main content

rill_core_dsp/
analyzer.rs

1//! Traits for signal analyzers
2
3use rill_core::traits::algorithm::Algorithm;
4use rill_core::Transcendental;
5
6/// Base trait for analyzers
7pub trait Analyzer<T: Transcendental>: Algorithm<T> {
8    /// Analysis result type
9    type Output;
10
11    /// Get analysis result
12    fn result(&self) -> &Self::Output;
13
14    /// Reset accumulated data
15    fn reset_analysis(&mut self);
16}
17
18/// Peak detector (VU meter)
19pub trait PeakMeter<T: Transcendental>: Analyzer<T, Output = T> {
20    /// Decay rate (0.0-1.0)
21    fn decay(&self) -> f32;
22
23    /// Set decay rate
24    fn set_decay(&mut self, decay: f32);
25
26    /// Current peak (for display)
27    fn peak(&self) -> T {
28        *self.result()
29    }
30}
31
32/// Envelope follower
33pub trait EnvelopeFollower<T: Transcendental>: Analyzer<T, Output = T> {
34    /// Attack time in seconds
35    fn attack(&self) -> f32;
36
37    /// Release time in seconds
38    fn release(&self) -> f32;
39
40    /// Set times
41    fn set_attack_release(&mut self, attack: f32, release: f32);
42
43    /// Current envelope
44    fn envelope(&self) -> T {
45        *self.result()
46    }
47}
48
49/// Frequency detector (for tuners)
50pub trait FrequencyDetector<T: Transcendental>: Analyzer<T, Output = f32> {
51    /// Minimum detection frequency
52    fn min_freq(&self) -> f32;
53
54    /// Maximum detection frequency
55    fn max_freq(&self) -> f32;
56
57    /// Current frequency
58    fn frequency(&self) -> f32 {
59        *self.result()
60    }
61
62    /// Closest MIDI note
63    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
73/// Spectrum analyzer (FFT)
74pub trait SpectrumAnalyzer<T: Transcendental>: Analyzer<T, Output = Vec<f32>> {
75    /// FFT size
76    fn fft_size(&self) -> usize;
77
78    /// Get spectrum
79    fn spectrum(&self) -> &[f32] {
80        self.result()
81    }
82
83    /// Get amplitude at specific frequency
84    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}