use crate::range_coder::RangeCoder;
use crate::silk::define::*;
use crate::silk::tables::*;
#[inline]
fn decode_split(ps_range_dec: &mut RangeCoder, p: i32, shell_table: &[u8]) -> (i16, i16) {
if p > 0 {
let idx = SILK_SHELL_CODE_TABLE_OFFSETS[p as usize] as usize;
let child1 = ps_range_dec.decode_icdf(&shell_table[idx..], 8) as i16;
let child2 = (p - child1 as i32) as i16;
(child1, child2)
} else {
(0, 0)
}
}
fn silk_shell_decoder(pulses0: &mut [i16], ps_range_dec: &mut RangeCoder, pulses4: i32) {
let mut pulses3: [i16; 2] = [0; 2];
let mut pulses2: [i16; 4] = [0; 4];
let mut pulses1: [i16; 8] = [0; 8];
let (p3_0, p3_1) = decode_split(ps_range_dec, pulses4, &SILK_SHELL_CODE_TABLE3);
pulses3[0] = p3_0;
pulses3[1] = p3_1;
let (p2_0, p2_1) = decode_split(ps_range_dec, pulses3[0] as i32, &SILK_SHELL_CODE_TABLE2);
pulses2[0] = p2_0;
pulses2[1] = p2_1;
let (p1_0, p1_1) = decode_split(ps_range_dec, pulses2[0] as i32, &SILK_SHELL_CODE_TABLE1);
pulses1[0] = p1_0;
pulses1[1] = p1_1;
let (p0_0, p0_1) = decode_split(ps_range_dec, pulses1[0] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[0] = p0_0;
pulses0[1] = p0_1;
let (p0_2, p0_3) = decode_split(ps_range_dec, pulses1[1] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[2] = p0_2;
pulses0[3] = p0_3;
let (p1_2, p1_3) = decode_split(ps_range_dec, pulses2[1] as i32, &SILK_SHELL_CODE_TABLE1);
pulses1[2] = p1_2;
pulses1[3] = p1_3;
let (p0_4, p0_5) = decode_split(ps_range_dec, pulses1[2] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[4] = p0_4;
pulses0[5] = p0_5;
let (p0_6, p0_7) = decode_split(ps_range_dec, pulses1[3] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[6] = p0_6;
pulses0[7] = p0_7;
let (p2_2, p2_3) = decode_split(ps_range_dec, pulses3[1] as i32, &SILK_SHELL_CODE_TABLE2);
pulses2[2] = p2_2;
pulses2[3] = p2_3;
let (p1_4, p1_5) = decode_split(ps_range_dec, pulses2[2] as i32, &SILK_SHELL_CODE_TABLE1);
pulses1[4] = p1_4;
pulses1[5] = p1_5;
let (p0_8, p0_9) = decode_split(ps_range_dec, pulses1[4] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[8] = p0_8;
pulses0[9] = p0_9;
let (p0_10, p0_11) = decode_split(ps_range_dec, pulses1[5] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[10] = p0_10;
pulses0[11] = p0_11;
let (p1_6, p1_7) = decode_split(ps_range_dec, pulses2[3] as i32, &SILK_SHELL_CODE_TABLE1);
pulses1[6] = p1_6;
pulses1[7] = p1_7;
let (p0_12, p0_13) = decode_split(ps_range_dec, pulses1[6] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[12] = p0_12;
pulses0[13] = p0_13;
let (p0_14, p0_15) = decode_split(ps_range_dec, pulses1[7] as i32, &SILK_SHELL_CODE_TABLE0);
pulses0[14] = p0_14;
pulses0[15] = p0_15;
}
fn silk_decode_signs(
ps_range_dec: &mut RangeCoder,
pulses: &mut [i16],
frame_length: i32,
signal_type: i32,
quant_offset_type: i32,
sum_pulses: &[i32],
) {
let n_blocks =
(frame_length + SHELL_CODEC_FRAME_LENGTH as i32 / 2) >> LOG2_SHELL_CODEC_FRAME_LENGTH;
let i_base = 7 * (quant_offset_type + (signal_type << 1));
for i in 0..n_blocks as usize {
let p = sum_pulses[i];
if p > 0 {
let idx = (p & 0x1F).min(6) as usize;
let icdf_0 = SILK_SIGN_ICDF[i_base as usize + idx];
let icdf = [icdf_0, 0u8];
let start = i * SHELL_CODEC_FRAME_LENGTH;
for j in 0..SHELL_CODEC_FRAME_LENGTH {
if pulses[start + j] > 0 {
let sign = ps_range_dec.decode_icdf(&icdf, 8);
if sign == 0 {
pulses[start + j] = -pulses[start + j];
}
}
}
}
}
}
pub fn silk_decode_pulses(
ps_range_dec: &mut RangeCoder,
pulses: &mut [i16],
signal_type: i32,
quant_offset_type: i32,
frame_length: i32,
) {
let mut sum_pulses: [i32; MAX_NB_SHELL_BLOCKS] = [0; MAX_NB_SHELL_BLOCKS];
let mut n_lshifts: [i32; MAX_NB_SHELL_BLOCKS] = [0; MAX_NB_SHELL_BLOCKS];
let rate_level_index =
ps_range_dec.decode_icdf(&SILK_RATE_LEVELS_ICDF[(signal_type >> 1) as usize], 8) as usize;
let mut iter = (frame_length as usize) >> LOG2_SHELL_CODEC_FRAME_LENGTH;
if iter * SHELL_CODEC_FRAME_LENGTH < frame_length as usize {
iter += 1;
}
let cdf_ptr = &SILK_PULSES_PER_BLOCK_ICDF[rate_level_index];
for i in 0..iter {
n_lshifts[i] = 0;
sum_pulses[i] = ps_range_dec.decode_icdf(cdf_ptr, 8);
while sum_pulses[i] == (SILK_MAX_PULSES as i32 + 1) {
n_lshifts[i] += 1;
if n_lshifts[i] == 10 {
sum_pulses[i] = ps_range_dec
.decode_icdf(&SILK_PULSES_PER_BLOCK_ICDF[N_RATE_LEVELS - 1][1..], 8);
} else {
sum_pulses[i] =
ps_range_dec.decode_icdf(&SILK_PULSES_PER_BLOCK_ICDF[N_RATE_LEVELS - 1], 8);
}
}
}
for i in 0..iter {
let start = i * SHELL_CODEC_FRAME_LENGTH;
if sum_pulses[i] > 0 {
silk_shell_decoder(&mut pulses[start..], ps_range_dec, sum_pulses[i]);
} else {
for j in 0..SHELL_CODEC_FRAME_LENGTH {
pulses[start + j] = 0;
}
}
}
for i in 0..iter {
if n_lshifts[i] > 0 {
let n_ls = n_lshifts[i];
let start = i * SHELL_CODEC_FRAME_LENGTH;
for k in 0..SHELL_CODEC_FRAME_LENGTH {
let mut abs_q = pulses[start + k] as i32;
for _ in 0..n_ls {
abs_q <<= 1;
abs_q += ps_range_dec.decode_icdf(&SILK_LSB_ICDF, 8);
}
pulses[start + k] = abs_q as i16;
}
sum_pulses[i] |= n_ls << 5;
}
}
silk_decode_signs(
ps_range_dec,
pulses,
frame_length,
signal_type,
quant_offset_type,
&sum_pulses,
);
}
const LOG2_SHELL_CODEC_FRAME_LENGTH: usize = 4;
const MAX_NB_SHELL_BLOCKS: usize = MAX_FRAME_LENGTH.div_ceil(SHELL_CODEC_FRAME_LENGTH);