Skip to content

Commit 060cf5b

Browse files
committed
Add Blackman window
1 parent ed969eb commit 060cf5b

File tree

2 files changed

+125
-1
lines changed

2 files changed

+125
-1
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use super::GeneralCosine;
2+
use super::{extend, len_guard, truncate};
3+
use nalgebra::RealField;
4+
use num_traits::{real::Real, Float};
5+
6+
#[cfg(feature = "alloc")]
7+
use super::GetWindow;
8+
#[cfg(feature = "alloc")]
9+
use alloc::{vec, vec::Vec};
10+
11+
/// Collection of arguments for window `Blackman` for use in [GetWindow].
12+
#[derive(Debug, Clone, PartialEq)]
13+
pub struct Blackman {
14+
/// Number of points in the output window. If zero, an empty array is returned in [GetWindow].
15+
pub m: usize,
16+
/// Whether the window is symmetric.
17+
///
18+
/// When true, generates a symmetric window, for use in filter design.
19+
/// When false, generates a periodic window, for use in spectral analysis.
20+
pub sym: bool,
21+
}
22+
23+
impl Blackman {
24+
/// Returns a Blackman struct.
25+
///
26+
/// # Parameters
27+
/// * `m`:
28+
/// Number of points in the output window. If zero, an empty array is returned.
29+
/// * `sym`:
30+
/// When true, generates a symmetric window, for use in filter design.
31+
/// When false, generates a periodic window, for use in spectral analysis.
32+
pub fn new(m: usize, sym: bool) -> Self {
33+
Blackman { m, sym }
34+
}
35+
}
36+
37+
#[cfg(feature = "alloc")]
38+
impl GetWindow for Blackman {
39+
/// Return a window of type: Blackman.
40+
///
41+
/// The Blackman window is a taper formed by using the first three terms of a summation of
42+
/// cosines. It was designed to have close to the minimal leakage possible. It is close to
43+
/// optimal, only slightly worse than a Kaiser window.
44+
///
45+
/// # Parameters
46+
/// `self`: [Blackman]
47+
///
48+
/// # Returns
49+
/// `w`: `vec<F>`
50+
/// The window, with the maximum value normalized to 1 (though the value 1 does not appear
51+
/// if `M` is even and `sym` is True).
52+
///
53+
/// # Example
54+
/// ```
55+
/// use sci_rs::signal::windows::{Blackman, GetWindow};
56+
///
57+
/// let nx = 8;
58+
/// let b = Blackman::new(nx, true);
59+
/// ```
60+
///
61+
/// # References
62+
/// <https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.windows.blackman.html>
63+
#[cfg(feature = "alloc")]
64+
fn get_window<F>(&self) -> Vec<F>
65+
where
66+
F: Real + Float + RealField,
67+
{
68+
GeneralCosine::new(
69+
self.m,
70+
[0.42, 0.50, 0.08]
71+
.into_iter()
72+
.map(|n| F::from(n).unwrap())
73+
.collect(),
74+
self.sym,
75+
)
76+
.get_window()
77+
}
78+
}
79+
80+
#[cfg(test)]
81+
mod tests {
82+
use super::*;
83+
use approx::assert_abs_diff_eq;
84+
85+
#[test]
86+
fn blackman_20() {
87+
// Created with
88+
// >>> from scipy.signal.windows import blackman
89+
// >>> blackman(20)
90+
let expected = vec![
91+
-1.38777878e-17,
92+
1.02226199e-02,
93+
4.50685843e-02,
94+
1.14390287e-01,
95+
2.26899356e-01,
96+
3.82380768e-01,
97+
5.66665187e-01,
98+
7.52034438e-01,
99+
9.03492728e-01,
100+
9.88846031e-01,
101+
9.88846031e-01,
102+
9.03492728e-01,
103+
7.52034438e-01,
104+
5.66665187e-01,
105+
3.82380768e-01,
106+
2.26899356e-01,
107+
1.14390287e-01,
108+
4.50685843e-02,
109+
1.02226199e-02,
110+
-1.38777878e-17,
111+
];
112+
assert_vec_eq(expected, Blackman::new(20, true).get_window());
113+
}
114+
115+
#[track_caller]
116+
fn assert_vec_eq(a: Vec<f64>, b: Vec<f64>) {
117+
for (a, b) in a.into_iter().zip(b) {
118+
assert_abs_diff_eq!(a, b, epsilon = 1e-6);
119+
}
120+
}
121+
}

sci-rs/src/signal/windows/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ fn truncate<'a, W>(mut w: Vec<W>, needed: bool) -> Vec<W> {
5757
w
5858
}
5959

60+
mod blackman;
6061
mod boxcar;
6162
mod general_cosine;
6263
mod triangle;
64+
pub use blackman::Blackman;
6365
pub use boxcar::Boxcar;
6466
pub use general_cosine::GeneralCosine;
6567
pub use triangle::Triangle;
@@ -80,7 +82,8 @@ where
8082
Boxcar(Boxcar),
8183
/// Triangle window.
8284
Triangle(Triangle),
83-
// Blackman,
85+
/// Blackman window
86+
Blackman(Blackman),
8487
// Hamming,
8588
// Hann,
8689
// Bartlett,

0 commit comments

Comments
 (0)