use crate::silk::macros::{
silk_add_lshift32, silk_div32_16, silk_lshift, silk_rshift_round, silk_sat16, silk_smlawb,
silk_smulbb,
};
const STEREO_INTERP_LEN_MS: i32 = 8;
pub struct StereoDecState {
pub pred_prev_q13: [i32; 2],
pub s_mid: [i16; 2],
pub s_side: [i16; 2],
}
impl Default for StereoDecState {
fn default() -> Self {
Self {
pred_prev_q13: [0; 2],
s_mid: [0; 2],
s_side: [0; 2],
}
}
}
pub fn silk_stereo_ms_to_lr(
state: &mut StereoDecState,
x1: &mut [i16],
x2: &mut [i16],
pred_q13: &[i32; 2],
fs_khz: i32,
frame_length: i32,
) {
let fl = frame_length as usize;
x1[0] = state.s_mid[0];
x1[1] = state.s_mid[1];
x2[0] = state.s_side[0];
x2[1] = state.s_side[1];
state.s_mid[0] = x1[fl];
state.s_mid[1] = x1[fl + 1];
state.s_side[0] = x2[fl];
state.s_side[1] = x2[fl + 1];
let mut pred0_q13 = state.pred_prev_q13[0];
let mut pred1_q13 = state.pred_prev_q13[1];
let denom_q16 = silk_div32_16(1 << 16, STEREO_INTERP_LEN_MS * fs_khz);
let delta0_q13 =
silk_rshift_round(silk_smulbb(pred_q13[0] - state.pred_prev_q13[0], denom_q16), 16);
let delta1_q13 =
silk_rshift_round(silk_smulbb(pred_q13[1] - state.pred_prev_q13[1], denom_q16), 16);
let interp_len = (STEREO_INTERP_LEN_MS * fs_khz) as usize;
for n in 0..interp_len {
pred0_q13 += delta0_q13;
pred1_q13 += delta1_q13;
let sum = silk_lshift(
silk_add_lshift32(x1[n] as i32 + x1[n + 2] as i32, x1[n + 1] as i32, 1),
9,
);
let sum = silk_smlawb(silk_lshift(x2[n + 1] as i32, 8), sum, pred0_q13);
let sum = silk_smlawb(sum, silk_lshift(x1[n + 1] as i32, 11), pred1_q13);
x2[n + 1] = silk_sat16(silk_rshift_round(sum, 8)) as i16;
}
pred0_q13 = pred_q13[0];
pred1_q13 = pred_q13[1];
for n in interp_len..fl {
let sum = silk_lshift(
silk_add_lshift32(x1[n] as i32 + x1[n + 2] as i32, x1[n + 1] as i32, 1),
9,
);
let sum = silk_smlawb(silk_lshift(x2[n + 1] as i32, 8), sum, pred0_q13);
let sum = silk_smlawb(sum, silk_lshift(x1[n + 1] as i32, 11), pred1_q13);
x2[n + 1] = silk_sat16(silk_rshift_round(sum, 8)) as i16;
}
state.pred_prev_q13[0] = pred_q13[0];
state.pred_prev_q13[1] = pred_q13[1];
for n in 0..fl {
let mid = x1[n + 1] as i32;
let side = x2[n + 1] as i32;
x1[n + 1] = silk_sat16(mid + side) as i16; x2[n + 1] = silk_sat16(mid - side) as i16; }
}