test(audio): implement automated 440 Hz audio loopback CI verification test

This commit is contained in:
katR 2026-09-29 21:12:17 +05:30
parent 7f6828df0c
commit c0d884bf94

View file

@ -0,0 +1,53 @@
// 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)"
);
}