use rustfft::num_traits::Float;
#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
pub fn calculate_multiplier<F>(sample_rate: F, duration_ms: F) -> F
where
F: Float,
{
let attack_secs = duration_ms * 0.001;
let attack_samples = sample_rate * attack_secs;
F::exp2(-1.0 / attack_samples)
}
pub type PeakDetector = PeakDetectorImpl<f32>;
pub struct PeakDetectorImpl<F> {
value: F,
}
impl<F: Float> Default for PeakDetectorImpl<F> {
#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
fn default() -> Self {
Self { value: 0.0 }
}
}
impl<F: Float + std::iter::Sum> PeakDetectorImpl<F> {
pub fn value(&self) -> F {
self.value
}
#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
pub fn accept_frame(&mut self, attack_mult: F, release_mult: F, frame: &[F]) {
let frame_len = F::from(frame.len()).unwrap();
let new: F = frame.iter().map(|f| F::abs(*f)).sum::<F>() / frame_len;
let curr_slope = if self.value > new {
release_mult
} else {
attack_mult
};
self.value = (self.value * curr_slope) + ((1.0 - curr_slope) * new);
}
}