#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::super::bits::{BitReader, BitWriter};
use super::super::decode::StreamDecoder;
use super::super::error::Result;
use super::super::ics::{IcsInfo, WindowSequence};
use super::super::stereo::{MsInfo, MsMask};
use super::super::swb::{LONG_WINDOW_LEN, long_offsets, short_offsets};
use super::{MaskForm, MsBands, decide_long};
use crate::engine::enc_frame::LcEncoder;
fn parse_ms(payload: &[u8], fs_index: u8) -> Result<(IcsInfo, MsInfo, u64)> {
let mut br = BitReader::new(payload);
let id = br.read(3)?;
assert_eq!(id, 1, "stereo frame must start with a CPE");
br.read(4)?; assert!(br.read_bit()?, "common_window");
let ics = IcsInfo::parse(&mut br, fs_index, true)?;
let pre = br.bit_position();
let ms = MsInfo::parse(&mut br, &ics)?;
Ok((ics, ms, br.bit_position() - pre))
}
fn noise_frame(t: usize, seed: u32, amp: f32) -> Vec<f32> {
let mut state = seed.wrapping_add((t as u32).wrapping_mul(2_654_435_761));
(0..LONG_WINDOW_LEN)
.map(|_| {
state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
amp * (((state >> 9) as f32 / (1u32 << 23) as f32) * 2.0 - 1.0)
})
.collect()
}
fn split_frame(t: usize, hf_amp: f32) -> (Vec<f32>, Vec<f32>) {
let mut l = Vec::with_capacity(LONG_WINDOW_LEN);
let mut r = Vec::with_capacity(LONG_WINDOW_LEN);
for i in 0..LONG_WINDOW_LEN {
let n = (t * LONG_WINDOW_LEN + i) as f32;
let low = 0.4 * (2.0 * std::f32::consts::PI * 200.0 * n / 48_000.0).sin();
let mut hl = 0.0f32;
let mut hr = 0.0f32;
for k in 0..16 {
let f = 8_000.0 + 500.0 * k as f32;
let w = 2.0 * std::f32::consts::PI * f / 48_000.0;
hl += (w * n + 0.7 * k as f32).sin();
hr += (w * n + 0.7 * k as f32 + 1.9).sin();
}
l.push(low + hf_amp * hl / 4.0);
r.push(low + hf_amp * hr / 4.0);
}
(l, r)
}
#[test]
fn correlated_pair_decides_all_ms() -> Result<()> {
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
for t in 0..4 {
let l = noise_frame(t, 0x1234_5678, 0.3);
let r: Vec<f32> = l.iter().map(|&x| x * 0.9).collect();
let payload = enc.encode_frame(&[&l, &r])?;
if t < 2 {
continue; }
let (_, ms, mask_bits) = parse_ms(&payload, enc.fs_index())?;
assert_eq!(ms.mask, MsMask::All, "frame {t}: correlated must be All");
assert_eq!(mask_bits, 2, "whole-pair mask costs 2 bits");
let mut dec = StreamDecoder::new();
let frame = dec.decode_raw_data_block(2, enc.fs_index(), 48_000, 2, 1, &payload)?;
assert_eq!(frame.planar.len(), 2);
}
Ok(())
}
#[test]
fn decorrelated_pair_decides_off() -> Result<()> {
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
for t in 0..4 {
let l = noise_frame(t, 0x0BAD_F00D, 0.3);
let r = noise_frame(t, 0x5EED_1234, 0.03);
let payload = enc.encode_frame(&[&l, &r])?;
if t < 2 {
continue;
}
let (_, ms, mask_bits) = parse_ms(&payload, enc.fs_index())?;
assert_eq!(ms.mask, MsMask::Off, "frame {t}: decorrelated must be Off");
assert_eq!(mask_bits, 2);
}
Ok(())
}
#[test]
fn split_spectrum_emits_per_band_bitmask() -> Result<()> {
let offsets = long_offsets(3)?; let n_bands = offsets.len() - 1;
let band_hz = |b: usize| {
f32::from(offsets[b]) * 48_000.0 / 2048.0 };
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
let mut dec = StreamDecoder::new();
let mut saw_per_band = false;
for t in 0..6 {
let (l, r) = split_frame(t, 0.5);
let payload = enc.encode_frame(&[&l, &r])?;
if t < 2 {
continue;
}
let (ics, ms, mask_bits) = parse_ms(&payload, enc.fs_index())?;
assert!(!ics.window_sequence.is_eight_short());
assert_eq!(ms.mask, MsMask::PerBand, "frame {t}: split must be PerBand");
assert_eq!(mask_bits, 2 + n_bands as u64, "one bit per long band");
saw_per_band = true;
for b in 0..n_bands {
if band_hz(b) >= 8_000.0 && band_hz(b) < 16_000.0 {
assert!(!ms.used(0, b), "frame {t} band {b}: decorrelated HF is L/R");
}
}
let b200 = (0..n_bands)
.find(|&b| usize::from(offsets[b]) <= 8 && 8 < usize::from(offsets[b + 1]))
.expect("200 Hz band");
assert!(ms.used(0, b200), "frame {t}: correlated low band is M/S");
let frame = dec.decode_raw_data_block(2, enc.fs_index(), 48_000, 2, 1, &payload)?;
assert_eq!(frame.planar.len(), 2);
}
assert!(saw_per_band);
Ok(())
}
#[test]
fn short_window_bitmask_is_per_group() -> Result<()> {
let offsets = short_offsets(3)?;
let n_sfb = offsets.len() - 1;
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
let mut dec = StreamDecoder::new();
let mut saw_short_per_band = false;
for t in 0..6 {
let mut l = Vec::with_capacity(LONG_WINDOW_LEN);
let mut r = Vec::with_capacity(LONG_WINDOW_LEN);
for i in 0..LONG_WINDOW_LEN {
let n = (t * LONG_WINDOW_LEN + i) as f32;
let v = 0.3 * (2.0 * std::f32::consts::PI * 300.0 * n / 48_000.0).sin();
l.push(v);
r.push(v);
}
if t >= 2 {
let nl = noise_frame(t, 0xC1C4_0001, 0.4);
let nr = noise_frame(t, 0xC1C4_0002, 0.04);
for i in 0..LONG_WINDOW_LEN {
l[i] += nl[i];
r[i] += nr[i];
}
}
let payload = enc.encode_frame(&[&l, &r])?;
let (ics, ms, mask_bits) = parse_ms(&payload, enc.fs_index())?;
if ics.window_sequence != WindowSequence::EightShort {
continue;
}
saw_short_per_band = true;
assert_eq!(ics.num_window_groups, 8, "8 groups of 1 window");
assert_eq!(ms.mask, MsMask::PerBand, "short split must be PerBand");
assert_eq!(mask_bits, 2 + (8 * n_sfb) as u64, "8 groups × n_sfb bits");
assert_eq!(ms.used.len(), 8);
for g in 0..8 {
assert!(ms.used(g, 0), "g{g}: correlated tone band is M/S");
for (b, &off) in offsets.iter().enumerate().take(n_sfb) {
let hz = f32::from(off) * 48_000.0 / 256.0;
if (4_000.0..16_000.0).contains(&hz) {
assert!(!ms.used(g, b), "g{g} b{b}: decorrelated HF is L/R");
}
}
}
let frame = dec.decode_raw_data_block(2, enc.fs_index(), 48_000, 2, 1, &payload)?;
assert_eq!(frame.planar.len(), 2);
}
assert!(
saw_short_per_band,
"fixture must produce an EightShort frame"
);
Ok(())
}
#[test]
fn emit_parses_back_bit_exact() -> Result<()> {
let offsets = long_offsets(3)?;
let n_bands = offsets.len() - 1;
let mut specs = [[0.0f32; LONG_WINDOW_LEN]; 2];
{
let [l, r] = &mut specs;
for (b, win) in offsets.windows(2).enumerate() {
let (lo, hi) = (usize::from(win[0]), usize::from(win[1]));
let bins = l.iter_mut().zip(r.iter_mut()).enumerate().take(hi).skip(lo);
for (i, (lv, rv)) in bins {
if b < n_bands / 2 {
*lv = 100.0;
*rv = 90.0; } else {
*lv = if i % 2 == 0 { 100.0 } else { -100.0 };
*rv = if i % 3 == 0 { 100.0 } else { -90.0 };
}
}
}
}
let ms = decide_long(&mut specs, offsets, true);
assert_eq!(ms.form(), MaskForm::PerBand);
let mut w = BitWriter::new();
ms.emit(&mut w);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
let ics = IcsInfo {
window_sequence: WindowSequence::OnlyLong,
window_shape: super::super::ics::WindowShape::Kbd,
max_sfb: n_bands as u8,
num_windows: 1,
num_window_groups: 1,
window_group_length: [1, 0, 0, 0, 0, 0, 0, 0],
num_swb: n_bands as u8,
};
let parsed = MsInfo::parse(&mut br, &ics)?;
assert_eq!(parsed.mask, MsMask::PerBand);
for b in 0..n_bands {
assert_eq!(parsed.used(0, b), ms.used(b), "band {b} mirror");
}
Ok(())
}
fn ab_frame(t: usize, hf_amp: f32, tonal: bool) -> (Vec<f32>, Vec<f32>) {
let mut l = Vec::with_capacity(LONG_WINDOW_LEN);
let mut r = Vec::with_capacity(LONG_WINDOW_LEN);
let (nl, nr) = if tonal {
(vec![0.0f32; LONG_WINDOW_LEN], vec![0.0f32; LONG_WINDOW_LEN])
} else {
(
noise_frame(t, 0xAB00_0001, hf_amp),
noise_frame(t, 0xAB00_0002, hf_amp * 0.1),
)
};
for i in 0..LONG_WINDOW_LEN {
let n = (t * LONG_WINDOW_LEN + i) as f32;
let low = 0.3 * (2.0 * std::f32::consts::PI * 200.0 * n / 48_000.0).sin();
let (mut hl, mut hr) = (0.0f32, 0.0f32);
for (k, &f) in [8_000.0f32, 10_000.0, 12_000.0].iter().enumerate() {
let w = 2.0 * std::f32::consts::PI * f / 48_000.0;
hl += (w * n + 0.9 * k as f32).sin();
hr += (w * n + 0.9 * k as f32 + 2.1).sin();
}
l.push(low + hf_amp * hl + nl[i]);
r.push(low + hf_amp * 0.1 * hr + nr[i]);
}
(l, r)
}
fn ab_snr(payloads: &[Vec<u8>], frames: &[(Vec<f32>, Vec<f32>)], fs_index: u8) -> Result<[f64; 2]> {
let mut dec = StreamDecoder::new();
let (mut ps, mut pe) = ([0.0f64; 2], [0.0f64; 2]);
for (t, payload) in payloads.iter().enumerate() {
let frame = dec.decode_raw_data_block(2, fs_index, 48_000, 2, 1, payload)?;
if t < 2 || t + 1 >= frames.len() {
continue; }
let (l, r) = &frames[t - 1];
for (ch, want) in [l, r].into_iter().enumerate() {
for (&g, &w) in frame.planar[ch].iter().zip(want.iter()) {
let w = f64::from(w) * 32768.0;
ps[ch] += w * w;
let e = w - f64::from(g);
pe[ch] += e * e;
}
}
}
Ok([
10.0 * (ps[0] / pe[0].max(1.0)).log10(),
10.0 * (ps[1] / pe[1].max(1.0)).log10(),
])
}
#[test]
fn per_band_never_worse_than_whole_pair() -> Result<()> {
let encode_all = |per_band: bool, frames: &[(Vec<f32>, Vec<f32>)]| -> Result<Vec<Vec<u8>>> {
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
enc.set_ms_per_band(per_band);
frames
.iter()
.map(|(l, r)| enc.encode_frame(&[l, r]))
.collect()
};
let tonal: Vec<_> = (0..8).map(|t| ab_frame(t, 0.2, true)).collect();
let whole = encode_all(false, &tonal)?;
let per_band = encode_all(true, &tonal)?;
let (bw, bp): (usize, usize) = (
whole.iter().map(Vec::len).sum(),
per_band.iter().map(Vec::len).sum(),
);
eprintln!("asymmetric tonal split @128k: whole-pair {bw} B, per-band {bp} B");
assert!(bp < bw, "per-band {bp} B should beat whole-pair {bw} B");
let n_bands = long_offsets(3)?.len() - 1;
let noisy: Vec<_> = (0..10).map(|t| ab_frame(t, 0.3, false)).collect();
let whole = encode_all(false, &noisy)?;
let per_band = encode_all(true, &noisy)?;
let (bw, bp): (usize, usize) = (
whole.iter().map(Vec::len).sum(),
per_band.iter().map(Vec::len).sum(),
);
let sw = ab_snr(&whole, &noisy, 3)?;
let sp = ab_snr(&per_band, &noisy, 3)?;
eprintln!(
"asymmetric noisy split @128k: whole {bw} B SNR {:.1}/{:.1} dB, \
per-band {bp} B SNR {:.1}/{:.1} dB",
sw[0], sw[1], sp[0], sp[1]
);
let tax_bytes = noisy.len() * (n_bands - 2).div_ceil(8) + 16;
assert!(
bp <= bw + tax_bytes,
"per-band {bp} B exceeds whole-pair {bw} B by more than the mask tax"
);
for ch in 0..2 {
assert!(sp[ch] > 0.0, "ch{ch}: per-band SNR {:.1} dB", sp[ch]);
assert!(
sp[ch] >= sw[ch] - 1.5,
"ch{ch}: per-band SNR {:.1} regressed vs whole-pair {:.1}",
sp[ch],
sw[ch]
);
}
Ok(())
}
#[test]
fn silence_stays_off() -> Result<()> {
let mut enc = LcEncoder::new(48_000, 2, 128_000)?;
let pcm = [0.0f32; LONG_WINDOW_LEN];
let payload = enc.encode_frame(&[&pcm, &pcm])?;
let (_, ms, mask_bits) = parse_ms(&payload, enc.fs_index())?;
assert_eq!(ms.mask, MsMask::Off);
assert_eq!(mask_bits, 2);
Ok(())
}
#[test]
fn mono_mask_form_is_off() {
let ms = MsBands::off();
assert_eq!(ms.form(), MaskForm::Off);
assert_eq!(ms.overhead_bits(), 2);
}