Skip to content

Commit

Permalink
fix(filters_and_windows): resolve remote merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
akshithio committed Sep 12, 2024
2 parents 726b274 + f72d3bd commit 752392e
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/filters_and_windows/blackman.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This function is based on the triangle filter function from wikipedia found here: https://en.wikipedia.org/wiki/Window_function

/// Creates a blackman filter of size N
/// Formula: f(x) = 0.42 - (1/2) cos((2*pi*n)/N) + 0.08 cos(4*pi*n)/N for n in 0..N
///
/// Where:
/// o is the bin offset
///
/// # Arguments
/// N: usize - Size of the filter
/// l: usize - Filter setting (N, N+1, or N+2)
/// offset: usize - Bin offset
///
/// # Returns
/// [f32; N] - Blackman window
pub fn blackman_window<const N: usize>(offset: usize) -> [f32; N] {
let mut filter = [0.0; N];
let a0 = 0.42;
let a1 = 0.5;
let a2 = 0.08;

for n in 0..N {
filter[n] = a0 - a1 * f32::cos((2.0 * std::f32::consts::PI * ((n - offset) as f32) ) / (N as f32))
+ a2 * f32::cos((4.0 * std::f32::consts::PI * ((n - offset) as f32)) / (N as f32));
}

filter
}
20 changes: 20 additions & 0 deletions src/filters_and_windows/gaussian_window.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Creates a gaussian filter of size N
/// Formula: w(x) = exp(-0.5 * ((x - N / 2) / (σ * N / 2))^2)
///
/// # Arguments
/// N: usize - Size of the filter
/// sigma: f32 - Standard deviation, controls the width of the Gaussian
///
/// # Returns
/// [f32; N] - Gaussian window
pub fn gaussian_window<const N: usize>(sigma: f32) -> [f32; N] {
let mut filter = [0.0; N];
let mid = N as f32 / 2.0;

for x in 0..N {
let norm_x = (x as f32 - mid) / (sigma * mid);
filter[x] = (-0.5 * norm_x * norm_x).exp();
}

filter
}
29 changes: 29 additions & 0 deletions src/filters_and_windows/hamming.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This function is based on the triangle filter function from wikipedia found here: https://en.wikipedia.org/wiki/Window_function

/// Creates a triangle filter of size N
/// Formula: f(x) = 1 - |((n - o) - (N / 2)) / (L / 2)| for n in 0..N
///
/// Where:
/// L can be N, N+1, or N+2
/// o is the bin offset
///
/// # Arguments
/// N: usize - Size of the filter
/// l: usize - Filter setting (N, N+1, or N+2)
/// offset: usize - Bin offset
///
/// # Returns
/// [f32; N] - Triangle window\
pub fn triangle_window<const N: usize>(l: usize, offset: usize) -> [f32; N] {
let mut filter = [0.0; N];

let a_nought: f32 = 25.0/46.0;
let float_large_n: f32 = N as f32;

for n in 0..N {
let float_small_n = n as f32;
filter[n] = a_nought - (1.0-a_nought) * libm::cosf((2.0*core::f32::consts::PI*float_small_n)/float_large_n);
}

filter
}
3 changes: 3 additions & 0 deletions src/filters_and_windows/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pub mod blackman;
pub mod blackman_nuttall;
pub mod gaussian_window;
pub mod hamming;
pub mod triangle;
Empty file added src/filters_and_windows/test.rs
Empty file.
35 changes: 35 additions & 0 deletions tests/blackman.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Test Triangle Window

use superdsp::filters_and_windows::{blackman};

const N_SHORT: usize = 16;
const N_LONG: usize = 64;
#[test]
pub fn blackman_window_short(){
let expected = [
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 0.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 0.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 1.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 1.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 2.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 2.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 3.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 3.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 4.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 4.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 5.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 5.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 6.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 6.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 7.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 7.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 8.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 8.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 9.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 9.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 10.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 10.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 11.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 11.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 12.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 12.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 13.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 13.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 14.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 14.0) / 16.0),
0.42 - 0.5 * f32::cos((2.0 * std::f32::consts::PI * 15.0) / 16.0) + 0.08 * f32::cos((4.0 * std::f32::consts::PI * 15.0) / 16.0)
];

let window = blackman::blackman_window::<N_SHORT>(0);
assert_eq!(window.len(), N_SHORT);

// make sure the window is correct to 4 decimal places (floating point error)
for i in 0..N_SHORT {
assert!((window[i] - expected[i]).abs() < 0.0001);
}
}
39 changes: 39 additions & 0 deletions tests/gaussian_window.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use superdsp::filters_and_windows::gaussian_window;

const N_SHORT: usize = 16;
const N_LONG: usize = 64;
const SIGMA: f32 = 0.4;

#[test]
pub fn gaussian_window_short(){
// Expected values for a gaussian window with N = 16 and sigma = 0.4
let expected: [f32; 16] = [
0.04394,
0.09136,
0.17242,
0.29502,
0.45783,
0.64439,
0.82258,
0.95234,
1.0,
0.95234,
0.82258,
0.64439,
0.45783,
0.29502,
0.17242,
0.09136,
];

let window = gaussian_window::gaussian_window::<N_SHORT>(SIGMA);
assert_eq!(window.len(), N_SHORT);

// make sure the window is correct to 4 decimal places (floating point error)
for i in 0..N_SHORT {
assert!((window[i] - expected[i]).abs() < 0.0001);
}
}



118 changes: 118 additions & 0 deletions tests/hamming.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Test Triangle Window

use superdsp::filters_and_windows::hamming;

const N_SHORT: usize = 16;
const N_LONG: usize = 64;
#[test]
pub fn triangle_window_short(){
let expected = [
0.08696,
0.12171,
0.22067,
0.36877,
0.54348,
0.71818,
0.86629,
0.96525,
1.0,
0.96525,
0.86629,
0.71818,
0.54348,
0.36877,
0.22067,
0.12171
];

let window = hamming::triangle_window::<N_SHORT>(N_SHORT, 0);
assert_eq!(window.len(), N_SHORT);

// make sure the window is correct to 3 decimal places (floating point error)
for i in 0..N_SHORT {
let expected_value = expected[i];
let got_value = window[i];
println!("Testing {i}, expecting {expected_value} and got {got_value}.");
assert!((window[i] - expected[i]).abs() < 0.001);
}
}

#[test]
fn triangle_window_long(){
let expected = [
0.0,
0.03125,
0.0625,
0.09375,
0.125,
0.15625,
0.1875,
0.21875,
0.25,
0.28125,
0.3125,
0.34375,
0.375,
0.40625,
0.4375,
0.46875,
0.5,
0.53125,
0.5625,
0.59375,
0.625,
0.65625,
0.6875,
0.71875,
0.75,
0.78125,
0.8125,
0.84375,
0.875,
0.90625,
0.9375,
0.96875,
1.0,
0.96875,
0.9375,
0.90625,
0.875,
0.84375,
0.8125,
0.78125,
0.75,
0.71875,
0.6875,
0.65625,
0.625,
0.59375,
0.5625,
0.53125,
0.5,
0.46875,
0.4375,
0.40625,
0.375,
0.34375,
0.3125,
0.28125,
0.25,
0.21875,
0.1875,
0.15625,
0.125,
0.09375,
0.0625,
0.03125
];

let window = hamming::triangle_window::<N_LONG>(N_LONG, 0);
assert_eq!(window.len(), N_LONG);

// make sure the window is correct to 4 decimal places (floating point error)
for i in 0..N_LONG {
println!("{}: {}", i, window[i]);
assert!((window[i] - expected[i]).abs() < 0.0001);
}
}

0 comments on commit 752392e

Please sign in to comment.