use alloc::vec::Vec;
use core::f32::consts::PI;
use libm::cosf;
#[must_use]
pub fn hann_window(samples: &[f32]) -> Vec<f32> {
let mut windowed_samples = Vec::with_capacity(samples.len());
let samples_len_f32 = samples.len() as f32;
for (i, sample) in samples.iter().enumerate() {
let two_pi_i = 2.0 * PI * i as f32;
let idontknowthename = cosf(two_pi_i / samples_len_f32);
let multiplier = 0.5 * (1.0 - idontknowthename);
windowed_samples.push(multiplier * sample)
}
windowed_samples
}
#[must_use]
pub fn hamming_window(samples: &[f32]) -> Vec<f32> {
let mut windowed_samples = Vec::with_capacity(samples.len());
if samples.len() <= 1 {
windowed_samples.extend_from_slice(samples);
return windowed_samples;
}
let samples_len_f32 = samples.len() as f32;
for (i, sample) in samples.iter().enumerate() {
let multiplier = 0.54 - (0.46 * cosf(2.0 * PI * i as f32 / (samples_len_f32 - 1.0)));
windowed_samples.push(multiplier * sample)
}
windowed_samples
}
#[must_use]
pub fn blackman_harris_4term(samples: &[f32]) -> Vec<f32> {
const ALPHA: [f32; 4] = [0.35875, -0.48829, 0.14128, -0.01168];
blackman_harris_xterm(samples, &ALPHA)
}
#[must_use]
pub fn blackman_harris_7term(samples: &[f32]) -> Vec<f32> {
const ALPHA: [f32; 7] = [
0.271_051_4,
-0.433_297_93,
0.218_123,
-0.065_925_45,
0.010_811_742,
-0.000_776_584_84,
0.000_013_887_217,
];
blackman_harris_xterm(samples, &ALPHA)
}
#[must_use]
fn blackman_harris_xterm(samples: &[f32], alphas: &[f32]) -> Vec<f32> {
let mut windowed_samples = Vec::with_capacity(samples.len());
if samples.len() <= 1 {
windowed_samples.extend_from_slice(samples);
return windowed_samples;
}
let samples_len_f32 = samples.len() as f32;
for (i, sample) in samples.iter().enumerate() {
let mut acc = 0.0;
for (alpha_i, alpha) in alphas.iter().enumerate() {
let two_pi_iteration = 2.0 * alpha_i as f32 * PI;
let cos = cosf((two_pi_iteration * i as f32) / (samples_len_f32 - 1.0));
acc += alpha * cos;
}
windowed_samples.push(acc * sample)
}
windowed_samples
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hamming_window_coefficients() {
let windowed = hamming_window(&[1.0; 4]);
let expected = [0.08, 0.77, 0.77, 0.08];
for (actual, expected) in windowed.iter().zip(expected) {
float_cmp::assert_approx_eq!(f32, *actual, expected, epsilon = 0.00001);
}
}
#[test]
fn test_blackman_harris_4term_window_coefficients() {
let windowed = blackman_harris_4term(&[2.0; 4]);
let expected = [0.00012, 1.04115, 1.04115, 0.00012];
for (actual, expected) in windowed.iter().zip(expected) {
float_cmp::assert_approx_eq!(f32, *actual, expected, epsilon = 0.00001);
}
}
}