audio_processor_analysis/window_functions/
mod.rs1use audio_processor_traits::num::traits::FloatConst;
25use audio_processor_traits::Float;
26
27pub type WindowFunction<F> = fn(n: F, size: F) -> F;
28
29pub enum WindowFunctionType {
30 Hann,
31 BlackmanHarris,
32 Blackman,
33 Rectangular,
34 Triangular,
35 Parzen,
36 Welch,
37 Sine,
38}
39
40pub fn make_window_vec<F: Float + FloatConst>(size: usize, fn_type: WindowFunctionType) -> Vec<F> {
41 match fn_type {
42 WindowFunctionType::Hann => make_hann_vec(size),
43 WindowFunctionType::BlackmanHarris => make_blackman_harris_vec(size),
44 WindowFunctionType::Blackman => make_blackman_vec(size),
45 WindowFunctionType::Rectangular => make_rectangular_vec(size),
46 WindowFunctionType::Triangular => make_triangular_vec(size),
47 WindowFunctionType::Parzen => make_parzen_vec(size),
48 WindowFunctionType::Welch => make_welch_vec(size),
49 WindowFunctionType::Sine => make_sine_vec(size),
50 }
51}
52
53#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
54pub fn hann<F>(n: F, size: F) -> F
55where
56 F: Float + FloatConst,
57{
58 0.5 * (1.0 - (2.0 * F::PI() * (n / size)).cos())
59}
60
61#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
62pub fn blackman_harris<F>(n: F, size: F) -> F
63where
64 F: Float + FloatConst,
65{
66 let pi = F::PI();
67 let a0 = 0.35875;
68 let a1 = 0.48829;
69 let a2 = 0.14128;
70 let a3 = 0.01168;
71 a0 - a1 * ((2.0 * pi * n) / size).cos() + a2 * ((4.0 * pi * n) / size).cos()
72 - a3 * ((6.0 * pi * n) / size).cos()
73}
74
75#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
76pub fn blackman<F>(n: F, size: F) -> F
77where
78 F: Float + FloatConst,
79{
80 let pi = F::PI();
82 let a0 = 0.42; let a1 = 0.5; let a2 = 0.08; a0 - a1 * ((2.0 * pi * n) / size).cos() + a2 * ((4.0 * pi * n) / size).cos()
86}
87
88#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
89pub fn triangular<F>(n: F, size: F) -> F
90where
91 F: Float,
92{
93 let l_value = size;
94 1.0 - ((n - size / 2.0) / (l_value)).abs()
95}
96
97#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
98pub fn parzen<F>(n: F, size: F) -> F
99where
100 F: Float,
101{
102 let l = size + 1.0;
103 let w0 = |n: F| {
104 let mn = n.abs();
105 if mn <= l / 4.0 {
106 1.0f64 - 6.0f64 * (n / (l / 2.0)).powi(2) * (1.0 - mn / (l / 2.0))
107 } else if mn <= l / 2.0 {
108 2.0f64 * (1.0 - mn / (l / 2.0)).powi(3)
109 } else {
110 1.0
111 }
112 };
113 w0(n - size / 2.0)
114}
115
116#[numeric_literals::replace_float_literals(F::from(literal).unwrap())]
117pub fn welch<F>(n: F, size: F) -> F
118where
119 F: Float,
120{
121 1.0f64 - ((n - size / 2.0) / (size / 2.0)).powi(2)
122}
123
124pub fn sine<F>(n: F, size: F) -> F
125where
126 F: Float + FloatConst,
127{
128 (F::PI() * (n / size)).sin()
129}
130
131fn make_vec<F>(size: usize, window_fn: WindowFunction<F>) -> Vec<F>
132where
133 F: Float,
134{
135 (0..size)
136 .map(|n| window_fn(F::from(n).unwrap(), F::from(size).unwrap()))
137 .collect()
138}
139
140pub fn make_hann_vec<F: Float + FloatConst>(size: usize) -> Vec<F> {
141 make_vec(size, hann)
142}
143
144pub fn make_blackman_harris_vec<F: Float + FloatConst>(size: usize) -> Vec<F> {
145 make_vec(size, blackman_harris)
146}
147
148pub fn make_blackman_vec<F: Float + FloatConst>(size: usize) -> Vec<F> {
149 make_vec(size, blackman)
150}
151
152pub fn make_rectangular_vec<F: Float>(size: usize) -> Vec<F> {
153 (0..size).map(|_| F::from(1.0).unwrap()).collect()
154}
155
156pub fn make_triangular_vec<F: Float>(size: usize) -> Vec<F> {
157 make_vec(size, triangular)
158}
159
160pub fn make_parzen_vec<F: Float>(size: usize) -> Vec<F> {
161 make_vec(size, parzen)
162}
163
164pub fn make_welch_vec<F: Float>(size: usize) -> Vec<F> {
165 make_vec(size, welch)
166}
167
168pub fn make_sine_vec<F: Float + FloatConst>(size: usize) -> Vec<F> {
169 make_vec(size, sine)
170}
171
172#[cfg(test)]
173mod test {
174 use audio_processor_testing_helpers::{charts::draw_vec_chart, relative_path};
175
176 use super::*;
177
178 type WindowFunction = fn(usize) -> Vec<f32>;
179 fn window_functions() -> Vec<(&'static str, WindowFunction)> {
180 vec![
181 ("RectangularWindow", make_rectangular_vec),
182 ("TriangularWindow", make_triangular_vec),
183 ("HannWindow", make_hann_vec),
184 ("ParzenWindow", make_parzen_vec),
185 ("WelchWindow", make_welch_vec),
186 ("SineWindow", make_sine_vec),
187 ("BlackmanWindow", make_blackman_vec),
188 ("BlackmanHarrisWindow", make_blackman_harris_vec),
189 ]
190 }
191
192 fn draw_window(label: &str, window_fn: WindowFunction) {
193 let window = window_fn(1000);
194 draw_vec_chart(
195 &relative_path!("src/window_functions/windows"),
196 label,
197 window,
198 );
199 }
200
201 #[test]
202 fn test_draw_windows() {
203 for (label, window_fn) in window_functions() {
204 draw_window(label, window_fn);
205 }
206 }
207}