use crate::codecs::g729::impls::codec::state::EncoderState;
use crate::codecs::g729::impls::constants::{GPCLIP2, L_SUBFR};
use crate::codecs::g729::impls::dsp::arith::{add, extract_h, negate, sub};
use crate::codecs::g729::impls::dsp::arith32::{l_deposit_h, l_deposit_l, l_mult, l_sub};
use crate::codecs::g729::impls::dsp::div::div_s;
use crate::codecs::g729::impls::dsp::oper32::l_extract;
use crate::codecs::g729::impls::dsp::shift::{l_shl, l_shr, norm_l, shl, shr};
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16};
use crate::codecs::g729::impls::gain::predict::predict_encoder_gain;
use crate::codecs::g729::impls::gain::presel::gbk_presel;
pub(crate) struct QuantizePrep {
pub gcode0: i16,
pub exp_gcode0: i16,
pub cand1: usize,
pub cand2: usize,
pub coeff: [i16; 5],
pub coeff_lsf: [i16; 5],
}
pub(crate) fn prepare_quantization(
state: &EncoderState,
code: &[i16; L_SUBFR],
g_coeff: &[i16; 5],
exp_coeff: &[i16; 5],
tameflag: i16,
) -> QuantizePrep {
let mut ctx = DspContext::default();
let mut gcode0 = 0i16;
let mut exp_gcode0 = 0i16;
predict_encoder_gain(&state.past_qua_en, code, &mut gcode0, &mut exp_gcode0);
let l_tmp1 = l_mult(&mut ctx, Word16(g_coeff[0]), Word16(g_coeff[2]));
let e1_t = add(&mut ctx, Word16(exp_coeff[0]), Word16(exp_coeff[2])).0;
let exp1 = add(&mut ctx, Word16(e1_t), Word16(-1)).0;
let l_tmp2 = l_mult(&mut ctx, Word16(g_coeff[4]), Word16(g_coeff[4]));
let e2_t = add(&mut ctx, Word16(exp_coeff[4]), Word16(exp_coeff[4])).0;
let exp2 = add(&mut ctx, Word16(e2_t), Word16(1)).0;
let (l_tmp, exp) = if sub(&mut ctx, Word16(exp1), Word16(exp2)).0 > 0 {
let shift = sub(&mut ctx, Word16(exp1), Word16(exp2)).0;
let l_tmp1s = l_shr(&mut ctx, l_tmp1, shift);
(l_sub(&mut ctx, l_tmp1s, l_tmp2), exp2)
} else {
let shift = sub(&mut ctx, Word16(exp2), Word16(exp1)).0;
let l_tmp2s = l_shr(&mut ctx, l_tmp2, shift);
(l_sub(&mut ctx, l_tmp1, l_tmp2s), exp1)
};
let sft = norm_l(l_tmp);
let l_tmpn = l_shl(&mut ctx, l_tmp, sft);
let denom = extract_h(l_tmpn).0;
let expt = add(&mut ctx, Word16(exp), Word16(sft)).0;
let exp_denom = sub(&mut ctx, Word16(expt), Word16(16)).0;
let mut inv_denom = div_s(Word16(16384), Word16(denom)).0;
inv_denom = negate(&mut ctx, Word16(inv_denom)).0;
let exp_inv_denom = sub(&mut ctx, Word16(14 + 15), Word16(exp_denom)).0;
let l_tmp1 = l_mult(&mut ctx, Word16(g_coeff[2]), Word16(g_coeff[1]));
let exp1 = add(&mut ctx, Word16(exp_coeff[2]), Word16(exp_coeff[1])).0;
let l_tmp2 = l_mult(&mut ctx, Word16(g_coeff[3]), Word16(g_coeff[4]));
let e2_t = add(&mut ctx, Word16(exp_coeff[3]), Word16(exp_coeff[4])).0;
let exp2 = add(&mut ctx, Word16(e2_t), Word16(1)).0;
let (l_tmp, exp) = if sub(&mut ctx, Word16(exp1), Word16(exp2)).0 > 0 {
let d = sub(&mut ctx, Word16(exp1), Word16(exp2)).0;
let d1 = add(&mut ctx, Word16(d), Word16(1)).0;
let l_tmp1s = l_shr(&mut ctx, l_tmp1, d1);
let l_tmp2s = l_shr(&mut ctx, l_tmp2, 1);
let e = sub(&mut ctx, Word16(exp2), Word16(1)).0;
(l_sub(&mut ctx, l_tmp1s, l_tmp2s), e)
} else {
let d = sub(&mut ctx, Word16(exp2), Word16(exp1)).0;
let d1 = add(&mut ctx, Word16(d), Word16(1)).0;
let l_tmp1s = l_shr(&mut ctx, l_tmp1, 1);
let l_tmp2s = l_shr(&mut ctx, l_tmp2, d1);
let e = sub(&mut ctx, Word16(exp1), Word16(1)).0;
(l_sub(&mut ctx, l_tmp1s, l_tmp2s), e)
};
let sft = norm_l(l_tmp);
let l_tmpn = l_shl(&mut ctx, l_tmp, sft);
let nume = extract_h(l_tmpn).0;
let expt = add(&mut ctx, Word16(exp), Word16(sft)).0;
let exp_nume = sub(&mut ctx, Word16(expt), Word16(16)).0;
let expt2 = add(&mut ctx, Word16(exp_nume), Word16(exp_inv_denom)).0;
let sft2 = sub(&mut ctx, Word16(expt2), Word16(9 + 16 - 1)).0;
let l_nm = l_mult(&mut ctx, Word16(nume), Word16(inv_denom));
let l_acc = l_shr(&mut ctx, l_nm, sft2);
let mut best_gain0 = extract_h(l_acc).0;
if tameflag == 1 && sub(&mut ctx, Word16(best_gain0), Word16(GPCLIP2)).0 > 0 {
best_gain0 = GPCLIP2;
}
let l_tmp1 = l_mult(&mut ctx, Word16(g_coeff[0]), Word16(g_coeff[3]));
let exp1 = add(&mut ctx, Word16(exp_coeff[0]), Word16(exp_coeff[3])).0;
let l_tmp2 = l_mult(&mut ctx, Word16(g_coeff[1]), Word16(g_coeff[4]));
let e2_t = add(&mut ctx, Word16(exp_coeff[1]), Word16(exp_coeff[4])).0;
let exp2 = add(&mut ctx, Word16(e2_t), Word16(1)).0;
let (l_tmp, exp) = if sub(&mut ctx, Word16(exp1), Word16(exp2)).0 > 0 {
let d = sub(&mut ctx, Word16(exp1), Word16(exp2)).0;
let d1 = add(&mut ctx, Word16(d), Word16(1)).0;
let l_tmp1s = l_shr(&mut ctx, l_tmp1, d1);
let l_tmp2s = l_shr(&mut ctx, l_tmp2, 1);
let e = sub(&mut ctx, Word16(exp2), Word16(1)).0;
(l_sub(&mut ctx, l_tmp1s, l_tmp2s), e)
} else {
let d = sub(&mut ctx, Word16(exp2), Word16(exp1)).0;
let d1 = add(&mut ctx, Word16(d), Word16(1)).0;
let l_tmp1s = l_shr(&mut ctx, l_tmp1, 1);
let l_tmp2s = l_shr(&mut ctx, l_tmp2, d1);
let e = sub(&mut ctx, Word16(exp1), Word16(1)).0;
(l_sub(&mut ctx, l_tmp1s, l_tmp2s), e)
};
let sft = norm_l(l_tmp);
let l_tmpn = l_shl(&mut ctx, l_tmp, sft);
let nume = extract_h(l_tmpn).0;
let expt = add(&mut ctx, Word16(exp), Word16(sft)).0;
let exp_nume = sub(&mut ctx, Word16(expt), Word16(16)).0;
let expt2 = add(&mut ctx, Word16(exp_nume), Word16(exp_inv_denom)).0;
let sft2 = sub(&mut ctx, Word16(expt2), Word16(2 + 16 - 1)).0;
let l_nm = l_mult(&mut ctx, Word16(nume), Word16(inv_denom));
let l_acc = l_shr(&mut ctx, l_nm, sft2);
let best_gain1 = extract_h(l_acc).0;
let best_gain = [best_gain0, best_gain1];
let gcode0_org = if sub(&mut ctx, Word16(exp_gcode0), Word16(4)).0 >= 0 {
let sh = sub(&mut ctx, Word16(exp_gcode0), Word16(4)).0;
shr(&mut ctx, Word16(gcode0), sh).0
} else {
let mut l_acc = l_deposit_l(Word16(gcode0));
let sh = sub(&mut ctx, Word16(4 + 16), Word16(exp_gcode0)).0;
l_acc = l_shl(&mut ctx, l_acc, sh);
extract_h(l_acc).0
};
let mut cand1 = 0usize;
let mut cand2 = 0usize;
gbk_presel(&best_gain, &mut cand1, &mut cand2, gcode0_org);
let mut exp_min = [0i16; 5];
exp_min[0] = add(&mut ctx, Word16(exp_coeff[0]), Word16(13)).0;
exp_min[1] = add(&mut ctx, Word16(exp_coeff[1]), Word16(14)).0;
let eg2 = shl(&mut ctx, Word16(exp_gcode0), 1);
let eg2m21 = sub(&mut ctx, eg2, Word16(21));
exp_min[2] = add(&mut ctx, Word16(exp_coeff[2]), eg2m21).0;
let egm3 = sub(&mut ctx, Word16(exp_gcode0), Word16(3));
exp_min[3] = add(&mut ctx, Word16(exp_coeff[3]), egm3).0;
let egm4 = sub(&mut ctx, Word16(exp_gcode0), Word16(4));
exp_min[4] = add(&mut ctx, Word16(exp_coeff[4]), egm4).0;
let mut e_min = exp_min[0];
for &e in &exp_min[1..] {
if sub(&mut ctx, Word16(e), Word16(e_min)).0 < 0 {
e_min = e;
}
}
let mut coeff = [0i16; 5];
let mut coeff_lsf = [0i16; 5];
for i in 0..5 {
let j = sub(&mut ctx, Word16(exp_min[i]), Word16(e_min)).0;
let mut l_tmp = l_deposit_h(Word16(g_coeff[i]));
l_tmp = l_shr(&mut ctx, l_tmp, j);
let (ch, cl) = l_extract(l_tmp);
coeff[i] = ch.0;
coeff_lsf[i] = cl.0;
}
QuantizePrep {
gcode0,
exp_gcode0,
cand1,
cand2,
coeff,
coeff_lsf,
}
}