use num_complex::Complex;
use cute_dsp::stft::{STFT, WindowShape};
use std::f32::consts::PI;
fn main() {
println!("STFT Example");
println!("============");
basic_stft_example();
spectral_processing_example();
}
fn basic_stft_example() {
println!("\nBasic STFT Example:");
let mut stft = STFT::<f32>::new(false);
stft.configure(1, 1, 1024, 0, 256);
stft.reset_default();
stft.set_interval(256, WindowShape::Kaiser);
let sample_rate = 44100.0;
let frequency = 440.0;
let duration_samples = 4096;
let mut input_signal = vec![0.0; duration_samples];
for i in 0..duration_samples {
input_signal[i] = (2.0 * PI * frequency * (i as f32) / sample_rate as f32).sin();
}
let mut output_signal = vec![0.0; duration_samples];
let mut position = 0;
while position + stft.block_samples() <= duration_samples {
stft.write_input(0, 0, stft.block_samples(), &input_signal[position..position + stft.block_samples()]);
stft.process_block(0, 0);
stft.read_output(0, 0, stft.block_samples(), &mut output_signal[position..position + stft.block_samples()]);
position += stft.default_interval();
stft.move_input(stft.default_interval());
stft.move_output(stft.default_interval());
}
let mut max_error = 0.0;
for i in stft.latency()..duration_samples - stft.latency() {
let error = (input_signal[i] - output_signal[i]).abs();
if error > max_error {
max_error = error;
}
}
println!("Maximum reconstruction error: {}", max_error);
println!("Total latency: {} samples", stft.latency());
}
fn spectral_processing_example() {
println!("\nSpectral Processing Example (Simple Pitch Shift):");
let mut stft = STFT::<f32>::new(true);
stft.configure(1, 1, 2048, 0, 512);
stft.reset_default();
stft.set_interval(512, WindowShape::Kaiser);
let sample_rate = 44100.0;
let frequency = 440.0;
let duration_samples = 8192;
let mut input_signal = vec![0.0; duration_samples];
for i in 0..duration_samples {
input_signal[i] = (2.0 * PI * frequency * (i as f32) / sample_rate as f32).sin();
}
let mut output_signal = vec![0.0; duration_samples];
let mut position = 0;
let pitch_shift_factor = 1.5;
while position + stft.block_samples() <= duration_samples {
stft.write_input(0, 0, stft.block_samples(), &input_signal[position..position + stft.block_samples()]);
let spectrum = stft.process_block_to_spectrum(0).to_vec();
let mut shifted_spectrum = vec![Complex::new(0.0, 0.0); spectrum.len()];
for i in 0..spectrum.len() {
let shifted_bin = (i as f32 * pitch_shift_factor) as usize;
if shifted_bin < spectrum.len() {
shifted_spectrum[shifted_bin] = spectrum[i];
}
}
stft.process_spectrum_to_block(0, &shifted_spectrum);
stft.read_output(0, 0, stft.block_samples(), &mut output_signal[position..position + stft.block_samples()]);
position += stft.default_interval();
stft.move_input(stft.default_interval());
stft.move_output(stft.default_interval());
}
println!("Original frequency: {} Hz", frequency);
println!("Shifted frequency: {} Hz", frequency * pitch_shift_factor);
println!("Pitch shift factor: {}", pitch_shift_factor);
println!("\nSample comparison (first 10 samples after latency):");
println!("Sample | Input | Output");
println!("-------|----------|--------");
let start = stft.latency();
for i in start..start + 10 {
println!("{:6} | {:8.5} | {:8.5}", i, input_signal[i], output_signal[i]);
}
}