use crate::codecs::g729::impls::codec::state::EncoderState;
use crate::codecs::g729::impls::constants::{L_INTER10, L_SUBFR, L_THRESH_ERR};
use crate::codecs::g729::impls::dsp::arith::{add, sub};
use crate::codecs::g729::impls::dsp::arith32::{l_add, l_sub};
use crate::codecs::g729::impls::dsp::oper32::{l_extract, mpy_32_16};
use crate::codecs::g729::impls::dsp::shift::l_shl;
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16, Word32};
use crate::codecs::g729::impls::tables::annexa::TAB_ZONE;
pub(crate) fn test_excitation_error(state: &EncoderState, t0: i16, t0_frac: i16) -> i16 {
let mut ctx = DspContext::default();
let t1 = if t0_frac > 0 {
add(&mut ctx, Word16(t0), Word16(1)).0
} else {
t0
};
let mut i = sub(&mut ctx, Word16(t1), Word16((L_SUBFR + L_INTER10) as i16)).0;
if i < 0 {
i = 0;
}
let zone1 = TAB_ZONE[i as usize] as usize;
i = add(&mut ctx, Word16(t1), Word16((L_INTER10 - 2) as i16)).0;
let zone2 = TAB_ZONE[i as usize] as usize;
let mut l_maxloc = Word32(-1);
for zi in (zone1..=zone2).rev() {
let l_acc = l_sub(&mut ctx, Word32(state.l_exc_err[zi]), l_maxloc);
if l_acc.0 > 0 {
l_maxloc = Word32(state.l_exc_err[zi]);
}
}
if l_sub(&mut ctx, l_maxloc, Word32(L_THRESH_ERR)).0 > 0 {
1
} else {
0
}
}
pub(crate) fn update_excitation_error(state: &mut EncoderState, gain_pit: i16, t0: i16) {
let mut ctx = DspContext::default();
let mut l_worst = Word32(-1);
let n = sub(&mut ctx, Word16(t0), Word16(L_SUBFR as i16)).0;
if n < 0 {
let mut l_temp = Word32(state.l_exc_err[0]);
for _ in 0..2 {
let (hi, lo) = l_extract(l_temp);
l_temp = mpy_32_16(hi, lo, Word16(gain_pit));
l_temp = l_shl(&mut ctx, l_temp, 1);
l_temp = l_add(&mut ctx, Word32(0x0000_4000), l_temp);
if l_sub(&mut ctx, l_temp, l_worst).0 > 0 {
l_worst = l_temp;
}
}
} else {
let zone1 = TAB_ZONE[n as usize] as usize;
let i = sub(&mut ctx, Word16(t0), Word16(1)).0;
let zone2 = TAB_ZONE[i as usize] as usize;
for zi in zone1..=zone2 {
let (hi, lo) = l_extract(Word32(state.l_exc_err[zi]));
let mut l_temp = mpy_32_16(hi, lo, Word16(gain_pit));
l_temp = l_shl(&mut ctx, l_temp, 1);
l_temp = l_add(&mut ctx, Word32(0x0000_4000), l_temp);
if l_sub(&mut ctx, l_temp, l_worst).0 > 0 {
l_worst = l_temp;
}
}
}
for i in (1..4).rev() {
state.l_exc_err[i] = state.l_exc_err[i - 1];
}
state.l_exc_err[0] = l_worst.0;
}