use fdaf_aec::FdafAec;
fn main() {
println!("--- Running Basic Sine Wave AEC Simulation ---");
const SAMPLE_RATE: u32 = 16000;
const FFT_SIZE: usize = 1024;
const FRAME_SIZE: usize = FFT_SIZE / 2;
const STEP_SIZE: f32 = 0.05;
let mut aec = FdafAec::new(FFT_SIZE, STEP_SIZE);
let mut far_end_signal = Vec::new();
for i in 0..(SAMPLE_RATE * 2) { let t = i as f32 / SAMPLE_RATE as f32;
far_end_signal.push(0.6 * (2.0 * std::f32::consts::PI * 440.0 * t).sin());
}
let mut near_end_signal = vec![0.0; (SAMPLE_RATE * 2) as usize];
for i in (SAMPLE_RATE / 2) as usize..near_end_signal.len() {
let t = i as f32 / SAMPLE_RATE as f32;
near_end_signal[i] = 0.4 * (2.0 * std::f32::consts::PI * 880.0 * t).sin();
}
let echo_delay_samples = 128;
let echo_attenuation = 0.7;
let mut mic_signal = vec![0.0; far_end_signal.len()];
for i in echo_delay_samples..mic_signal.len() {
mic_signal[i] = near_end_signal[i] + far_end_signal[i - echo_delay_samples] * echo_attenuation;
}
let mut processed_signal = Vec::new();
for (mic_chunk, far_chunk) in mic_signal.chunks(FRAME_SIZE).zip(far_end_signal.chunks(FRAME_SIZE)) {
if mic_chunk.len() != FRAME_SIZE { break; }
let output_frame = aec.process(far_chunk, mic_chunk);
processed_signal.extend_from_slice(&output_frame);
}
println!("\n--- AEC Performance Analysis (RMS Energy) ---");
analyze_and_print_rms("Single-Talk (Echo Only)",
&mic_signal[.. (SAMPLE_RATE / 2) as usize],
&processed_signal[.. (SAMPLE_RATE / 2) as usize]);
analyze_and_print_rms("Double-Talk (Echo + Voice)",
&mic_signal[(SAMPLE_RATE / 2) as usize ..],
&processed_signal[(SAMPLE_RATE / 2) as usize ..]);
println!("\nExplanation:");
println!("- Single-Talk: The RMS of the processed signal should be significantly lower, showing echo removal.");
println!("- Double-Talk: The RMS should decrease (as echo is removed) but not go to zero, showing the near-end voice was preserved.");
}
fn rms(signal: &[f32]) -> f32 {
if signal.is_empty() { return 0.0; }
let sum_sq: f32 = signal.iter().map(|&x| x * x).sum();
(sum_sq / signal.len() as f32).sqrt()
}
fn analyze_and_print_rms(label: &str, before: &[f32], after: &[f32]) {
println!("\n[{}]", label);
println!(" - Before AEC: {:.6}", rms(before));
println!(" - After AEC: {:.6}", rms(after));
}