use crate::codecs::g729::impls::bitstream::itu_params::pack_speech_params;
use crate::codecs::g729::impls::codec::encode_sub::{
encode_subframe, synthesize_weighted_speech_subframes,
};
use crate::codecs::g729::impls::codec::state::{
EncoderState, ENC_EXC_OFFSET, NEW_SPEECH_OFFSET, P_WINDOW_OFFSET, SPEECH_OFFSET, WSP_OFFSET,
};
use crate::codecs::g729::impls::constants::{
GAMMA1, L_FRAME, L_SUBFR, L_TOTAL, L_WINDOW, M, MP1, PIT_MAX, PIT_MIN,
};
use crate::codecs::g729::impls::dsp::arith::{add, sub};
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16};
use crate::codecs::g729::impls::filter::resid::residu_i16;
fn copy_window_or_none(old_speech: &[i16]) -> Option<[i16; L_WINDOW]> {
let mut window = [0i16; L_WINDOW];
let src = old_speech.get(P_WINDOW_OFFSET..P_WINDOW_OFFSET + L_WINDOW)?;
window.copy_from_slice(src);
Some(window)
}
pub(crate) fn advance_frame_counter(frame: &mut i16) {
if *frame == 32767 {
*frame = 256;
} else {
*frame = (*frame).wrapping_add(1);
}
}
pub(crate) fn encode_speech_frame_impl(state: &mut EncoderState, pcm: &[i16; L_FRAME]) -> [u8; 10] {
let mut ctx = DspContext::default();
let mut pre = *pcm;
crate::codecs::g729::impls::preproc::pre_process_frame(state, &mut pre);
state.old_speech[NEW_SPEECH_OFFSET..NEW_SPEECH_OFFSET + L_FRAME].copy_from_slice(&pre);
let p_window = match copy_window_or_none(&state.old_speech) {
Some(window) => window,
None => {
debug_assert!(false, "old_speech window bounds invariant violated");
return [0u8; 10];
}
};
let mut r_h = [0i16; M + 1];
let mut r_l = [0i16; M + 1];
let mut exp_r0 = 0i16;
crate::codecs::g729::impls::lp::autocorr::autocorr_10(
&p_window,
&mut r_h,
&mut r_l,
&mut exp_r0,
);
crate::codecs::g729::impls::lp::window::lag_window_10(&mut r_h, &mut r_l);
let mut a_lpc = [0i16; MP1];
let mut rc = [0i16; M];
crate::codecs::g729::impls::lp::levinson::levinson_10(
state, &r_h, &r_l, &mut a_lpc, &mut rc, None,
);
let mut lsp_new = [0i16; M];
crate::codecs::g729::impls::lp::az_lsp::az_lsp(&a_lpc, &mut lsp_new, &state.lsp_old);
let mut lsp_new_q = [0i16; M];
let mut lsp_codes = [0i16; 2];
crate::codecs::g729::impls::lsp_quant::encode::qua_lsp(
state,
&lsp_new,
&mut lsp_new_q,
&mut lsp_codes,
);
let mut aq_t = [0i16; MP1 * 2];
crate::codecs::g729::impls::lp::interp::int_qlpc(&state.lsp_old_q, &lsp_new_q, &mut aq_t);
let mut ap_t = [0i16; MP1 * 2];
let mut aq0 = [0i16; MP1];
aq0.copy_from_slice(&aq_t[..MP1]);
let mut aq1 = [0i16; MP1];
aq1.copy_from_slice(&aq_t[MP1..]);
let mut ap0 = [0i16; MP1];
let mut ap1 = [0i16; MP1];
crate::codecs::g729::impls::lp::weight::weight_az(&aq0, GAMMA1, &mut ap0);
crate::codecs::g729::impls::lp::weight::weight_az(&aq1, GAMMA1, &mut ap1);
ap_t[..MP1].copy_from_slice(&ap0);
ap_t[MP1..].copy_from_slice(&ap1);
state.lsp_old = lsp_new;
state.lsp_old_q = lsp_new_q;
let speech_base = SPEECH_OFFSET;
let exc_base = ENC_EXC_OFFSET;
let mut resid = [0i16; L_SUBFR];
residu_i16(&aq0, &state.old_speech, speech_base, &mut resid, L_SUBFR);
state.old_exc[exc_base..exc_base + L_SUBFR].copy_from_slice(&resid);
residu_i16(
&aq1,
&state.old_speech,
speech_base + L_SUBFR,
&mut resid,
L_SUBFR,
);
state.old_exc[exc_base + L_SUBFR..exc_base + L_FRAME].copy_from_slice(&resid);
synthesize_weighted_speech_subframes(state, &ap_t);
let t_op = crate::codecs::g729::impls::pitch::open_loop::search_open_loop(
&state.old_wsp,
WSP_OFFSET,
PIT_MAX,
L_FRAME,
);
let mut t0_min = sub(&mut ctx, Word16(t_op), Word16(3)).0;
if sub(&mut ctx, Word16(t0_min), Word16(PIT_MIN)).0 < 0 {
t0_min = PIT_MIN;
}
let mut t0_max = add(&mut ctx, Word16(t0_min), Word16(6)).0;
if sub(&mut ctx, Word16(t0_max), Word16(PIT_MAX)).0 > 0 {
t0_max = PIT_MAX;
t0_min = sub(&mut ctx, Word16(t0_max), Word16(6)).0;
}
let mut params = [Word16(0); 11];
params[0] = Word16(lsp_codes[0]);
params[1] = Word16(lsp_codes[1]);
let mut p = 2usize;
for sf in 0..2 {
let i_subfr = sf * L_SUBFR;
let mut ap = [0i16; MP1];
ap.copy_from_slice(&ap_t[sf * MP1..sf * MP1 + MP1]);
encode_subframe(
state,
i_subfr,
&ap,
&mut t0_min,
&mut t0_max,
&mut params,
&mut p,
);
}
state.old_speech.copy_within(L_FRAME..L_TOTAL, 0);
state
.old_wsp
.copy_within(L_FRAME..(L_FRAME + PIT_MAX as usize), 0);
state.old_exc.copy_within(
L_FRAME..(L_FRAME + PIT_MAX as usize + crate::codecs::g729::impls::constants::L_INTERPOL),
0,
);
advance_frame_counter(&mut state.frame);
pack_speech_params(¶ms)
}