pub fn hann(n: usize) -> Vec<f32> {
let den = (n.max(2) - 1) as f32;
let pi2_div_den = 2.0 * std::f32::consts::PI / den;
(0..n)
.map(|i| 0.5 - 0.5 * f32::cos(pi2_div_den * i as f32))
.collect()
}
#[inline]
pub fn ema_tc(prev: f32, x: f32, tau_s: f32, dt_s: f32) -> f32 {
let a = (-dt_s / tau_s).exp();
a * prev + (1.0 - a) * x
}
#[inline]
pub fn hz_to_mel(f: f32) -> f32 {
2595.0 * (1.0 + f / 700.0).log10()
}
#[inline]
pub fn mel_to_hz(m: f32) -> f32 {
700.0 * (10f32.powf(m / 2595.0) - 1.0)
}
pub fn prepare_fft_input(
samples: &[f32],
window: &[f32],
) -> Vec<f32> {
samples
.iter()
.zip(window.iter())
.map(|(&s, &w)| s * w)
.collect()
}
#[inline]
pub fn prepare_fft_input_inplace(
samples: &[f32],
window: &[f32],
buf: &mut Vec<f32>,
) {
buf.clear();
buf.extend(
samples.iter().zip(window.iter()).map(|(&s, &w)| s * w),
);
}
#[inline]
pub fn a_weighting(hz: f32) -> f32 {
let f = hz.max(10.0);
let f2 = f * f;
let f4 = f2 * f2;
const P1_SQ: f32 = 20.6_f32 * 20.6_f32; const P2_SQ: f32 = 107.7_f32 * 107.7_f32; const P3_SQ: f32 = 737.9_f32 * 737.9_f32; const P4_SQ: f32 = 12_194.0_f32 * 12_194.0_f32;
let num = P4_SQ * f4;
let den = (f2 + P1_SQ)
* ((f2 + P2_SQ) * (f2 + P3_SQ)).sqrt()
* (f2 + P4_SQ);
let ra = num / den;
const NORM: f32 = 1.258_925_4; ra * NORM
}