use opus_rs::OpusDecoder;
use std::fs;
struct RefData {
packets: Vec<Vec<u8>>,
ref_pcm: Vec<f32>,
frame_size: usize,
sampling_rate: i32,
channels: usize,
}
fn load_ref(path_prefix: &str, sampling_rate: i32, channels: usize) -> Option<RefData> {
let pkt_path = format!("/tmp/opus_ref/{}.pkts", path_prefix);
let pcm_path = format!("/tmp/opus_ref/{}.pcm", path_prefix);
let pkt_raw = fs::read(&pkt_path).ok()?;
let pcm_raw = fs::read(&pcm_path).ok()?;
let frame_size = (sampling_rate / 50) as usize; let mut packets = Vec::new();
let mut pos = 0;
while pos + 2 <= pkt_raw.len() {
let n = u16::from_le_bytes([pkt_raw[pos], pkt_raw[pos + 1]]) as usize;
pos += 2;
if pos + n > pkt_raw.len() {
break;
}
packets.push(pkt_raw[pos..pos + n].to_vec());
pos += n;
}
let ref_pcm: Vec<f32> = pcm_raw
.chunks_exact(4)
.map(|c| f32::from_le_bytes(c.try_into().unwrap()))
.collect();
Some(RefData {
packets,
ref_pcm,
frame_size,
sampling_rate,
channels,
})
}
fn run_diff(label: &str, data: &RefData) {
let mut dec = OpusDecoder::new(data.sampling_rate, data.channels).unwrap();
let fs_ch = data.frame_size * data.channels;
let mut rust_pcm: Vec<f32> = Vec::new();
for pkt in &data.packets {
let mut buf = vec![0.0f32; fs_ch * 2];
match dec.decode(pkt, data.frame_size, &mut buf) {
Ok(n) => rust_pcm.extend_from_slice(&buf[..n * data.channels]),
Err(e) => {
panic!("{}: decode error on packet (toc={:02x}): {}", label, pkt[0], e);
}
}
}
let n_frames = data.packets.len();
let fs_ch = data.frame_size * data.channels;
let mut n_exact = 0usize;
let mut n_good = 0usize;
let mut n_bad = 0usize;
let mut worst_snr = f64::MAX;
let mut worst_frame = 0usize;
for f in 0..n_frames {
let r_start = f * fs_ch;
let ref_start = f * fs_ch;
if r_start + fs_ch > rust_pcm.len() || ref_start + fs_ch > data.ref_pcm.len() {
break;
}
let r_frame = &rust_pcm[r_start..r_start + fs_ch];
let f_frame = &data.ref_pcm[ref_start..ref_start + fs_ch];
let mut best_snr = f64::MIN;
for lag in -30i32..=30i32 {
let lag = lag as isize;
let (rs, fs): (&[f32], &[f32]) = if lag >= 0 {
let l = lag as usize;
if l >= fs_ch { continue; }
(&r_frame[l..], &f_frame[..fs_ch - l])
} else {
let l = (-lag) as usize;
if l >= fs_ch { continue; }
(&r_frame[..fs_ch - l], &f_frame[l..])
};
let m = rs.len().min(fs.len());
if m < 10 { continue; }
let mut ef = 0.0f64; let mut err = 0.0f64;
for i in 0..m {
let r = rs[i] as f64; let f = fs[i] as f64;
ef += f * f; err += (r - f) * (r - f);
}
if ef > 0.0 {
let snr = if err > 1e-30 { 10.0 * (ef / err).log10() } else { 999.0 };
if snr > best_snr { best_snr = snr; }
}
}
if best_snr > 100.0 {
n_exact += 1;
} else if best_snr > 40.0 {
n_good += 1;
} else {
n_bad += 1;
if best_snr < worst_snr {
worst_snr = best_snr;
worst_frame = f;
}
}
}
println!(
"{}: {} frames — exact(>100dB):{}, good(>40dB):{}, bad(<40dB):{} | worst: frame {} @ {:.1}dB",
label, n_frames, n_exact, n_good, n_bad, worst_frame, worst_snr
);
}
#[test]
fn diff_silk_mono() {
if let Some(data) = load_ref("silk_m", 16000, 1) {
run_diff("SILK mono 16kHz", &data);
} else {
eprintln!("skipping diff_silk_mono (no ref files)");
}
}
#[test]
fn diff_silk_stereo() {
if let Some(data) = load_ref("silk_s", 16000, 2) {
run_diff("SILK stereo 16kHz", &data);
let mut dec = OpusDecoder::new(16000, 2).unwrap();
if let Some(pkt) = data.packets.first() {
let mut buf = vec![0.0f32; 320 * 2];
if let Ok(n) = dec.decode(pkt, 320, &mut buf) {
let mut max_diff = 0.0f32;
for i in 0..n {
max_diff = max_diff.max((buf[i * 2] - buf[i * 2 + 1]).abs());
}
println!("SILK stereo max |L-R| = {:.6} (should be > 0 for M/S)", max_diff);
assert!(max_diff > 0.001, "L and R must differ for stereo M/S decode");
}
}
} else {
eprintln!("skipping diff_silk_stereo (no ref files)");
}
}
#[test]
fn diff_celt_mono() {
if let Some(data) = load_ref("celt_m", 48000, 1) {
run_diff("CELT mono 48kHz", &data);
} else {
eprintln!("skipping diff_celt_mono (no ref files)");
}
}
#[test]
fn diff_celt_stereo() {
if let Some(data) = load_ref("celt_s", 48000, 2) {
run_diff("CELT stereo 48kHz", &data);
} else {
eprintln!("skipping diff_celt_stereo (no ref files)");
}
}
#[test]
fn diff_celt_16k() {
if let Some(data) = load_ref("celt16k", 16000, 1) {
run_diff("CELT mono 16kHz (downsample=3)", &data);
} else {
eprintln!("skipping diff_celt_16k (no ref files)");
}
}
#[test]
fn diff_hybrid_mono() {
if let Some(data) = load_ref("hybrid_m", 48000, 1) {
run_diff("Hybrid mono 48kHz", &data);
} else {
eprintln!("skipping diff_hybrid_mono (no ref files)");
}
}