mod common;
#[test]
fn test_mel_spectrogram_matches_librosa() {
let ref_data = common::load_audio_reference("mel_spectrogram.json");
let sr = ref_data["sample_rate"].as_u64().unwrap() as f64;
let n_fft = ref_data["n_fft"].as_u64().unwrap() as usize;
let hop_length = ref_data["hop_length"].as_u64().unwrap() as usize;
let n_mels = ref_data["n_mels"].as_u64().unwrap() as usize;
let power = ref_data["power"].as_f64().unwrap();
let expected_n_frames = ref_data["n_frames"].as_u64().unwrap() as usize;
let wav = common::wav_path("20_Pink Noise mono 500Hz_2kHz -20dBFS 48k.wav");
let (samples, _wav_sr) = common::read_wav_mono(&wav);
let mut params = rosa::stft::MelSpectrogramParams::new(sr);
params.stft = rosa::stft::StftParams::new(n_fft);
assert_eq!(params.stft.hop_length, hop_length);
params.mel.n_mels = n_mels;
params.power = power;
let mel_spec = rosa::stft::mel_spectrogram(&samples, ¶ms);
assert_eq!(
mel_spec.rows(),
n_mels,
"n_mels mismatch: got {}, expected {}",
mel_spec.rows(),
n_mels
);
assert_eq!(
mel_spec.cols(),
expected_n_frames,
"n_frames mismatch: got {}, expected {}",
mel_spec.cols(),
expected_n_frames
);
let frames = ref_data["frames"].as_array().unwrap();
assert!(!frames.is_empty(), "No reference frames found");
for frame_ref in frames {
let idx = frame_ref["index"].as_u64().unwrap() as usize;
let expected_mel: Vec<f64> =
serde_json::from_value(frame_ref["mel_spectrum"].clone()).unwrap();
assert_eq!(expected_mel.len(), n_mels);
let actual_mel: Vec<f64> = (0..n_mels).map(|bin| mel_spec[(bin, idx)]).collect();
common::assert_approx_eq(
&actual_mel,
&expected_mel,
1e-4,
&format!("mel spectrogram frame {idx}"),
);
}
}