use super::rangecoder::RangeDecoder;
pub(crate) struct LsfGrid {
pub(crate) match1: Vec<u16>,
pub(crate) match1_alt: Vec<u16>,
pub(crate) match0: Vec<u16>,
pub(crate) match0_alt: Vec<u16>,
}
pub(crate) struct SmplTables {
pub(crate) lsf_sel: Vec<Vec<u16>>,
pub(crate) lsf_grid: LsfGrid,
pub(crate) lsf_stage2: Vec<Vec<Vec<Vec<Vec<u16>>>>>,
pub(crate) lsf_extra: Vec<u16>,
}
pub(crate) fn load_smpl_tables() -> &'static SmplTables {
&super::smpl_lsf_seed::lsf_built().tables
}
#[derive(Default, Clone)]
pub(crate) struct SmplLsfState {
pub(crate) prev_stage1: i32,
pub(crate) prev_match: bool,
pub(crate) have_prev: bool,
pub(crate) prev_gain_idx: i32,
pub(crate) prev_filt_idx: i32,
pub(crate) prev_lag: i32,
pub(crate) prev_frac_lag: i32,
pub(crate) prev_lag_samples: f32,
pub(crate) prev_lagblk: i32,
pub(crate) prev_lagidx: i32,
}
pub(crate) fn smpl_advance_lsf_state(st: &mut SmplLsfState, intf: usize, stage1: i32) {
let m = intf != 0 && stage1 == st.prev_stage1;
if !m {
st.prev_gain_idx = -1;
st.prev_filt_idx = -1;
st.prev_lag = -1;
st.prev_frac_lag = -1;
st.prev_lagblk = -1;
st.prev_lagidx = -1;
}
st.prev_stage1 = stage1;
st.prev_match = m;
st.have_prev = true;
}
pub(crate) struct SmplLsfIndices {
pub(crate) stage1: i32,
pub(crate) grid: i32,
pub(crate) stage2: [i32; 16],
pub(crate) extra: i32,
}
pub(crate) fn decode_smpl_lsf(
dec: &mut RangeDecoder,
t: &SmplTables,
st: &mut SmplLsfState,
config: usize,
intf: usize,
) -> SmplLsfIndices {
let mut idx = SmplLsfIndices {
stage1: 0,
grid: 0,
stage2: [0; 16],
extra: 0,
};
let sel = if intf == 0 {
0
} else if st.prev_stage1 != 0 {
2
} else {
1
};
let stage1 = dec.decode_cdf(&t.lsf_sel[sel]);
idx.stage1 = stage1;
let enter_match = intf != 0;
let m = enter_match && (stage1 == st.prev_stage1);
if !m {
st.prev_gain_idx = -1;
st.prev_filt_idx = -1;
st.prev_lag = -1;
st.prev_frac_lag = -1;
}
st.prev_stage1 = stage1;
let grid_cdf: &[u16] = if m {
if stage1 != 0 {
&t.lsf_grid.match1
} else {
&t.lsf_grid.match1_alt
}
} else if stage1 != 0 {
&t.lsf_grid.match0_alt
} else {
&t.lsf_grid.match0
};
let grid = dec.decode_cdf(grid_cdf);
idx.grid = grid;
st.prev_match = m;
st.have_prev = true;
let st2 = &t.lsf_stage2[stage1 as usize][config][grid as usize];
for (k, c) in st2.iter().enumerate().take(16) {
idx.stage2[k] = dec.decode_cdf(c);
}
idx.extra = dec.decode_cdf(&t.lsf_extra);
log::trace!(
"mlow LSF intf={intf} sel={sel} m={m}: stage1={stage1} grid={grid} extra={} stage2={:?}",
idx.extra,
idx.stage2
);
idx
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Value;
#[test]
fn lsf_frame0_matches_go() {
let recs: Value =
serde_json::from_str(include_str!("testdata/lsf_vectors.json")).expect("lsf_vectors");
let t = load_smpl_tables();
let arr = recs.as_array().unwrap();
assert!(!arr.is_empty());
for rec in arr {
let frame = hex::decode(rec["frame"].as_str().unwrap()).unwrap();
let mut st = SmplLsfState::default();
let mut dec = RangeDecoder::new(&frame[1..]);
let idx = decode_smpl_lsf(&mut dec, t, &mut st, 0, 0);
assert_eq!(idx.stage1, rec["stage1"].as_i64().unwrap() as i32, "stage1");
assert_eq!(idx.grid, rec["grid"].as_i64().unwrap() as i32, "grid");
assert_eq!(idx.extra, rec["extra"].as_i64().unwrap() as i32, "extra");
let want2: Vec<i32> = rec["stage2"]
.as_array()
.unwrap()
.iter()
.map(|x| x.as_i64().unwrap() as i32)
.collect();
assert_eq!(idx.stage2.to_vec(), want2, "stage2");
assert_eq!(dec.err, 0, "no decode error");
}
}
}