use std::f64::consts::PI;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FftWindow {
BlackmanHarris,
Blackman,
Hamming,
Hann,
Rectangular,
}
impl FftWindow {
pub fn coherent_gain(&self) -> f64 {
match self {
FftWindow::Rectangular => 1.0,
FftWindow::Hann => 0.5,
FftWindow::Hamming => 0.54,
FftWindow::Blackman => 0.42,
FftWindow::BlackmanHarris => 0.35875,
}
}
}
pub(super) fn window_coefficients(size: usize, window: FftWindow) -> Vec<f64> {
if size == 0 {
return Vec::new();
}
if size == 1 {
return vec![1.0];
}
match window {
FftWindow::Rectangular => vec![1.0; size],
FftWindow::Hann => cosine_window(size, 0.5, 0.5, 0.0, 0.0),
FftWindow::Hamming => cosine_window(size, 0.54, 0.46, 0.0, 0.0),
FftWindow::Blackman => cosine_window(size, 0.42, 0.5, 0.08, 0.0),
FftWindow::BlackmanHarris => cosine_window(size, 0.35875, 0.48829, 0.14128, 0.01168),
}
}
fn cosine_window(size: usize, a0: f64, a1: f64, a2: f64, a3: f64) -> Vec<f64> {
let denom = (size - 1) as f64;
let mut coeffs = Vec::with_capacity(size);
for n in 0..size {
let phase = 2.0 * PI * (n as f64) / denom;
let value = a0 - a1 * phase.cos() + a2 * (2.0 * phase).cos() - a3 * (3.0 * phase).cos();
coeffs.push(value);
}
coeffs
}