From 4aaf71502528f4ff13c2cf1bed3d398fc2e01c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Lucas?= Date: Fri, 4 Sep 2026 23:13:34 -0300 Subject: [PATCH 01/30] fix(mlow): match shipped DSP tuning and validate wasm vectors --- Cargo.lock | 63 +- wacore/Cargo.toml | 3 + wacore/src/voip/mlow/decoder.rs | 91 + wacore/src/voip/mlow/fixture.rs | 22 + wacore/src/voip/mlow/golden.rs | 10 +- wacore/src/voip/mlow/mod.rs | 2 + wacore/src/voip/mlow/param_decode_match.rs | 134 +- wacore/src/voip/mlow/quality_tests.rs | 78 +- wacore/src/voip/mlow/rangecoder.rs | 20 +- wacore/src/voip/mlow/smpl_celpdec.rs | 37 +- wacore/src/voip/mlow/smpl_gennoise.rs | 19 +- wacore/src/voip/mlow/smpl_harm_postfilter.rs | 120 +- wacore/src/voip/mlow/smpl_harmcomb.rs | 61 +- wacore/src/voip/mlow/smpl_lpc.rs | 89 +- wacore/src/voip/mlow/smpl_lsf_quant.rs | 40 +- wacore/src/voip/mlow/smpl_pitch_enc.rs | 144 +- wacore/src/voip/mlow/smpl_pulse.rs | 5 +- wacore/src/voip/mlow/smpl_signal_mode.rs | 97 +- wacore/src/voip/mlow/smpl_vad.rs | 67 + .../voip/mlow/testdata/e2e_vectors.cbor.zst | Bin 0 -> 228923 bytes .../src/voip/mlow/testdata/e2e_vectors.json | 1 - .../voip/mlow/testdata/exc_pre_lags.cbor.zst | Bin 0 -> 33028 bytes .../src/voip/mlow/testdata/exc_pre_lags.json | 1 - .../src/voip/mlow/testdata/fe_dump.cbor.zst | Bin 0 -> 199182 bytes wacore/src/voip/mlow/testdata/fe_dump.json | 282 - .../testdata/gennoise_params_dump.cbor.zst | Bin 0 -> 1136 bytes .../mlow/testdata/gennoise_params_dump.json | 1 - .../mlow/testdata/gennoise_vectors.cbor.zst | Bin 0 -> 28923 bytes .../voip/mlow/testdata/gennoise_vectors.json | 1 - .../mlow/testdata/harm_postfilter_vectors.raw | Bin 857124 -> 0 bytes .../testdata/harm_postfilter_vectors.raw.zst | Bin 0 -> 619264 bytes .../mlow/testdata/hp_postfilter_vectors.raw | Bin 1297564 -> 0 bytes .../testdata/hp_postfilter_vectors.raw.zst | Bin 0 -> 123277 bytes .../voip/mlow/testdata/lsf_quant_io.cbor.zst | Bin 0 -> 22129 bytes .../src/voip/mlow/testdata/lsf_quant_io.json | 602 - .../voip/mlow/testdata/packed-fixtures.json | 150 + .../testdata/pitchio_ground_truth.cbor.zst | Bin 0 -> 530850 bytes .../mlow/testdata/pitchio_ground_truth.json | 602 - .../voip/mlow/testdata/pulse_vectors.cbor.zst | Bin 0 -> 31245 bytes .../src/voip/mlow/testdata/pulse_vectors.json | 1 - .../voip/mlow/testdata/rc_vectors.cbor.zst | Bin 0 -> 11760 bytes wacore/src/voip/mlow/testdata/rc_vectors.json | 17543 ---------------- .../testdata/sigmode_ground_truth.cbor.zst | Bin 0 -> 129968 bytes .../mlow/testdata/sigmode_ground_truth.json | 1 - .../src/voip/mlow/testdata/wasm-fixtures.json | 97 + .../testdata/wasm_derived_120ms_frames.json | 10 + .../mlow/testdata/wasm_derived_120ms_ref.raw | Bin 0 -> 30720 bytes .../mlow/testdata/wasm_derived_frames.json | 112 + .../voip/mlow/testdata/wasm_derived_ref.raw | Bin 0 -> 211200 bytes .../voip/mlow/testdata/wasm_derived_vad.json | 662 + .../src/voip/mlow/testdata/wasm_fe.cbor.zst | Bin 0 -> 1258019 bytes .../voip/mlow/testdata/wasm_gennoise.cbor.zst | Bin 0 -> 1040001 bytes .../testdata/wasm_harm_postfilter.cbor.zst | Bin 0 -> 659553 bytes .../mlow/testdata/wasm_hp_postfilter.cbor.zst | Bin 0 -> 1252990 bytes .../mlow/testdata/wasm_lsf_quant.cbor.zst | Bin 0 -> 523632 bytes .../voip/mlow/testdata/wasm_params.cbor.zst | Bin 0 -> 23913 bytes .../voip/mlow/testdata/wasm_pitch.cbor.zst | Bin 0 -> 770099 bytes .../mlow/testdata/wasm_signal_mode.cbor.zst | Bin 0 -> 331621 bytes 58 files changed, 2078 insertions(+), 19090 deletions(-) create mode 100644 wacore/src/voip/mlow/fixture.rs create mode 100644 wacore/src/voip/mlow/testdata/e2e_vectors.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/e2e_vectors.json create mode 100644 wacore/src/voip/mlow/testdata/exc_pre_lags.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/exc_pre_lags.json create mode 100644 wacore/src/voip/mlow/testdata/fe_dump.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/fe_dump.json create mode 100644 wacore/src/voip/mlow/testdata/gennoise_params_dump.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/gennoise_params_dump.json create mode 100644 wacore/src/voip/mlow/testdata/gennoise_vectors.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/gennoise_vectors.json delete mode 100644 wacore/src/voip/mlow/testdata/harm_postfilter_vectors.raw create mode 100644 wacore/src/voip/mlow/testdata/harm_postfilter_vectors.raw.zst delete mode 100644 wacore/src/voip/mlow/testdata/hp_postfilter_vectors.raw create mode 100644 wacore/src/voip/mlow/testdata/hp_postfilter_vectors.raw.zst create mode 100644 wacore/src/voip/mlow/testdata/lsf_quant_io.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/lsf_quant_io.json create mode 100644 wacore/src/voip/mlow/testdata/packed-fixtures.json create mode 100644 wacore/src/voip/mlow/testdata/pitchio_ground_truth.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/pitchio_ground_truth.json create mode 100644 wacore/src/voip/mlow/testdata/pulse_vectors.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/pulse_vectors.json create mode 100644 wacore/src/voip/mlow/testdata/rc_vectors.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/rc_vectors.json create mode 100644 wacore/src/voip/mlow/testdata/sigmode_ground_truth.cbor.zst delete mode 100644 wacore/src/voip/mlow/testdata/sigmode_ground_truth.json create mode 100644 wacore/src/voip/mlow/testdata/wasm-fixtures.json create mode 100644 wacore/src/voip/mlow/testdata/wasm_derived_120ms_frames.json create mode 100644 wacore/src/voip/mlow/testdata/wasm_derived_120ms_ref.raw create mode 100644 wacore/src/voip/mlow/testdata/wasm_derived_frames.json create mode 100644 wacore/src/voip/mlow/testdata/wasm_derived_ref.raw create mode 100644 wacore/src/voip/mlow/testdata/wasm_derived_vad.json create mode 100644 wacore/src/voip/mlow/testdata/wasm_fe.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_gennoise.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_harm_postfilter.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_hp_postfilter.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_lsf_quant.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_params.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_pitch.cbor.zst create mode 100644 wacore/src/voip/mlow/testdata/wasm_signal_mode.cbor.zst diff --git a/Cargo.lock b/Cargo.lock index 43ae39ff9..d7c0c0e8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,6 +566,33 @@ dependencies = [ "serde", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -844,6 +871,12 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -1519,6 +1552,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbag" version = "0.1.13" @@ -3128,6 +3172,15 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ruzstd" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" +dependencies = [ + "twox-hash", +] + [[package]] name = "same-file" version = "1.0.6" @@ -3483,7 +3536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -3807,6 +3860,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "twox-hash" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" + [[package]] name = "typenum" version = "1.20.1" @@ -3939,6 +3998,7 @@ dependencies = [ "bytes", "cbc", "chrono", + "ciborium", "codspeed-divan-compat", "compact_str", "ctr 0.10.1", @@ -3957,6 +4017,7 @@ dependencies = [ "metrics", "portable-atomic", "rand 0.10.2", + "ruzstd", "serde", "serde-big-array", "serde_json", diff --git a/wacore/Cargo.toml b/wacore/Cargo.toml index 30e2065fa..951ffb4c6 100644 --- a/wacore/Cargo.toml +++ b/wacore/Cargo.toml @@ -105,6 +105,9 @@ buffa-build = { workspace = true } sha2 = { workspace = true } [dev-dependencies] +# Compact oracle fixtures; pure Rust, test-only, including on wasm targets. +ciborium = "0.2.2" +ruzstd = "0.8.3" divan = { workspace = true } # Compression only: the runtime inflates through `wacore_binary::zlib_pool` # (zlib-rs directly), so flate2 stays out of the release dependency set. diff --git a/wacore/src/voip/mlow/decoder.rs b/wacore/src/voip/mlow/decoder.rs index 940675b44..a4abfe8db 100644 --- a/wacore/src/voip/mlow/decoder.rs +++ b/wacore/src/voip/mlow/decoder.rs @@ -831,6 +831,56 @@ mod tests { ); } + /// Same DTX-off property as above, but both halves come from the shipped + /// engine (`oracle derive --spec specs/mlow_110frames.json` in unwasm; + /// see PROVENANCE.md): the `0x10` frames it encoded over the silent + /// stretches must decode (here) to audio matching what it decoded + /// itself — a coded-inactive frame carries a decodable body, and the + /// lengths differ per side (DTX routes short), so this compares per-frame + /// RMS instead of concatenated spans. + #[test] + fn wasm_derived_dtx_frames_decode_to_audio() { + let frames: Vec = + serde_json::from_str(include_str!("testdata/wasm_derived_frames.json")) + .expect("wasm_derived_frames.json"); + let refp: Vec = include_bytes!("testdata/wasm_derived_ref.raw") + .chunks_exact(2) + .map(|b| i16::from_le_bytes([b[0], b[1]]) as f32 / 32768.0) + .collect(); + + let mut dec = MlowDecoder::new(); + let mut n_dtx = 0usize; + let mut n_audible = 0usize; + for (k, hex_frame) in frames.iter().enumerate() { + let frame = hex::decode(hex_frame).unwrap(); + let out = dec.decode(&frame); + if frame[0] & 0xC2 != 0 { + continue; + } + n_dtx += 1; + assert!(!out.is_empty(), "frame {k}: DTX frame decoded empty"); + let expected = &refp[k * 960..(k + 1) * 960]; + let rms = |v: &[f32]| { + (v.iter().map(|&x| (x as f64) * (x as f64)).sum::() / v.len() as f64).sqrt() + }; + let (e_out, e_ref) = (rms(&out), rms(expected)); + if e_ref < 0.005 { + assert!( + e_out < 0.02, + "frame {k}: silent ref decoded loud at {e_out:.4}" + ); + continue; + } + n_audible += 1; + assert!( + e_out > e_ref * 0.5, + "frame {k}: DTX frame decoded to {e_out:.5} rms against ref {e_ref:.5}" + ); + } + assert!(n_dtx > 0, "fixture lost its DTX frames"); + assert!(n_audible > 0, "no audible DTX reference to compare against"); + } + /// A stream that ends where it claims to must be accepted. This is the guard against the /// endpoint check being too strict: the synthetic 120 ms vector is a well-formed six-frame /// packet, and rejecting it would silence audio that decodes correctly. @@ -989,6 +1039,47 @@ mod tests { assert!(corr > 0.999, "lag-0 corr {corr:.6} vs reference"); } + /// Same shape as above, but both halves come from the shipped engine + /// (`oracle derive --spec specs/mlow_120ms.json` in unwasm; see + /// PROVENANCE.md): 8 120 ms packets it encoded itself, plus the PCM it + /// decoded back. Correlation (not 0.999): our decoder and theirs agree + /// closely on the same packets without sharing lineage — the 0.9874 + /// measured atlock time is the number to beat, with margin. + #[test] + fn wasm_derived_120ms_decode_matches_wasm_reference() { + let frames: Vec = + serde_json::from_str(include_str!("testdata/wasm_derived_120ms_frames.json")) + .expect("wasm_derived_120ms_frames.json"); + let refp: Vec = include_bytes!("testdata/wasm_derived_120ms_ref.raw") + .chunks_exact(2) + .map(|b| i16::from_le_bytes([b[0], b[1]]) as f32 / 32768.0) + .collect(); + + let mut dec = MlowDecoder::new(); + let mut out: Vec = Vec::new(); + for hex_frame in &frames { + let frame = hex::decode(hex_frame).unwrap(); + assert_eq!(frame[0], 0x58, "the fixture must stay 120 ms packets"); + out.extend_from_slice(&dec.decode(&frame)); + } + assert_eq!(out.len(), refp.len(), "decode length vs reference"); + + let n = refp.len(); + let (mr, mo) = ( + refp.iter().map(|&v| v as f64).sum::() / n as f64, + out.iter().map(|&v| v as f64).sum::() / n as f64, + ); + let (mut sxy, mut sxx, mut syy) = (0f64, 0f64, 0f64); + for i in 0..n { + let (dr, dz) = (refp[i] as f64 - mr, out[i] as f64 - mo); + sxy += dr * dz; + sxx += dr * dr; + syy += dz * dz; + } + let corr = sxy / (sxx * syy).sqrt(); + assert!(corr > 0.95, "lag-0 corr {corr:.6} vs shipped reference"); + } + /// Decoding a multi-frame packet must leave the cross-frame predictor usable: a real 60 ms frame /// after it still has to produce audio. #[test] diff --git a/wacore/src/voip/mlow/fixture.rs b/wacore/src/voip/mlow/fixture.rs new file mode 100644 index 000000000..05697bf86 --- /dev/null +++ b/wacore/src/voip/mlow/fixture.rs @@ -0,0 +1,22 @@ +//! Test-only reader for losslessly packed oracle fixtures. + +use std::io::Read; + +pub(super) fn decode( + packed: &[u8], +) -> Result> { + let bytes = inflate(packed)?; + let mut reader = bytes.as_slice(); + let value = ciborium::de::from_reader(&mut reader)?; + if !reader.is_empty() { + return Err("trailing bytes after the fixture CBOR value".into()); + } + Ok(value) +} + +pub(super) fn inflate(packed: &[u8]) -> Result, Box> { + let mut decoder = ruzstd::decoding::StreamingDecoder::new(packed)?; + let mut bytes = Vec::new(); + decoder.read_to_end(&mut bytes)?; + Ok(bytes) +} diff --git a/wacore/src/voip/mlow/golden.rs b/wacore/src/voip/mlow/golden.rs index 1f0e7c7c2..49ea97b2b 100644 --- a/wacore/src/voip/mlow/golden.rs +++ b/wacore/src/voip/mlow/golden.rs @@ -112,12 +112,14 @@ const GOLDEN_CLIP: f32 = 0.0; // one build: the encoder resolves ties on f32 comparisons, so the bitstream is a function of the // arithmetic the compiler emits, not only of the source. Changing `-C target-cpu` alone moves these // constants. They are a drift tripwire on the CI target, not a portable identity of the codec. -const GOLDEN_RMS: f32 = 0.156401; -const GOLDEN_PEAK: f32 = 0.524200; -const GOLDEN_CHECKSUM: u64 = 0x4302_cced_6791_52b4; +// Regenerated after the shipped LPC/VUV/pitch/harmonic tuning and the LPC +// f64 regularization fix. Independent wasm kernel tests pin those changes. +const GOLDEN_RMS: f32 = 0.155180; +const GOLDEN_PEAK: f32 = 0.513214; +const GOLDEN_CHECKSUM: u64 = 0x5f7a_a0e3_d0d9_5e7e; // Pins the ENCODER bitstream independently of the decoder: fnv1a over the concatenation of every // emitted packet's wire bytes. Drift here means the encoder changed even if decode output did not. -const GOLDEN_FRAMES_CHECKSUM: u64 = 0x5583_7f25_b89a_0621; +const GOLDEN_FRAMES_CHECKSUM: u64 = 0x83de_fbfb_b2b8_68b2; /// Encode then decode the whole corpus, returning the decoded i16 output and the concatenated /// packet bytes. diff --git a/wacore/src/voip/mlow/mod.rs b/wacore/src/voip/mlow/mod.rs index 0d54e9c39..db059d841 100644 --- a/wacore/src/voip/mlow/mod.rs +++ b/wacore/src/voip/mlow/mod.rs @@ -10,6 +10,8 @@ mod analysis; mod decoder; mod encode; +#[cfg(test)] +mod fixture; mod golden; mod multiframe; mod param_decode_match; diff --git a/wacore/src/voip/mlow/param_decode_match.rs b/wacore/src/voip/mlow/param_decode_match.rs index f22a3c1dd..fc70a8be4 100644 --- a/wacore/src/voip/mlow/param_decode_match.rs +++ b/wacore/src/voip/mlow/param_decode_match.rs @@ -13,8 +13,10 @@ use std::collections::HashMap; #[test] fn nrgres_fcbg_match_c_reference() { - let cdump: Value = - serde_json::from_str(include_str!("testdata/gennoise_params_dump.json")).unwrap(); + let cdump: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/gennoise_params_dump.cbor.zst" + )) + .unwrap(); let carr = cdump.as_array().unwrap(); let mut cmap: HashMap<(i64, i64, i64), &Value> = HashMap::new(); for c in carr { @@ -86,3 +88,131 @@ fn nrgres_fcbg_match_c_reference() { "coverage too thin: class={voiced_class} uv_nrgres={uv_nrgres} uv_fcbg={uv_fcbg} v_fcbg={v_fcbg}" ); } + +#[test] +fn all_wire_parameters_match_shipped_wasm() { + use super::rangecoder::RangeDecoder; + use super::smpl_cc_tables::load_cc_tables; + use super::smpl_decode::{SmplLsfState, decode_smpl_lsf, load_smpl_tables}; + use super::smpl_gains::decode_smpl_gains; + use super::smpl_mem::load_smpl_mem; + use super::smpl_pitch::decode_smpl_pitch; + use super::smpl_pulse::decode_smpl_pulses; + use super::toc::parse_mlow_toc; + + let frames: Vec = + serde_json::from_str(include_str!("testdata/wasm_derived_frames.json")).unwrap(); + let records: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_params.cbor.zst")) + .expect("wasm wire parameters"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), frames.len() * 3); + let ints = |v: &Value| { + v.as_array() + .unwrap() + .iter() + .map(|x| x.as_i64().unwrap() as i32) + .collect::>() + }; + let tables = load_smpl_tables(); + let cc = load_cc_tables(); + let mem = load_smpl_mem(); + let mut state = SmplLsfState::default(); + let mut voiced_count = 0; + let mut unvoiced_count = 0; + for (packet, hex) in frames.iter().enumerate() { + let frame = hex::decode(hex).unwrap(); + let toc = parse_mlow_toc(frame[0]); + let mut decoder = RangeDecoder::new(&frame[1..]); + for internal in 0..3 { + let r = &records[packet * 3 + internal]; + assert_eq!(r["len"].as_i64().unwrap(), 320); + assert_eq!(r["subframes"].as_i64().unwrap(), 4); + assert_eq!(r["frame"].as_u64().unwrap() as usize, internal); + assert_eq!(r["cav"].as_i64().unwrap() != 0, toc.active); + let lsf = decode_smpl_lsf(&mut decoder, tables, &mut state, 0, internal, toc.active); + assert_eq!( + lsf.stage1, + r["voiced"].as_i64().unwrap() as i32, + "packet {packet}/{internal}: voiced" + ); + let mut indices = vec![lsf.grid]; + indices.extend(lsf.stage2); + assert_eq!(indices, ints(&r["lsf"]), "packet {packet}/{internal}: LSF"); + assert_eq!( + lsf.extra, + r["interp"].as_i64().unwrap() as i32, + "packet {packet}/{internal}: interpolation" + ); + let pulses = decode_smpl_pulses( + &mut decoder, + cc, + 320, + 4, + i32::from(toc.active), + 0, + lsf.stage1, + ); + assert_eq!( + pulses.pulses, + ints(&r["pulses"]), + "packet {packet}/{internal}: pulse positions/magnitudes" + ); + assert_eq!( + pulses.subfr.to_vec(), + ints(&r["sf_pulses"]), + "packet {packet}/{internal}: pulse counts" + ); + let fcbg = if lsf.stage1 == 1 { + voiced_count += 1; + let pitch = + decode_smpl_pitch(&mut decoder, mem, cc, &mut state, 320, 4, 0, pulses.subfr); + assert_eq!( + pitch.gain_idx.to_vec(), + ints(&r["acbg"]), + "packet {packet}/{internal}: ACB gain" + ); + assert_eq!( + pitch.block_lags.to_vec(), + ints(&r["lags"]), + "packet {packet}/{internal}: pitch lags" + ); + assert_eq!( + pitch.contour, + r["contour"].as_i64().unwrap() as i32, + "packet {packet}/{internal}: contour" + ); + pitch.filt_idx + } else { + unvoiced_count += 1; + let gains = decode_smpl_gains(&mut decoder, cc, 4, pulses.subfr); + assert_eq!( + gains.gain_q.to_vec(), + ints(&r["energy_q14"]), + "packet {packet}/{internal}: gain Q14" + ); + gains.nrg_res + }; + for (sf, expected) in ints(&r["fcbg"]).iter().enumerate() { + if pulses.subfr[sf] > 0 { + assert_eq!( + fcbg[sf], *expected, + "packet {packet}/{internal}/{sf}: FCB gain" + ); + } + } + let range = r["range"] + .as_array() + .unwrap() + .iter() + .map(|x| x.as_u64().unwrap() as u32) + .collect::>(); + assert_eq!( + decoder.oracle_state().to_vec(), + range, + "packet {packet}/{internal}: entropy context" + ); + } + } + assert!(voiced_count > 0 && unvoiced_count > 0); +} diff --git a/wacore/src/voip/mlow/quality_tests.rs b/wacore/src/voip/mlow/quality_tests.rs index 2757e4a40..53a20ac92 100644 --- a/wacore/src/voip/mlow/quality_tests.rs +++ b/wacore/src/voip/mlow/quality_tests.rs @@ -589,7 +589,8 @@ fn voiced_fundamental_survives_in_spectrum() { #[test] fn decoder_tracks_energy_envelope() { let recs: serde_json::Value = - serde_json::from_str(include_str!("testdata/e2e_vectors.json")).expect("e2e_vectors"); + crate::voip::mlow::fixture::decode(include_bytes!("testdata/e2e_vectors.cbor.zst")) + .expect("e2e_vectors"); let arr = recs.as_array().unwrap(); let mut dec = MlowDecoder::new(); let mut active_pairs: Vec<(f64, f64)> = Vec::new(); // (ref_rms, rust_rms) @@ -645,7 +646,8 @@ fn decoder_tracks_energy_envelope() { #[test] fn decoder_silence_frames_produce_zero() { let recs: serde_json::Value = - serde_json::from_str(include_str!("testdata/e2e_vectors.json")).expect("e2e_vectors"); + crate::voip::mlow::fixture::decode(include_bytes!("testdata/e2e_vectors.cbor.zst")) + .expect("e2e_vectors"); let arr = recs.as_array().unwrap(); let mut dec = MlowDecoder::new(); @@ -817,3 +819,75 @@ fn inbound_capture_frames_cover_config1_and_config2_tocs() { "fixture lost active config-0 (0x50) frames: capture is not a normal call stream" ); } + +/// The wasm-derived oracle pair: `wasm_derived_frames.json` is the shipped +/// VoIP engine's own encode of `synth_mic.raw` (derived with +/// `oracle derive --spec specs/mlow_110frames.json` in unwasm, pinned by +/// module hash — see PROVENANCE.md), and `wasm_derived_ref.raw` is the same +/// engine's decode of those packets, 960 s16le samples per frame. +/// +/// Compares our decoder with the shipped decoder on the shipped encoder's +/// packets. Correlation allows numeric differences in DSP implementations; +/// the independent C oracle remains covered by the adjacent fixture tests. +#[test] +fn wasm_derived_frames_decode_to_wasm_reference() { + let frames: Vec = + serde_json::from_str(include_str!("testdata/wasm_derived_frames.json")) + .expect("wasm_derived_frames.json"); + let refp: Vec = include_bytes!("testdata/wasm_derived_ref.raw") + .chunks_exact(2) + .map(|b| i16::from_le_bytes([b[0], b[1]]) as f32 / 32768.0) + .collect(); + assert_eq!( + refp.len(), + frames.len() * 960, + "ref must hold 960 samples/frame" + ); + + let mut dec = MlowDecoder::new(); + let mut n_active = 0usize; + let mut corr_sum = 0.0f64; + let mut worst_corr = 1.0f64; + for (k, hex_frame) in frames.iter().enumerate() { + let frame = hex::decode(hex_frame).unwrap(); + let out = dec.decode(&frame); + assert!(!out.is_empty(), "frame {k}: decoder returned nothing"); + // DTX/CN frames route short; only active frames carry 960 comparable samples. + if out.len() != 960 { + continue; + } + let expected = &refp[k * 960..(k + 1) * 960]; + let (e_out, e_ref) = (rms(&out), rms(expected)); + if e_ref < 0.005 { + // Quiet in, quiet out: correlation is undefined on near-silence + // (`corr` returns 0.0), so assert the envelope instead. + assert!( + e_out < 0.02, + "frame {k}: quiet ref {e_ref:.4} decoded loud at {e_out:.4}" + ); + continue; + } + let c = corr(&out, expected); + worst_corr = worst_corr.min(c); + corr_sum += c; + n_active += 1; + assert!( + (0.25..4.0).contains(&(e_out / e_ref)), + "frame {k}: energy ratio out {e_out:.4} vs ref {e_ref:.4} outside 4x band" + ); + } + assert!( + n_active > frames.len() / 2, + "only {n_active}/{} active frames; stream decoded short", + frames.len() + ); + let mean_corr = corr_sum / n_active as f64; + assert!( + mean_corr > 0.90, + "mean active-frame correlation {mean_corr:.4} too low against the shipped decoder" + ); + assert!( + worst_corr > 0.70, + "worst active-frame correlation {worst_corr:.4} too low against the shipped decoder" + ); +} diff --git a/wacore/src/voip/mlow/rangecoder.rs b/wacore/src/voip/mlow/rangecoder.rs index 8e1b7d3a2..c4222ad96 100644 --- a/wacore/src/voip/mlow/rangecoder.rs +++ b/wacore/src/voip/mlow/rangecoder.rs @@ -42,6 +42,24 @@ pub(crate) struct RangeDecoder<'a> { } impl<'a> RangeDecoder<'a> { + /// ec_dec words after the buffer pointer, for comparison with guest snapshots. + #[cfg(test)] + pub(crate) fn oracle_state(&self) -> [u32; 11] { + [ + self.storage, + self.end_offs, + self.end_window, + self.nend_bits as u32, + self.nbits_total as u32, + self.offs, + self.rng, + self.val, + self.ext, + self.rem as u32, + self.err as u32, + ] + } + /// RFC 6716 `ec_dec_init`. pub(crate) fn new(buf: &'a [u8]) -> Self { let mut d = RangeDecoder { @@ -636,7 +654,7 @@ mod tests { use serde_json::Value; fn vectors() -> Value { - serde_json::from_str(include_str!("testdata/rc_vectors.json")) + crate::voip::mlow::fixture::decode(include_bytes!("testdata/rc_vectors.cbor.zst")) .expect("rc_vectors.json must parse") } diff --git a/wacore/src/voip/mlow/smpl_celpdec.rs b/wacore/src/voip/mlow/smpl_celpdec.rs index 050d4d92b..be97e6de2 100644 --- a/wacore/src/voip/mlow/smpl_celpdec.rs +++ b/wacore/src/voip/mlow/smpl_celpdec.rs @@ -537,7 +537,26 @@ mod tests { /// the voiced ACB/LTP synthesis are faithful, independent of the PRNG-driven noise. #[test] fn exc_pre_matches_c() { - let recs: Value = serde_json::from_str(include_str!("testdata/exc_pre_lags.json")).unwrap(); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/exc_pre_lags.cbor.zst")) + .unwrap(); + let frames: Vec = + serde_json::from_str(include_str!("testdata/inbound_capture_frames.json")).unwrap(); + check_excitation(recs, frames, false); + } + + #[test] + fn excitation_matches_shipped_wasm() { + let records: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_gennoise.cbor.zst")) + .expect("wasm excitation"); + assert_eq!(records.as_array().unwrap().len(), 1320); + let frames: Vec = + serde_json::from_str(include_str!("testdata/wasm_derived_frames.json")).unwrap(); + check_excitation(records, frames, true); + } + + fn check_excitation(recs: Value, frames: Vec, include_inactive: bool) { let carr = recs.as_array().unwrap(); // Key the reference exc_pre by (packet, frame, sf). @@ -554,8 +573,6 @@ mod tests { ); } - let frames: Vec = - serde_json::from_str(include_str!("testdata/inbound_capture_frames.json")).unwrap(); let tbl = load_smpl_tables(); let synth_t = load_smpl_synth_tables(); let mem = load_smpl_mem(); @@ -572,15 +589,23 @@ mod tests { continue; } let toc = crate::voip::mlow::toc::parse_mlow_toc(frame[0]); - if toc.std_opus || toc.sid || !toc.active { + if toc.std_opus || toc.sid || (!include_inactive && !toc.active) { continue; } let config = (frame[0] >> 2) as usize & 1; let low_rate = (frame[0] >> 2) & 1 != 0; let mut dec = crate::voip::mlow::rangecoder::RangeDecoder::new(&frame[1..]); for f in 0..3 { - let lsf = decode_smpl_lsf(&mut dec, tbl, &mut lstate, config, f, true); - let pulses = decode_smpl_pulses(&mut dec, cc, 320, 4, 1, config as i32, lsf.stage1); + let lsf = decode_smpl_lsf(&mut dec, tbl, &mut lstate, config, f, toc.active); + let pulses = decode_smpl_pulses( + &mut dec, + cc, + 320, + 4, + i32::from(toc.active), + config as i32, + lsf.stage1, + ); let voiced = lsf.stage1 == 1; let mut params = CelpDecParams { voiced, diff --git a/wacore/src/voip/mlow/smpl_gennoise.rs b/wacore/src/voip/mlow/smpl_gennoise.rs index 5054f1ae9..1f1b86ffb 100644 --- a/wacore/src/voip/mlow/smpl_gennoise.rs +++ b/wacore/src/voip/mlow/smpl_gennoise.rs @@ -652,13 +652,28 @@ mod tests { /// running our implementation must reproduce both bit-for-bit across voiced and unvoiced paths. #[test] fn gen_noise_matches_c() { + let recs: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/gennoise_vectors.cbor.zst" + )) + .unwrap(); + check_gennoise(recs); + } + + #[test] + fn gen_noise_matches_shipped_wasm() { + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_gennoise.cbor.zst")) + .expect("wasm gennoise"); + assert_eq!(recs.as_array().unwrap().len(), 1320); + check_gennoise(recs); + } + + fn check_gennoise(recs: Value) { // fcbgains_uv[ix] = 10^(0.05*(ix-90)), ix in 0..=90. let fcbgains_uv: Vec = (0..=90) .map(|ix| 10.0f32.powf(0.05 * (ix as f32 - 90.0))) .collect(); - let recs: Value = - serde_json::from_str(include_str!("testdata/gennoise_vectors.json")).unwrap(); let arr = recs.as_array().unwrap(); assert!(!arr.is_empty()); diff --git a/wacore/src/voip/mlow/smpl_harm_postfilter.rs b/wacore/src/voip/mlow/smpl_harm_postfilter.rs index 57495641b..1ef75a6c1 100644 --- a/wacore/src/voip/mlow/smpl_harm_postfilter.rs +++ b/wacore/src/voip/mlow/smpl_harm_postfilter.rs @@ -22,8 +22,16 @@ const HARM_DELAY: usize = LAG_SUBFR_LEN; // SMPL_HARM_POSTF_DELAY #[cfg(test)] pub(crate) const TOT_POSTFILT_DELAY: usize = FB_DELAY + HARM_DELAY; // 48 const PITCH_NUM_SUBFRAMES: usize = 8; -const FB_STRENGTH: f32 = 0.4734; -const STRENGTH: f32 = 0.6438; +// J#10726: feedback 0.4 (0x3ecccccd), comb strength 0.713 (0x3f36872b). +#[derive(Clone, Copy)] +struct HarmTuning { + feedback: f32, + strength: f32, +} +const SHIPPED_TUNING: HarmTuning = HarmTuning { + feedback: 0.4, + strength: 0.713, +}; const CUTOFF_HZ: f32 = 4000.0; const NHARM_CUTOFF: f32 = 6.3; const REDUCTION_FAC: f32 = 0.0579; @@ -159,6 +167,7 @@ fn harm_postfilter_core( l: usize, fb_strength: f32, prev_did_filter: &mut i32, + tuning: HarmTuning, ) { let tables = harm_tables(); let lag_u = lag as usize; @@ -188,7 +197,7 @@ fn harm_postfilter_core( let high_lag_reduction = 1.0 - REDUCTION_FAC * ((lag - MIN_PITCH_LAG) as f32 / (MAX_PITCH_LAG - MIN_PITCH_LAG) as f32); - let strength = strength * high_lag_reduction * STRENGTH; + let strength = strength * high_lag_reduction * tuning.strength; for i in 0..l { out[out_off + i] *= 0.5 * strength; } @@ -243,6 +252,26 @@ pub(crate) fn smpl_harm_postfilter( lags: &[f32], n_lags: usize, normalized_bitrate: f32, +) { + harm_postfilter_with_tuning( + st, + x, + x_len, + lags, + n_lags, + normalized_bitrate, + SHIPPED_TUNING, + ); +} + +fn harm_postfilter_with_tuning( + st: &mut HarmPostfilterState, + x: &mut [f32], + x_len: usize, + lags: &[f32], + n_lags: usize, + normalized_bitrate: f32, + tuning: HarmTuning, ) { debug_assert_eq!(x_len, n_lags * LAG_SUBFR_LEN); // diff buffer with 16 samples of history prefix: backing is FRAME_LEN + 2*FB_DELAY, diff starts at +2*FB_DELAY. @@ -254,7 +283,7 @@ pub(crate) fn smpl_harm_postfilter( let comb_cur = MAX_PITCH_LAG as usize + HARM_DELAY; st.state_comb[comb_cur..comb_cur + x_len].copy_from_slice(&x[..x_len]); - let fb_strength = 1.0 - FB_STRENGTH * normalized_bitrate; + let fb_strength = 1.0 - tuning.feedback * normalized_bitrate; let mut offset1 = 0usize; let mut lag_ctr = 0usize; @@ -279,6 +308,7 @@ pub(crate) fn smpl_harm_postfilter( LAG_SUBFR_LEN, fb_strength, &mut st.prev_did_filter, + tuning, ); offset1 += LAG_SUBFR_LEN; offset2 += LAG_SUBFR_LEN; @@ -326,7 +356,11 @@ mod tests { const I16_LSB: f32 = 1.0 / 32768.0; // The voiced→silence transition zero-input response under -ffast-math; bulk stays under I16_LSB. const TRANSITION_TOL: f32 = 6.0e-4; - let data = include_bytes!("testdata/harm_postfilter_vectors.raw"); + let unpacked = crate::voip::mlow::fixture::inflate(include_bytes!( + "testdata/harm_postfilter_vectors.raw.zst" + )) + .expect("C postfilter archive"); + let data = unpacked.as_slice(); let mut o = 0usize; let count = ri32(data, &mut o); let mut st = HarmPostfilterState::default(); @@ -352,7 +386,19 @@ mod tests { // A silent packet (lag0 == 0) carries the transition zero-input response in its first 48 // samples; everywhere else is the i16-exact regime. let transition = lags[0] == 0.0; - smpl_harm_postfilter(&mut st, &mut inp, plen, &lags, nlags, nbr); + // The C audit corpus predates the shipped tuning. + harm_postfilter_with_tuning( + &mut st, + &mut inp, + plen, + &lags, + nlags, + nbr, + HarmTuning { + feedback: 0.4734, + strength: 0.6438, + }, + ); for i in 0..plen { let d = (inp[i] - cout[i]).abs(); worst = worst.max(d); @@ -374,4 +420,66 @@ mod tests { "harm_postfilter transition residual {worst:.2e} exceeds tolerance {TRANSITION_TOL:.2e}" ); } + #[test] + fn harm_postfilter_matches_shipped_wasm() { + let records: serde_json::Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/wasm_harm_postfilter.cbor.zst" + )) + .expect("wasm harmonic postfilter"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 110); + let floats = |v: &serde_json::Value| { + v.as_array() + .unwrap() + .iter() + .map(|x| x.as_f64().unwrap() as f32) + .collect::>() + }; + for (i, r) in records.iter().enumerate() { + let initial = floats(&r["state_in"]); + let mut state = HarmPostfilterState { + state1: initial[..16].try_into().unwrap(), + lpcoefs: initial[16..33].try_into().unwrap(), + state_comb: initial[33..2313].to_vec(), + prev_lag: initial[2313] as i32, + prev_did_filter: initial[2314] as i32, + }; + let mut out = floats(&r["input"]); + let lags = floats(&r["lags"]); + smpl_harm_postfilter( + &mut state, + &mut out, + 960, + &lags, + 24, + r["norm_br"].as_f64().unwrap() as f32, + ); + let expected_state = floats(&r["state_out"]); + assert_eq!( + state.prev_lag, expected_state[2313] as i32, + "packet {i}: previous lag" + ); + assert_eq!( + state.prev_did_filter, expected_state[2314] as i32, + "packet {i}: filter state" + ); + let state_values = state + .state1 + .iter() + .chain(state.lpcoefs.iter()) + .chain(state.state_comb.iter()); + for (got, want) in state_values.zip(&expected_state[..2313]) { + assert!( + (got - want).abs() < 6e-4, + "packet {i}: harmonic state {got} vs {want}" + ); + } + for (got, want) in out.iter().zip(floats(&r["output"])) { + assert!( + (got - want).abs() < 6e-4, + "packet {i}: harmonic output {got} vs {want}" + ); + } + } + } } diff --git a/wacore/src/voip/mlow/smpl_harmcomb.rs b/wacore/src/voip/mlow/smpl_harmcomb.rs index 0cf67164e..e5df530dd 100644 --- a/wacore/src/voip/mlow/smpl_harmcomb.rs +++ b/wacore/src/voip/mlow/smpl_harmcomb.rs @@ -414,7 +414,11 @@ mod tests { #[test] fn hp_postfilter_matches_c() { const I16_LSB: f32 = 1.0 / 32768.0; - let data = include_bytes!("testdata/hp_postfilter_vectors.raw"); + let unpacked = crate::voip::mlow::fixture::inflate(include_bytes!( + "testdata/hp_postfilter_vectors.raw.zst" + )) + .expect("C postfilter archive"); + let data = unpacked.as_slice(); let mut o = 0usize; let count = ri32(data, &mut o); let mut worst = 0f32; @@ -479,4 +483,59 @@ mod tests { "hp_postfilter diverges from reference by {worst:.2e} (>= i16 LSB {I16_LSB:.2e})" ); } + #[test] + fn hp_postfilter_matches_shipped_wasm() { + let records: serde_json::Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/wasm_hp_postfilter.cbor.zst" + )) + .expect("wasm HP postfilter"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 330); + let floats = |v: &serde_json::Value| { + v.as_array() + .unwrap() + .iter() + .map(|x| x.as_f64().unwrap() as f32) + .collect::>() + }; + for (i, r) in records.iter().enumerate() { + let state = floats(&r["state_in"]); + let mut state = seed_state( + state[0], + state[1], + state[2..6].try_into().unwrap(), + state[6], + state[7..327].try_into().unwrap(), + state[327..330].try_into().unwrap(), + state[330..333].try_into().unwrap(), + ); + let input = floats(&r["input"]); + let mut out = vec![0.0; FRAME_LEN]; + smpl_hp_postfilter( + &mut state, + &input, + FRAME_LEN, + r["lag"].as_f64().unwrap() as f32, + &mut out, + ); + let mut next_state = vec![state.state_lo_emph1, state.state_lo_emph2]; + next_state.extend(state.state_hp); + next_state.push(state.lag_old); + next_state.extend(state.x_old); + next_state.extend(state.coef_ma); + next_state.extend(state.coef_ar); + for (got, want) in next_state.iter().zip(floats(&r["state_out"])) { + assert!( + (got - want).abs() < 1.0 / 32768.0, + "frame {i}: HP state {got} vs {want}" + ); + } + for (got, want) in out.iter().zip(floats(&r["output"])) { + assert!( + (got - want).abs() < 1.0 / 32768.0, + "frame {i}: HP output {got} vs {want}" + ); + } + } + } } diff --git a/wacore/src/voip/mlow/smpl_lpc.rs b/wacore/src/voip/mlow/smpl_lpc.rs index eed2f33ee..abaa24b2d 100644 --- a/wacore/src/voip/mlow/smpl_lpc.rs +++ b/wacore/src/voip/mlow/smpl_lpc.rs @@ -23,7 +23,8 @@ pub(crate) const SMPL_LPC_NFFT: usize = 512; const SMPL_PI: f32 = 3.1415926535897; const SMPL_PI_F64: f64 = SMPL_PI as f64; const SMPL_LPC_REG: f32 = 5e-7; -const SMPL_LPC_BWE: f32 = 0.9999; +// J#10736 expands the LPC coefficients with f32 bits 0x3f7f9db2. +const SMPL_LPC_BWE: f32 = 0.9985; const SMPL_LPC_WIN1_20MS_LEN: usize = 264; const SMPL_WIN3_LONG_LEN: usize = 64; @@ -186,7 +187,9 @@ fn ac2rc_dbl(corr: &[f64], order: usize, reg: f32, rc: &mut [f32]) { let mut c0 = vec![0.0f64; order + 1]; let mut c1 = vec![0.0f64; order + 1]; c0[..order + 1].copy_from_slice(&corr[..order + 1]); - c0[0] *= (1.0f32 + reg) as f64; + // J#10797 promotes reg before adding 1. Rounding that sum in f32 + // changes the LPC solve on quiet, highly correlated input. + c0[0] *= 1.0f64 + f64::from(reg); c1[..order + 1].copy_from_slice(&c0[..order + 1]); for r in rc.iter_mut().take(order) { *r = 0.0; @@ -263,6 +266,15 @@ fn dct_tables() -> &'static DctTables { pub(crate) fn smpl_lpc_analyze_with_f2( windowed: &[f32; SMPL_LPC_BUF_LEN], fft: &mut FftScratch, +) -> ([f32; SMPL_LPC_ORDER + 1], [f32; SMPL_F_LEN]) { + let (mut a, f2) = lpc_analyze_unexpanded(windowed, fft); + bwe_expand(&mut a, SMPL_LPC_ORDER, SMPL_LPC_BWE); + (a, f2) +} + +fn lpc_analyze_unexpanded( + windowed: &[f32; SMPL_LPC_BUF_LEN], + fft: &mut FftScratch, ) -> ([f32; SMPL_LPC_ORDER + 1], [f32; SMPL_F_LEN]) { // Zero-pad to NFFT and forward real FFT (pffft ordered layout). let mut xbuf = [0.0f32; SMPL_LPC_NFFT]; @@ -286,7 +298,6 @@ pub(crate) fn smpl_lpc_analyze_with_f2( ac2rc_dbl(&r, SMPL_LPC_ORDER, SMPL_LPC_REG, &mut rc); let mut a = [0.0f32; SMPL_LPC_ORDER + 1]; rc2a(&rc, SMPL_LPC_ORDER, &mut a); - bwe_expand(&mut a, SMPL_LPC_ORDER, SMPL_LPC_BWE); (a, f2) } @@ -626,7 +637,9 @@ mod tests { // exact (NLSF in radians within float rounding of the Q15->radians scale). #[test] fn a2nlsf_matches_c() { - let recs: Value = serde_json::from_str(include_str!("testdata/lsf_quant_io.json")).unwrap(); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/lsf_quant_io.cbor.zst")) + .unwrap(); let arr = recs.as_array().unwrap(); let mut worst = 0.0f32; for (n, r) in arr.iter().enumerate() { @@ -653,7 +666,9 @@ mod tests { // like the decoder postfilters). #[test] fn front_end_a_matches_c() { - let recs: Value = serde_json::from_str(include_str!("testdata/fe_dump.json")).unwrap(); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/fe_dump.cbor.zst")) + .unwrap(); let arr = recs.as_array().unwrap(); assert!(arr.len() >= 12, "need front-end vectors"); let mut worst = 0.0f32; @@ -671,7 +686,10 @@ mod tests { for k in 0..SMPL_LPC_BUF_LEN { worst_win = worst_win.max((win[k] - want_win[k]).abs()); } - let a = smpl_lpc_analyze_with_f2(&win, &mut new_lpc_fft_scratch()).0; + // C 84b076e used 0.9999; compare its tuning explicitly. The shipped + // profile is checked against the independent wasm corpus below. + let mut a = lpc_analyze_unexpanded(&win, &mut new_lpc_fft_scratch()).0; + bwe_expand(&mut a, SMPL_LPC_ORDER, 0.9999); let want_a = fvec(&r["A"]); let r0: f64 = r["R"][0].as_f64().unwrap(); let mut rd = 0.0f32; @@ -694,6 +712,61 @@ mod tests { assert!(worst_win < 1e-6, "windowing |dwin|={worst_win:.2e}"); } + #[test] + fn front_end_matches_shipped_wasm() { + let records: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_fe.cbor.zst")) + .expect("wasm front-end"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 330); + for (i, r) in records.iter().enumerate() { + let input: [f32; SMPL_LPC_BUF_LEN] = fvec(&r["lpcbuf"]).try_into().unwrap(); + let window = smpl_window_lpc20(&input, r["numframe"].as_u64().unwrap() < 2); + for (got, want) in window.iter().zip(fvec(&r["windowed"])) { + assert!((got - want).abs() < 1e-6, "window case {i}"); + } + let (a, f2) = smpl_lpc_analyze_with_f2(&window, &mut new_lpc_fft_scratch()); + let expected_a = fvec(&r["A"]); + let mut max_coefficient_error = 0.0f32; + let mut coefficient_error_sum = 0.0f32; + for (got, want) in a.iter().zip(&expected_a) { + let error = (got - want).abs(); + max_coefficient_error = max_coefficient_error.max(error); + coefficient_error_sum += error; + } + // Near silence, FFT rounding is amplified by the ill-conditioned + // LPC solve. Bound the resulting prediction error by one PCM LSB, + // while checking the solve itself on the exact oracle R below. + let input_peak = window.iter().map(|x| x.abs()).fold(0.0f32, f32::max); + assert!( + max_coefficient_error < 5e-3 || coefficient_error_sum * input_peak < 1.0 / 32768.0, + "case {i}: LPC coefficient error {max_coefficient_error}, prediction bound {}", + coefficient_error_sum * input_peak + ); + let oracle_r: Vec = r["R"] + .as_array() + .unwrap() + .iter() + .map(|v| v.as_f64().unwrap()) + .collect(); + let mut rc = [0.0f32; SMPL_LPC_ORDER]; + let mut solved = [0.0f32; SMPL_LPC_ORDER + 1]; + ac2rc_dbl(&oracle_r, SMPL_LPC_ORDER, SMPL_LPC_REG, &mut rc); + rc2a(&rc, SMPL_LPC_ORDER, &mut solved); + for (got, want) in solved.iter().zip(fvec(&r["A_before_bwe"])) { + assert!( + (got - want).abs() < 1e-5, + "case {i}: LPC solve {got} vs {want}" + ); + } + let expected = fvec(&r["F2"]); + let scale = expected.iter().copied().fold(1e-8f32, f32::max); + for (got, want) in f2.iter().zip(expected) { + assert!((got - want).abs() < scale * 1e-5, "spectrum case {i}"); + } + } + } + // DIAGNOSTIC: the wire round-trip; feed the captured `qi` (grid+stage2) + threaded prev_nlsf to // the decoder's NLSF reconstruction and compare to the captured `qlsf`. Proves grid/stage2 map // directly onto the decoder wire (grid=qi[0], cond centroid=16) and that the decoder rebuilds the @@ -702,7 +775,9 @@ mod tests { fn decoder_reconstructs_c_qlsf() { use super::super::smpl_lsf_quant::{lsf_quant, lsf_quant_cond}; use super::super::smpl_synth::{load_smpl_synth_tables, smpl_reconstruct_nlsf}; - let recs: Value = serde_json::from_str(include_str!("testdata/lsf_quant_io.json")).unwrap(); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/lsf_quant_io.cbor.zst")) + .unwrap(); let arr = recs.as_array().unwrap(); let st = load_smpl_synth_tables(); let mut prev_nlsf: Vec = Vec::new(); diff --git a/wacore/src/voip/mlow/smpl_lsf_quant.rs b/wacore/src/voip/mlow/smpl_lsf_quant.rs index c1edf2064..6ffa8fdbe 100644 --- a/wacore/src/voip/mlow/smpl_lsf_quant.rs +++ b/wacore/src/voip/mlow/smpl_lsf_quant.rs @@ -602,7 +602,9 @@ mod tests { // indices `qi[]` AND the reconstructed `qlsf` must match the reference bit-for-bit. #[test] fn lsf_quant_matches_c() { - let recs: Value = serde_json::from_str(include_str!("testdata/lsf_quant_io.json")).unwrap(); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/lsf_quant_io.cbor.zst")) + .unwrap(); let arr = recs.as_array().unwrap(); assert!(arr.len() >= 12, "need vectors"); let mut bad = 0usize; @@ -644,4 +646,40 @@ mod tests { } assert_eq!(bad, 0, "lsf_quant qi mismatch vs reference"); } + #[test] + fn lsf_quant_matches_shipped_wasm() { + use super::super::smpl_lpc::smpl_a2nlsf_16; + let records: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_lsf_quant.cbor.zst")) + .expect("wasm LSF quantizer"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 330); + let mut previous = vec![0.0f32; 16]; + let mut conditional = 0; + for (i, r) in records.iter().enumerate() { + let a = fvec(&r["A"]); + let nlsf = smpl_a2nlsf_16(&a); + let voiced = r["voiced"].as_u64().unwrap() as usize; + let low_rate = r["lowRate"].as_u64().unwrap() as usize; + let weight = r["RDw_adj"].as_f64().unwrap() as f32; + let survivors = r["surv"].as_u64().unwrap() as usize; + let result = if r["cond"].is_null() { + lsf_quant(&a, &nlsf, voiced, low_rate, weight, survivors) + } else { + conditional += 1; + lsf_quant_cond(&a, &nlsf, &previous, voiced, low_rate, weight, survivors) + }; + assert_eq!( + result.qi.to_vec(), + ivec(&r["qi"]), + "case {i}: quantized indices" + ); + let expected = fvec(&r["qlsf"]); + for (got, want) in result.qlsf.iter().zip(&expected) { + assert!((got - want).abs() < 1e-4, "case {i}: quantized LSF"); + } + previous = expected; + } + assert_eq!(conditional, 219); + } } diff --git a/wacore/src/voip/mlow/smpl_pitch_enc.rs b/wacore/src/voip/mlow/smpl_pitch_enc.rs index 0a7e551f7..006119688 100644 --- a/wacore/src/voip/mlow/smpl_pitch_enc.rs +++ b/wacore/src/voip/mlow/smpl_pitch_enc.rs @@ -25,10 +25,12 @@ const MINPITCH_LEN: i32 = MINPITCH_MS * FS_KHZ; // 32 const MAXPITCH_LEN: i32 = MAXPITCH_MS * FS_KHZ; // 320 const MINPITCH_STAGE1: i32 = MINPITCH_MS * STAGE1_FS_KHZ - TOT_INTERP_DELAY; // 10 const MAXPITCH_STAGE1: i32 = MAXPITCH_MS * STAGE1_FS_KHZ + TOT_INTERP_DELAY; // 166 -const PITCH_DELTAWGHT: f32 = 0.1439; +// J#10736: coarse penalty 0.105, fine penalty 0.0046875 (0.3 / 64). +const PITCH_DELTAWGHT: f32 = 0.3; const PITCH_SHORTWGHT1: f32 = 0.04; const SPEC_HARM_BIAS: f32 = 2.5; -const PREVWGHT: f32 = 0.7981; +// J#10736 uses 0x3f333333 for the previous-lag bias. +const PREVWGHT: f32 = 0.7; const PREVWGHT_SPAN: f32 = 0.15; const RATEWGHT_HR: f32 = 0.022; const LAG_SUBFRLEN: i32 = 40; @@ -703,6 +705,38 @@ pub(crate) fn smpl_pitch( ltp_buf: &[f32], f2: &[f32; F_LEN], coded_as_active_voice: bool, +) -> PitchResult { + pitch_with_search( + st, + ltp_buf, + f2, + coded_as_active_voice, + PitchSearch { + survivors: NUMSTATES1, + low_complexity: LOW_COMPLEXITY, + low_rate: LOW_RATE, + previous_weight: PREVWGHT, + delta_weight: PITCH_DELTAWGHT, + }, + ) +} + +// Oracle captures carry their search budget. The forged pjmedia default has +// four survivors/low-complexity mode; our encoder retains its 24-survivor budget. +struct PitchSearch { + survivors: usize, + low_complexity: bool, + low_rate: bool, + previous_weight: f32, + delta_weight: f32, +} + +fn pitch_with_search( + st: &mut PitchEstState, + ltp_buf: &[f32], + f2: &[f32; F_LEN], + coded_as_active_voice: bool, + search: PitchSearch, ) -> PitchResult { let tab = load_pitch_tables(); let numsubfrs = NUM_SUBFRAMES; @@ -774,7 +808,7 @@ pub(crate) fn smpl_pitch( let mut numlags_c = numlags; let mut minpitch_e = MINPITCH_STAGE1; let mut numlags_e = numlags; - if LOW_COMPLEXITY { + if search.low_complexity { upsamp_e_fast(&mut c, numsubfrs, &mut minpitch_c, &mut numlags_c); } else { upsamp_c_fast(&mut c, numsubfrs, &mut minpitch_c, &mut numlags_c); @@ -818,7 +852,7 @@ pub(crate) fn smpl_pitch( // Block-track survivor selection. let blocksize_fs = PITCHBLOCK * 2; // BLOCKSIZE = 64 let reduction_factor = 0.7f32; - let pitch_deltawght = PITCH_DELTAWGHT / blocksize_fs as f32; + let pitch_deltawght = search.delta_weight / blocksize_fs as f32; let mut sf_wght = [0.0f32; NUM_SUBFRAMES]; { let sum_e2: f32 = e2.iter().take(numsubfrs).sum(); @@ -841,7 +875,7 @@ pub(crate) fn smpl_pitch( - reduction_factor * PITCHBLOCK as f32 * pitch_deltawght * bt.trackdeltas + shortlagbias1; } - let track_idx = get_maxi_k(&utils, NUMSTATES1); + let track_idx = get_maxi_k(&utils, search.survivors); // Recompute full-res E1 over the HP signal. let mut e1_fs = vec![0.0f32; numlags_e * numsubfrs + 16]; @@ -864,7 +898,7 @@ pub(crate) fn smpl_pitch( } } - let h_thres = if LOW_COMPLEXITY { 0.0 } else { 0.25 }; + let h_thres = if search.low_complexity { 0.0 } else { 0.25 }; let offset_c = (MINPITCH_MS * FS_KHZ - minpitch_c) as usize; let offset_e = (MINPITCH_MS * FS_KHZ - minpitch_e) as usize; // Update C and E around survivor block peaks at full resolution. @@ -924,7 +958,7 @@ pub(crate) fn smpl_pitch( ); let cin = c_ptr + block * PITCHBLOCK; let cout = c_ptr_frac + block * 2 * PITCHBLOCK; - if LOW_COMPLEXITY { + if search.low_complexity { upsamp_e_core( &mut c, cin + PITCHBLOCK - 1, @@ -991,7 +1025,7 @@ pub(crate) fn smpl_pitch( let nlaginds = laginds_surv.len(); // Final search. - let pitch_ratewght = if LOW_RATE { 0.028 } else { RATEWGHT_HR }; + let pitch_ratewght = if search.low_rate { 0.028 } else { RATEWGHT_HR }; let f2w = build_f2w(f2); let max_ix = get_maxi(&sf_wght[..numsubfrs]); let mut spectral_harm_cache = [0.0f32; 50]; @@ -999,7 +1033,7 @@ pub(crate) fn smpl_pitch( let mut best_util = 0.0f32; let mut best_pitchcorr = 0.0f32; let mut best_surv = 0usize; - let pitch_deltawght_fs = PITCH_DELTAWGHT / blocksize_fs as f32; + let pitch_deltawght_fs = search.delta_weight / blocksize_fs as f32; for surv in 0..nlaginds { let mut sum_c = 0.0f32; @@ -1022,7 +1056,7 @@ pub(crate) fn smpl_pitch( let mean_lag = laginds_surv[surv][max_ix] as f32 * 0.5 + MINPITCH_LEN as f32; let pitchcorr = sum_c / sum_e; let first_lag = 0.5 * laginds_surv[surv][0] as f32 + MINPITCH_LEN as f32; - let prev_lag_bias = get_prev_lag_bias(st, first_lag); + let prev_lag_bias = get_prev_lag_bias(st, first_lag, search.previous_weight); let spectral_harm_bias = SPEC_HARM_BIAS * spectral_harmonicity_cached(mean_lag, &f2w, &mut spectral_harm_cache, surv == 0); let util = 1.0 / (1.1 - pitchcorr) @@ -1074,11 +1108,11 @@ fn smpl_maximum(x: &[f32]) -> f32 { m } -fn get_prev_lag_bias(st: &PitchEstState, lag: f32) -> f32 { +fn get_prev_lag_bias(st: &PitchEstState, lag: f32, previous_weight: f32) -> f32 { let lag_diff = (lag - st.prev_lag).abs(); let diff_thres = PREVWGHT_SPAN * st.prev_lag; if lag_diff < diff_thres { - st.prev_pitch_corr * (1.0 - lag_diff / diff_thres) * PREVWGHT + st.prev_pitch_corr * (1.0 - lag_diff / diff_thres) * previous_weight } else { 0.0 } @@ -1095,8 +1129,10 @@ mod tests { // harm_strength (cache-aliasing tol). This is the rigorous proof the estimator is faithful. #[test] fn pitch_estimator_matches_c_ground_truth() { - let recs: Value = - serde_json::from_str(include_str!("testdata/pitchio_ground_truth.json")).unwrap(); + let recs: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/pitchio_ground_truth.cbor.zst" + )) + .unwrap(); let arr = recs.as_array().unwrap(); assert!(arr.len() >= 30, "expected >=30 records, got {}", arr.len()); @@ -1132,7 +1168,19 @@ mod tests { let mut f2 = [0.0f32; F_LEN]; f2.copy_from_slice(&f2v); - let res = smpl_pitch(&mut st, <p_buf, &f2, cav); + let res = pitch_with_search( + &mut st, + <p_buf, + &f2, + cav, + PitchSearch { + survivors: 24, + low_complexity: false, + low_rate: false, + previous_weight: 0.7981, + delta_weight: 0.1439, + }, + ); if cav { let pc_c = rec["pitchcorr"].as_f64().unwrap() as f32; @@ -1177,4 +1225,70 @@ mod tests { "harm_strength diverges beyond cache-aliasing tol: {max_harm_err}" ); } + #[test] + fn pitch_estimator_matches_shipped_wasm() { + let records: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/wasm_pitch.cbor.zst")) + .expect("wasm pitch"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 330); + let floats = |v: &Value| { + v.as_array() + .unwrap() + .iter() + .map(|x| x.as_f64().unwrap() as f32) + .collect::>() + }; + for (i, r) in records.iter().enumerate() { + let mut state = PitchEstState { + prev_lag: r["prev_lag"].as_f64().unwrap() as f32, + prev_pitch_corr: r["prev_pitch_corr"].as_f64().unwrap() as f32, + prev_lagblk: r["prev_lagblk"].as_i64().unwrap() as i32, + prev_lagidx: r["prev_lagidx"].as_i64().unwrap() as i32, + }; + let f2: [f32; F_LEN] = floats(&r["F2"]).try_into().unwrap(); + let ltp = floats(&r["ltp_buf"]); + assert_eq!(ltp.len(), MAX_LTP_BUF_LEN); + let result = pitch_with_search( + &mut state, + <p, + &f2, + r["cav"].as_i64().unwrap() != 0, + PitchSearch { + survivors: r["numstates"].as_u64().unwrap() as usize, + low_complexity: r["low_complexity"].as_i64().unwrap() != 0, + low_rate: r["low_rate"].as_i64().unwrap() != 0, + previous_weight: PREVWGHT, + delta_weight: PITCH_DELTAWGHT, + }, + ); + assert!( + (result.pitchcorr - r["pitchcorr"].as_f64().unwrap() as f32).abs() < 1e-3, + "frame {i}: pitch correlation {} vs {}, prev={}, lag={} vs {}", + result.pitchcorr, + r["pitchcorr"], + state.prev_pitch_corr, + result.avg_lag, + r["avg_lag"] + ); + assert!( + (result.avg_lag - r["avg_lag"].as_f64().unwrap() as f32).abs() < 1e-3, + "frame {i}: average lag {} vs {}", + result.avg_lag, + r["avg_lag"] + ); + assert!( + (result.harm_strength - r["harm"].as_f64().unwrap() as f32).abs() < 0.05, + "frame {i}: harmonicity" + ); + for (got, want) in result.laginds.iter().zip(r["laginds"].as_array().unwrap()) { + assert_eq!(*got, want.as_i64().unwrap() as i32, "frame {i}: lag index"); + } + assert_eq!( + result.blockseg_idx, + r["blockseg_idx"].as_u64().unwrap() as usize, + "frame {i}: contour" + ); + } + } } diff --git a/wacore/src/voip/mlow/smpl_pulse.rs b/wacore/src/voip/mlow/smpl_pulse.rs index bed9c8b1b..be744db58 100644 --- a/wacore/src/voip/mlow/smpl_pulse.rs +++ b/wacore/src/voip/mlow/smpl_pulse.rs @@ -220,8 +220,9 @@ mod tests { // counts + the full signed pulse vector against the reference. #[test] fn pulses_match_go() { - let recs: Value = serde_json::from_str(include_str!("testdata/pulse_vectors.json")) - .expect("pulse_vectors"); + let recs: Value = + crate::voip::mlow::fixture::decode(include_bytes!("testdata/pulse_vectors.cbor.zst")) + .expect("pulse_vectors"); let tbl = load_smpl_tables(); let cc = load_cc_tables(); let arr = recs.as_array().unwrap(); diff --git a/wacore/src/voip/mlow/smpl_signal_mode.rs b/wacore/src/voip/mlow/smpl_signal_mode.rs index 564d9259f..505bd6cdf 100644 --- a/wacore/src/voip/mlow/smpl_signal_mode.rs +++ b/wacore/src/voip/mlow/smpl_signal_mode.rs @@ -9,7 +9,8 @@ use super::smpl_lpc::SMPL_F_LEN; /// Weights on corrs, vad, tilt, harmonicity, short lags. The reference declares 6 entries but only /// sums the first 5, so this holds 5. const SMPL_VUV_WEIGHTS: [f32; 5] = [1.0, 0.5, 0.5, 0.7, 0.3]; -const SMPL_VUV_BIAS: f32 = -0.1038; +// J#10736 and the live 330-frame trace use f32 bits 0xbe051eb8. +const SMPL_VUV_BIAS: f32 = -0.13; const SMPL_VUV_HYST: f32 = 0.05; /// `SMPL_F_LEN / 3` (the transition index between the low/high spectral-tilt bands). const TRANSITION_IX: usize = SMPL_F_LEN / 3; @@ -172,6 +173,31 @@ pub(crate) fn smpl_get_signal_mode( f2: &[f32; SMPL_F_LEN], sp_act_prob: f32, vuv: &mut VuvMode, +) -> f32 { + signal_mode_with_bias( + pitchcorr, + lags, + avg_lag, + harm_strength, + f2, + sp_act_prob, + vuv, + SMPL_VUV_BIAS, + ) +} + +// The C auditor is pinned to an older tuning (-0.1038). Keep the same kernel +// testable under that tuning without carrying it into the shipped profile. +#[allow(clippy::too_many_arguments)] +fn signal_mode_with_bias( + pitchcorr: f32, + lags: &[f32], + avg_lag: f32, + harm_strength: f32, + f2: &[f32; SMPL_F_LEN], + sp_act_prob: f32, + vuv: &mut VuvMode, + bias: f32, ) -> f32 { let corr_strength = smpl_inv_sigmoid(0.1 + 0.75 * pitchcorr.clamp(0.0, 1.0)); // -1.4 .. 1.4 let vad_strength = 0.04 * (1.0 - 1.04 / (sp_act_prob + 0.04)); // -1 .. 0 @@ -203,7 +229,7 @@ pub(crate) fn smpl_get_signal_mode( + SMPL_VUV_WEIGHTS[3] * harm_strength + SMPL_VUV_WEIGHTS[4] * lag_strength) / smpl_sum_vec(&SMPL_VUV_WEIGHTS, 5) - + SMPL_VUV_BIAS; + + bias; // hysteresis if vuv.last_lag_prev > 0.0 { @@ -230,8 +256,10 @@ mod tests { // the reference output. Isolates the classifier from the pitch estimator. #[test] fn signal_mode_matches_c_ground_truth() { - let recs: Value = - serde_json::from_str(include_str!("testdata/sigmode_ground_truth.json")).unwrap(); + let recs: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/sigmode_ground_truth.cbor.zst" + )) + .unwrap(); let arr = recs.as_array().unwrap(); assert!(arr.len() >= 12); let mut vuv = VuvMode::default(); @@ -269,7 +297,8 @@ mod tests { max_harm_err = max_harm_err.max((harm_rs - harm).abs()); } - let vstr_rs = smpl_get_signal_mode(pitchcorr, &lags, avg_lag, harm, &f2, sp, &mut vuv); + let vstr_rs = + signal_mode_with_bias(pitchcorr, &lags, avg_lag, harm, &f2, sp, &mut vuv, -0.1038); max_err = max_err.max((vstr_rs - vstr_c).abs()); // Voiced decision (all dump frames are coded_as_active_voice). assert_eq!( @@ -291,4 +320,62 @@ mod tests { "harm_strength diverges from reference beyond cache-aliasing tolerance: {max_harm_err}" ); } + #[test] + fn signal_mode_matches_shipped_wasm() { + let records: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/wasm_signal_mode.cbor.zst" + )) + .expect("wasm signal mode"); + let records = records.as_array().unwrap(); + assert_eq!(records.len(), 330); + let vec = |v: &Value| { + v.as_array() + .unwrap() + .iter() + .map(|x| x.as_f64().unwrap() as f32) + .collect::>() + }; + for (i, r) in records.iter().enumerate() { + let initial = vec(&r["vuv_in"]); + let mut state = VuvMode { + voicing_prev: initial[0], + last_lag_prev: initial[1], + nrg_lo_bgn: initial[2], + nrg_hi_bgn: initial[3], + }; + let f2: [f32; SMPL_F_LEN] = vec(&r["F2"]).try_into().unwrap(); + let lags = vec(&r["lags"]); + let value = smpl_get_signal_mode( + r["pitchcorr"].as_f64().unwrap() as f32, + &lags, + r["avg_lag"].as_f64().unwrap() as f32, + r["harm"].as_f64().unwrap() as f32, + &f2, + r["sp_act_prob"].as_f64().unwrap() as f32, + &mut state, + ); + let expected = r["vstr"].as_f64().unwrap() as f32; + assert!( + (value - expected).abs() < 1e-5, + "frame {i}: strength {value} vs {expected}" + ); + let actual = [ + state.voicing_prev, + state.last_lag_prev, + state.nrg_lo_bgn, + state.nrg_hi_bgn, + ]; + for (got, want) in actual.iter().zip(vec(&r["vuv_out"])) { + assert!( + (got - want).abs() < 1e-5 * want.abs().max(1.0), + "frame {i}: VUV state {got} vs {want}" + ); + } + assert_eq!( + i32::from(value > 0.0 && r["cav"].as_i64().unwrap() != 0), + r["voiced"].as_i64().unwrap() as i32, + "frame {i}: voiced" + ); + } + } } diff --git a/wacore/src/voip/mlow/smpl_vad.rs b/wacore/src/voip/mlow/smpl_vad.rs index 5bc3df69d..93ce925cf 100644 --- a/wacore/src/voip/mlow/smpl_vad.rs +++ b/wacore/src/voip/mlow/smpl_vad.rs @@ -541,4 +541,71 @@ mod ground_truth_tests { assert_eq!(cav, c_cav, "pkt {pkt} frame {frame}: cav mismatch"); } } + + // The shipped encoder's own voice-activity routing, derived with + // `oracle derive --spec specs/mlow_110frames.json` in unwasm (see + // PROVENANCE.md): per 960-sample packet, `cav` is 0 for DTX (`0x10`) + // and 1 otherwise — hangover frames (`0x12`) count as active, matching + // the decoder's own routing (see the DTX-off test in decoder.rs) and + // the encoder's internal active/inactive counters. Our SILK VAD must + // route the same packets the same way, over the whole stream — the C + // ground truth above only covers a truncated prefix. + #[test] + fn vad_matches_wasm_routing() { + let raw = include_bytes!("testdata/synth_mic.raw"); + let samples: Vec = raw + .chunks_exact(2) + .map(|c| i16::from_le_bytes([c[0], c[1]])) + .collect(); + let gt: Value = serde_json::from_str(include_str!("testdata/wasm_derived_vad.json")) + .expect("wasm_derived_vad.json"); + let gt = gt.as_array().expect("array"); + + let mut vad = SmplVadState::new(); + let mut n_active = 0usize; + for (pkt, chunk) in samples.chunks(960).enumerate() { + if chunk.len() < 960 { + break; + } + let r = vad.process_packet(chunk, 320); + let rec = >[pkt]; + let w_cav = rec["cav"].as_i64().unwrap() as i32; + assert_eq!( + r.coded_as_active_voice as i32, w_cav, + "pkt {pkt}: cav mismatch against shipped routing" + ); + n_active += w_cav as usize; + } + assert_eq!(gt.len(), 110, "vector must cover the whole synth stream"); + assert_eq!( + n_active, 99, + "routing must retain 99 active / 11 inactive packets" + ); + } + #[test] + fn speech_activity_matches_shipped_wasm() { + let records: Value = crate::voip::mlow::fixture::decode(include_bytes!( + "testdata/wasm_signal_mode.cbor.zst" + )) + .expect("wasm speech activity"); + let records = records.as_array().unwrap(); + let samples: Vec = include_bytes!("testdata/synth_mic.raw") + .chunks_exact(2) + .map(|b| i16::from_le_bytes([b[0], b[1]])) + .collect(); + let mut vad = SmplVadState::new(); + assert_eq!(records.len(), 330); + for (packet, pcm) in samples.chunks_exact(960).enumerate() { + let result = vad.process_packet(pcm, 320); + for internal in 0..3 { + let expected = records[packet * 3 + internal]["sp_act_prob"] + .as_f64() + .unwrap() as f32; + assert_eq!( + result.vad_results[internal], expected, + "packet {packet}, frame {internal}: speech activity" + ); + } + } + } } diff --git a/wacore/src/voip/mlow/testdata/e2e_vectors.cbor.zst b/wacore/src/voip/mlow/testdata/e2e_vectors.cbor.zst new file mode 100644 index 0000000000000000000000000000000000000000..da9474071053aeda8c4d6d90caaeda024c85c63e GIT binary patch literal 228923 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