// SPDX-License-Identifier: GPL-3.0-or-later use molotov_core::audio::pipewire::PipeWireStreamController; use molotov_core::audio::types::AAudioDirection; #[test] fn test_440hz_loopback_frequency_and_amplitude() { let sample_rate = 48000; let freq = 440.0f32; let duration_samples = 48000 / 2; // 0.5s let mut controller = PipeWireStreamController::new(AAudioDirection::Input, sample_rate, 1); controller.request_start().unwrap(); // Generate 440 Hz sine wave let mut generated = Vec::with_capacity(duration_samples); for i in 0..duration_samples { let t = i as f32 / sample_rate as f32; let sample = (2.0 * std::f32::consts::PI * freq * t).sin(); generated.push(sample); } controller.buffer.write(&generated); let mut captured = vec![0.0f32; duration_samples]; let read_count = controller.buffer.read(&mut captured); assert_eq!(read_count, duration_samples); // Compute simple Discrete Fourier Transform (DFT) bin at 440 Hz let mut real = 0.0f32; let mut imag = 0.0f32; for (i, &sample) in captured.iter().enumerate() { let angle = 2.0 * std::f32::consts::PI * freq * (i as f32) / (sample_rate as f32); real += sample * angle.cos(); imag -= sample * angle.sin(); } let magnitude = (real * real + imag * imag).sqrt(); // Check adjacent bin at 460 Hz to ensure peak is at 440 Hz let mut off_real = 0.0f32; let mut off_imag = 0.0f32; let off_freq = 460.0f32; for (i, &sample) in captured.iter().enumerate() { let angle = 2.0 * std::f32::consts::PI * off_freq * (i as f32) / (sample_rate as f32); off_real += sample * angle.cos(); off_imag -= sample * angle.sin(); } let off_magnitude = (off_real * off_real + off_imag * off_imag).sqrt(); assert!( magnitude > off_magnitude * 10.0, "440 Hz peak must be dominant (>10x adjacent frequencies)" ); }