use crate::deep_plc::DeepPlcArgs;
use crate::osce_args::OsceFrameModels;
use crate::range_coder::RangeCoder;
use crate::silk::cng::silk_cng;
use crate::silk::decode_core::silk_decode_core;
use crate::silk::decode_indices::silk_decode_indices;
use crate::silk::decode_parameters::silk_decode_parameters;
use crate::silk::decode_pulses::silk_decode_pulses;
use crate::silk::decoder_structs::{SilkDecoderControl, SilkDecoderState};
use crate::silk::define::*;
use crate::silk::plc::{silk_plc, silk_plc_glue_frames};
pub const FLAG_DECODE_NORMAL: i32 = 0;
pub const FLAG_PACKET_LOST: i32 = 1;
pub const FLAG_DECODE_LBRR: i32 = 2;
#[allow(clippy::too_many_arguments)]
pub fn silk_decode_frame(
ps_dec: &mut SilkDecoderState,
ps_range_dec: &mut RangeCoder,
p_out: &mut [i16],
p_n: &mut i32,
lost_flag: i32,
cond_coding: i32,
deep_plc: Option<&mut DeepPlcArgs>,
osce: Option<&OsceFrameModels>,
) -> i32 {
#[cfg(not(feature = "osce"))]
let _ = osce;
let l = ps_dec.frame_length as usize;
let mut ps_dec_ctrl = SilkDecoderControl::new();
ps_dec_ctrl.ltp_scale_q14 = 0;
debug_assert!(l > 0 && l <= MAX_FRAME_LENGTH);
if lost_flag == FLAG_DECODE_NORMAL
|| (lost_flag == FLAG_DECODE_LBRR
&& ps_dec.lbrr_flags[ps_dec.n_frames_decoded as usize] == 1)
{
let mut pulses: [i16; MAX_FRAME_LENGTH] = [0; MAX_FRAME_LENGTH];
#[cfg(feature = "osce")]
let ec_start = ps_range_dec.tell();
silk_decode_indices(
ps_dec,
ps_range_dec,
ps_dec.n_frames_decoded,
lost_flag,
cond_coding,
);
silk_decode_pulses(
ps_range_dec,
&mut pulses,
ps_dec.indices.signal_type as i32,
ps_dec.indices.quant_offset_type as i32,
ps_dec.frame_length,
);
silk_decode_parameters(ps_dec, &mut ps_dec_ctrl, cond_coding);
silk_decode_core(ps_dec, &mut ps_dec_ctrl, p_out, &pulses);
let mv_len = ps_dec.ltp_mem_length - ps_dec.frame_length;
ps_dec.out_buf.copy_within(ps_dec.frame_length as usize..ps_dec.ltp_mem_length as usize, 0);
ps_dec.out_buf[mv_len as usize..mv_len as usize + l].copy_from_slice(&p_out[..l]);
#[cfg(feature = "osce")]
osce_enhance(ps_dec, &ps_dec_ctrl, &mut p_out[..l], ps_range_dec.tell() - ec_start, osce);
silk_plc(ps_dec, &mut ps_dec_ctrl, p_out, 0, deep_plc);
ps_dec.loss_cnt = 0;
ps_dec.prev_signal_type = ps_dec.indices.signal_type as i32;
ps_dec.first_frame_after_reset = 0;
} else {
silk_plc(ps_dec, &mut ps_dec_ctrl, p_out, 1, deep_plc);
#[cfg(feature = "osce")]
{
let method = ps_dec.osce.method();
crate::dnn::osce::osce_reset(&mut ps_dec.osce, method);
}
let mv_len = ps_dec.ltp_mem_length - ps_dec.frame_length;
ps_dec.out_buf.copy_within(ps_dec.frame_length as usize..ps_dec.ltp_mem_length as usize, 0);
ps_dec.out_buf[mv_len as usize..mv_len as usize + l].copy_from_slice(&p_out[..l]);
}
silk_cng(ps_dec, &ps_dec_ctrl, p_out, l);
silk_plc_glue_frames(ps_dec, p_out, l);
ps_dec.lag_prev = ps_dec_ctrl.pitch_l[ps_dec.nb_subfr as usize - 1];
*p_n = l as i32;
0
}
#[cfg(feature = "osce")]
fn osce_enhance(
ps_dec: &mut SilkDecoderState,
ctrl: &SilkDecoderControl,
frame: &mut [i16],
num_bits: i32,
models: Option<&OsceFrameModels>,
) {
use crate::dnn::osce::{OsceFrame, OsceModels, osce_enhance_frame};
let unloaded = OsceModels {
arch: crate::dnn::DnnArch::Portable,
lace: None,
nolace: None,
#[cfg(feature = "osce-bwe")]
bbwenet: None,
};
let params = OsceFrame {
fs_khz: ps_dec.fs_khz,
nb_subfr: ps_dec.nb_subfr,
lpc_order: ps_dec.lpc_order,
signal_type: ps_dec.indices.signal_type as i32,
pred_coef_q12: &ctrl.pred_coef_q12,
pitch_l: &ctrl.pitch_l,
ltp_coef_q14: &ctrl.ltp_coef_q14,
gains_q16: &ctrl.gains_q16,
num_bits,
};
osce_enhance_frame(&mut ps_dec.osce, models.unwrap_or(&unloaded), ¶ms, frame);
}