use oxideav_celt::range_decoder::RangeDecoder;
use oxideav_core::Result;
use crate::silk::tables;
use crate::toc::OpusBandwidth;
pub fn pitch_lag_bounds(bw: OpusBandwidth) -> (i32, i32) {
match bw {
OpusBandwidth::Narrowband => (16, 144),
OpusBandwidth::Mediumband => (24, 216),
OpusBandwidth::Wideband => (32, 288),
_ => (32, 288),
}
}
pub fn decode_absolute_pitch_lag(rc: &mut RangeDecoder<'_>, bw: OpusBandwidth) -> Result<i32> {
let (min_lag, max_lag) = pitch_lag_bounds(bw);
let high = rc.decode_icdf(&tables::PITCH_LAG_NB_HIGH_ICDF, 8) as i32;
let low = rc.decode_icdf(&tables::PITCH_LAG_NB_LOW_ICDF, 8) as i32;
let lag = min_lag + high * 4 + low;
Ok(lag.clamp(min_lag, max_lag))
}
pub fn decode_delta_pitch_lag(rc: &mut RangeDecoder<'_>) -> Result<i32> {
let delta = rc.decode_icdf(&tables::PITCH_DELTA_ICDF, 8) as i32;
Ok(delta - 9)
}
pub fn decode_pitch_contour(rc: &mut RangeDecoder<'_>, _bw: OpusBandwidth) -> Result<usize> {
Ok(rc.decode_icdf(&tables::PITCH_CONTOUR_NB_20MS_ICDF, 8))
}
pub fn expand_pitch_contour(
primary_lag: i32,
_contour_idx: usize,
bw: OpusBandwidth,
lags: &mut [i32],
) {
let (min_lag, max_lag) = pitch_lag_bounds(bw);
for lag in lags.iter_mut() {
*lag = primary_lag.clamp(min_lag, max_lag);
}
}
pub fn decode_ltp_filter(rc: &mut RangeDecoder<'_>, periodicity: usize) -> [f32; 5] {
let icdf: &[u8] = match periodicity {
0 => &tables::LTP_FILTER_P0_ICDF,
1 => &tables::LTP_FILTER_P1_ICDF,
_ => &tables::LTP_FILTER_P2_ICDF,
};
let idx = rc.decode_icdf(icdf, 8);
let s = (idx as f32 - 4.0) / 32.0;
[
-0.05 - s * 0.02,
0.10,
0.70 + s * 0.10,
0.10,
-0.05 - s * 0.02,
]
}