use rill_core::Transcendental;
use crate::algorithm::Algorithm;
pub trait Analyzer<T: Transcendental>: Algorithm<T> {
type Output;
fn result(&self) -> &Self::Output;
fn reset_analysis(&mut self);
}
pub trait PeakMeter<T: Transcendental>: Analyzer<T, Output = T> {
fn decay(&self) -> f32;
fn set_decay(&mut self, decay: f32);
fn peak(&self) -> T {
*self.result()
}
}
pub trait EnvelopeFollower<T: Transcendental>: Analyzer<T, Output = T> {
fn attack(&self) -> f32;
fn release(&self) -> f32;
fn set_attack_release(&mut self, attack: f32, release: f32);
fn envelope(&self) -> T {
*self.result()
}
}
pub trait FrequencyDetector<T: Transcendental>: Analyzer<T, Output = f32> {
fn min_freq(&self) -> f32;
fn max_freq(&self) -> f32;
fn frequency(&self) -> f32 {
*self.result()
}
fn closest_midi_note(&self) -> u8 {
let freq = self.frequency();
if freq <= 0.0 {
return 0;
}
let note = 69.0 + 12.0 * (freq / 440.0).log2();
note.round() as u8
}
}
pub trait SpectrumAnalyzer<T: Transcendental>: Analyzer<T, Output = Vec<f32>> {
fn fft_size(&self) -> usize;
fn spectrum(&self) -> &[f32] {
self.result()
}
fn amplitude_at(&self, freq: f32, sample_rate: f32) -> f32 {
let bin = (freq * self.fft_size() as f32 / sample_rate) as usize;
self.result().get(bin).copied().unwrap_or(0.0)
}
}