use cute_dsp::windows::{Kaiser, ApproximateConfinedGaussian, force_perfect_reconstruction};
use std::f32::consts::PI;
fn main() {
println!("Window Functions Example");
println!("=======================");
kaiser_window_example();
acg_window_example();
perfect_reconstruction_example();
window_comparison_example();
}
fn kaiser_window_example() {
println!("\nKaiser Window Example:");
let kaiser = Kaiser::new(6.0);
let mut window = vec![0.0f32; 64];
kaiser.fill(&mut window);
println!("Kaiser window values (beta=6.0):");
print_window_values(&window);
let kaiser_bw = Kaiser::with_bandwidth(2.5, true);
let mut window_bw = vec![0.0f32; 64];
kaiser_bw.fill(&mut window_bw);
println!("\nKaiser window values (bandwidth=2.5):");
print_window_values(&window_bw);
let bandwidth = 3.0;
let beta = Kaiser::bandwidth_to_beta(bandwidth, false);
let beta_heuristic = Kaiser::bandwidth_to_beta(bandwidth, true);
println!("\nBandwidth to beta conversion:");
println!("Bandwidth: {:.2}", bandwidth);
println!("Beta (direct): {:.4}", beta);
println!("Beta (with heuristic): {:.4}", beta_heuristic);
}
fn acg_window_example() {
println!("\nApproximate Confined Gaussian Window Example:");
let acg = ApproximateConfinedGaussian::new(0.2);
let mut window = vec![0.0f32; 64];
acg.fill(&mut window);
println!("ACG window values (sigma=0.2):");
print_window_values(&window);
let acg_bw = ApproximateConfinedGaussian::with_bandwidth(3.0);
let mut window_bw = vec![0.0f32; 64];
acg_bw.fill(&mut window_bw);
println!("\nACG window values (bandwidth=3.0):");
print_window_values(&window_bw);
let bandwidth = 2.5;
let sigma = ApproximateConfinedGaussian::bandwidth_to_sigma(bandwidth);
println!("\nBandwidth to sigma conversion:");
println!("Bandwidth: {:.2}", bandwidth);
println!("Sigma: {:.4}", sigma);
}
fn perfect_reconstruction_example() {
println!("\nPerfect Reconstruction Example:");
let kaiser = Kaiser::new(6.0);
let mut window = vec![0.0f32; 1024];
kaiser.fill(&mut window);
println!("Original window values (first 5):");
for i in 0..5 {
println!("Index {}: {:.6}", i, window[i]);
}
force_perfect_reconstruction(&mut window, 1024, 256);
println!("\nModified window values for perfect reconstruction (first 5):");
for i in 0..5 {
println!("Index {}: {:.6}", i, window[i]);
}
println!("\nVerifying perfect reconstruction:");
verify_perfect_reconstruction(&window, 256);
}
fn window_comparison_example() {
println!("\nWindow Function Comparison Example:");
let size = 128;
let mut kaiser_window = vec![0.0f32; size];
let mut acg_window = vec![0.0f32; size];
Kaiser::new(6.0).fill(&mut kaiser_window);
ApproximateConfinedGaussian::new(0.2).fill(&mut acg_window);
println!("Window properties comparison:");
let kaiser_energy = calculate_window_energy(&kaiser_window);
let acg_energy = calculate_window_energy(&acg_window);
println!("Kaiser window energy: {:.6}", kaiser_energy);
println!("ACG window energy: {:.6}", acg_energy);
let kaiser_enbw = calculate_enbw(&kaiser_window);
let acg_enbw = calculate_enbw(&acg_window);
println!("Kaiser window ENBW: {:.6}", kaiser_enbw);
println!("ACG window ENBW: {:.6}", acg_enbw);
let kaiser_scalloping = calculate_scalloping_loss(&kaiser_window);
let acg_scalloping = calculate_scalloping_loss(&acg_window);
println!("Kaiser window scalloping loss: {:.6} dB", kaiser_scalloping);
println!("ACG window scalloping loss: {:.6} dB", acg_scalloping);
}
fn print_window_values(window: &[f32]) {
let indices = [0, 1, 2, 3, window.len()/4, window.len()/2, window.len()*3/4, window.len()-4, window.len()-3, window.len()-2, window.len()-1];
for &i in &indices {
if i < window.len() {
println!("Index {}: {:.6}", i, window[i]);
}
}
}
fn verify_perfect_reconstruction(window: &[f32], hop_size: usize) {
let mut sum_squared = vec![0.0f32; hop_size];
for i in 0..window.len() {
sum_squared[i % hop_size] += window[i] * window[i];
}
let mut is_perfect = true;
for (i, &val) in sum_squared.iter().enumerate() {
println!("Hop {}: Sum of squares = {:.6}", i, val);
if (val - 1.0).abs() > 1e-5 {
is_perfect = false;
}
}
if is_perfect {
println!("Perfect reconstruction verified!");
} else {
println!("Perfect reconstruction not achieved.");
}
}
fn calculate_window_energy(window: &[f32]) -> f32 {
window.iter().map(|&x| x * x).sum::<f32>() / window.len() as f32
}
fn calculate_enbw(window: &[f32]) -> f32 {
let sum_squared = window.iter().map(|&x| x * x).sum::<f32>();
let sum = window.iter().sum::<f32>();
window.len() as f32 * sum_squared / (sum * sum)
}
fn calculate_scalloping_loss(window: &[f32]) -> f32 {
let n = window.len();
let mut sum = 0.0;
for i in 0..n {
sum += window[i] * (PI * (i as f32 + 0.5) / n as f32).cos();
}
20.0 * (sum / window.iter().sum::<f32>()).log10()
}