#![allow(non_snake_case)]
use crate::config::*;
use strum::IntoEnumIterator;
use strum_macros::{Display, EnumMessage, EnumIter};
fn hann(nfft: usize) -> Dcol {
let nfftF = nfft as Flt;
Dcol::from_iter((0..nfft).map(|i| {
0.5 * (1. - Flt::cos(2. * pi * i as Flt / (nfftF - 1.)))
}))
}
fn rect(nfft: usize) -> Dcol {
Dcol::ones(nfft)
}
fn blackman(N: usize) -> Dcol {
const a0: Flt = 7938. / 18608.;
const a1: Flt = 9240. / 18608.;
const a2: Flt = 1430. / 18608.;
let Nf = N as Flt;
Dcol::from_iter((0..N).map(|i| {
let iF = i as Flt;
a0 - a1 * Flt::cos(2. * pi * iF / (Nf - 1.)) + a2 * Flt::cos(4. * pi * iF / (Nf - 1.))
}))
}
fn bartlett(N: usize) -> Dcol {
let Nf = N as Flt;
Dcol::from_iter((0..N).map(|i| {
let iF = i as Flt;
if i <= (N - 1) / 2 {
2. * iF / (Nf - 1.)
} else {
2. - 2. * iF / (Nf - 1.)
}
}))
}
fn hamming(N: usize) -> Dcol {
let Nf = N as Flt;
const a0: Flt = 25.0 / 46.0;
const a1: Flt = 1. - a0;
Dcol::from_iter((0..N).map(|i|
a0 - a1 * Flt::cos(2. * pi * i as Flt / (Nf - 1.))
)
)
}
#[cfg_attr(feature = "python-bindings", pyclass(eq, eq_int))]
#[derive(Display, Default, Copy, Clone, Debug, PartialEq, EnumMessage, EnumIter)]
pub enum WindowType {
#[default]
Hann = 0,
Hamming = 1,
Rect = 2,
Bartlett = 3,
Blackman = 4,
}
#[cfg(feature = "python-bindings")]
#[cfg_attr(feature = "python-bindings", pymethods)]
impl WindowType {
#[staticmethod]
fn all() -> Vec<WindowType> {
WindowType::iter().collect()
}
#[staticmethod]
#[pyo3(name="default")]
fn default_py() -> Self {
Self::default()
}
}
#[derive(Clone, Debug)]
pub struct Window {
pub w: WindowType,
pub win: Dcol,
pub R: usize,
}
impl Window {
pub fn new(w: WindowType, nfft: usize) -> Window {
if nfft % 2 != 0 {
panic!("Requires even nfft");
}
let win = match w {
WindowType::Hann => hann(nfft),
WindowType::Hamming => hamming(nfft),
WindowType::Rect => rect(nfft),
WindowType::Bartlett => bartlett(nfft),
WindowType::Blackman => blackman(nfft),
};
let R = nfft/2;
Window { w, win, R }
}
pub fn len(&self) -> usize {
self.win.len()
}
pub fn is_empty(&self) -> bool {
self.win.is_empty()
}
}
#[cfg(test)]
mod test {
use approx::assert_abs_diff_eq;
use super::*;
#[test]
fn test_windows(){
let Hann = hann(11);
let Hamming = hamming(11);
let Bartlett = bartlett(11);
let Blackmann = bartlett(11);
assert_eq!(Hann[5] , 1.);
assert_eq!(Hamming[5] , 1.);
assert_eq!(Bartlett[5] , 1.);
assert_eq!(Blackmann[5] , 1.);
}
}