#![allow(dead_code, reason = "consumed incrementally as the SILK decoder stages land")]
use super::indices::MAX_NB_SUBFR;
use super::tables::{CB_LAGS_STAGE2, CB_LAGS_STAGE2_10_MS, CB_LAGS_STAGE3, CB_LAGS_STAGE3_10_MS};
const PE_MIN_LAG_MS: i32 = 2;
const PE_MAX_LAG_MS: i32 = 18;
pub(crate) fn decode_pitch(lag_index: i16, contour_index: i8, fs_khz: i32, nb_subfr: usize) -> [i32; MAX_NB_SUBFR] {
let contour = contour_index as usize;
let cb_row = |k: usize| -> i32 {
if fs_khz == 8 {
if nb_subfr == MAX_NB_SUBFR {
i32::from(CB_LAGS_STAGE2[k][contour])
} else {
i32::from(CB_LAGS_STAGE2_10_MS[k][contour])
}
} else if nb_subfr == MAX_NB_SUBFR {
i32::from(CB_LAGS_STAGE3[k][contour])
} else {
i32::from(CB_LAGS_STAGE3_10_MS[k][contour])
}
};
let min_lag = PE_MIN_LAG_MS * fs_khz;
let max_lag = PE_MAX_LAG_MS * fs_khz;
let lag = min_lag + i32::from(lag_index);
let mut pitch_lags = [0i32; MAX_NB_SUBFR];
for (k, out) in pitch_lags.iter_mut().enumerate().take(nb_subfr) {
*out = (lag + cb_row(k)).clamp(min_lag, max_lag);
}
pitch_lags
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decode_pitch_matches_reference_pins() {
assert_eq!(decode_pitch(100, 5, 8, 4), [116, 116, 116, 117]);
assert_eq!(decode_pitch(100, 1, 8, 2), [117, 116, 0, 0]);
assert_eq!(decode_pitch(200, 20, 12, 4), [216, 216, 216, 216]);
assert_eq!(decode_pitch(250, 30, 16, 4), [288, 284, 280, 276]);
assert_eq!(decode_pitch(250, 11, 16, 2), [279, 285, 0, 0]);
assert_eq!(decode_pitch(0, 33, 16, 4), [32, 32, 35, 41]);
assert_eq!(decode_pitch(255, 33, 16, 4), [278, 284, 288, 288]);
}
}