use crate::codecs::g729::impls::codec::state::DecoderState;
use crate::codecs::g729::impls::constants::{
GAP1, GAP2, GAP3, L_LIMIT, M, M_LIMIT, NC, NC0, NC0_B, NC1, NC1_B,
};
use crate::codecs::g729::impls::dsp::arith::{add, extract_h, sub};
use crate::codecs::g729::impls::dsp::arith32::{
l_deposit_h, l_deposit_l, l_mac, l_msu, l_mult, l_sub,
};
use crate::codecs::g729::impls::dsp::shift::{l_shl, shr};
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16};
use crate::codecs::g729::impls::tables::annexa::{fg, fg_sum, fg_sum_inv, lspcb1, lspcb2};
#[inline(always)]
fn w(v: i16) -> Word16 {
Word16(v)
}
pub(crate) fn lsp_expand_1_2(buf: &mut [i16; M], gap: i16) {
let mut ctx = DspContext::default();
for j in 1..M {
let diff = sub(&mut ctx, w(buf[j - 1]), w(buf[j]));
let sum = add(&mut ctx, diff, w(gap));
let tmp = shr(&mut ctx, sum, 1);
if tmp.0 > 0 {
buf[j - 1] = sub(&mut ctx, w(buf[j - 1]), tmp).0;
buf[j] = add(&mut ctx, w(buf[j]), tmp).0;
}
}
}
pub(crate) fn lsp_prev_compose(
state: &DecoderState,
mode: usize,
lsp_ele: &[i16; M],
lsp: &mut [i16; M],
) {
let mut ctx = DspContext::default();
for j in 0..M {
let mut l_acc = l_mult(&mut ctx, w(lsp_ele[j]), w(fg_sum(mode, j)));
for k in 0..4 {
l_acc = l_mac(&mut ctx, l_acc, w(state.freq_prev[k][j]), w(fg(mode, k, j)));
}
lsp[j] = extract_h(l_acc).0;
}
}
pub(crate) fn lsp_prev_extract(
state: &DecoderState,
mode: usize,
lsp: &[i16; M],
lsp_ele: &mut [i16; M],
) {
let mut ctx = DspContext::default();
for j in 0..M {
let mut l_temp = l_deposit_h(w(lsp[j]));
for k in 0..4 {
l_temp = l_msu(
&mut ctx,
l_temp,
w(state.freq_prev[k][j]),
w(fg(mode, k, j)),
);
}
let temp = extract_h(l_temp);
l_temp = l_mult(&mut ctx, temp, w(fg_sum_inv(mode, j)));
lsp_ele[j] = extract_h(l_shl(&mut ctx, l_temp, 3)).0;
}
}
pub(crate) fn lsp_prev_update(state: &mut DecoderState, lsp_ele: &[i16; M]) {
for k in (1..4).rev() {
state.freq_prev[k] = state.freq_prev[k - 1];
}
state.freq_prev[0] = *lsp_ele;
}
pub(crate) fn lsp_stability(buf: &mut [i16; M]) {
let mut ctx = DspContext::default();
for j in 0..(M - 1) {
let l_diff = l_sub(&mut ctx, l_deposit_l(w(buf[j + 1])), l_deposit_l(w(buf[j])));
if l_diff.0 < 0 {
buf.swap(j, j + 1);
}
}
if sub(&mut ctx, w(buf[0]), w(L_LIMIT)).0 < 0 {
buf[0] = L_LIMIT;
}
for j in 0..(M - 1) {
let l_diff = l_sub(&mut ctx, l_deposit_l(w(buf[j + 1])), l_deposit_l(w(buf[j])));
if l_sub(&mut ctx, l_diff, l_deposit_l(w(GAP3))).0 < 0 {
buf[j + 1] = add(&mut ctx, w(buf[j]), w(GAP3)).0;
}
}
if sub(&mut ctx, w(buf[M - 1]), w(M_LIMIT)).0 > 0 {
buf[M - 1] = M_LIMIT;
}
}
fn lsp_get_quant(
state: &mut DecoderState,
mode: usize,
code0: usize,
code1: usize,
code2: usize,
lspq: &mut [i16; M],
) {
let mut buf = [0i16; M];
let mut ctx = DspContext::default();
for (j, bj) in buf.iter_mut().enumerate().take(NC) {
*bj = add(&mut ctx, w(lspcb1(code0, j)), w(lspcb2(code1, j))).0;
}
for (j, bj) in buf.iter_mut().enumerate().take(M).skip(NC) {
*bj = add(&mut ctx, w(lspcb1(code0, j)), w(lspcb2(code2, j))).0;
}
lsp_expand_1_2(&mut buf, GAP1);
lsp_expand_1_2(&mut buf, GAP2);
lsp_prev_compose(state, mode, &buf, lspq);
lsp_prev_update(state, &buf);
lsp_stability(lspq);
}
fn lsp_iqua_cs(state: &mut DecoderState, prm: &[i16], lsp_q: &mut [i16; M], erase: i16) {
let mut ctx = DspContext::default();
if erase == 0 {
let mode_index = (shr(&mut ctx, w(prm[0]), NC0_B as i16).0 & 1) as usize;
let code0 = (prm[0] & (NC0 as i16 - 1)) as usize;
let code1 = (shr(&mut ctx, w(prm[1]), NC1_B as i16).0 & (NC1 as i16 - 1)) as usize;
let code2 = (prm[1] & (NC1 as i16 - 1)) as usize;
lsp_get_quant(state, mode_index, code0, code1, code2, lsp_q);
state.prev_lsp = *lsp_q;
state.prev_ma = mode_index as i16;
} else {
*lsp_q = state.prev_lsp;
let mut buf = [0i16; M];
lsp_prev_extract(state, state.prev_ma as usize, &state.prev_lsp, &mut buf);
lsp_prev_update(state, &buf);
}
}
pub(crate) fn d_lsp(state: &mut DecoderState, prm: &[i16], lsp_q: &mut [i16; M], erase: i16) {
let mut lsf_q = [0i16; M];
lsp_iqua_cs(state, prm, &mut lsf_q, erase);
crate::codecs::g729::impls::lp::lsf::lsf_to_lsp(&lsf_q, lsp_q);
}