use crate::range_coder::RangeCoder;
use crate::silk::define::*;
use crate::silk::shell_coder::silk_shell_encoder;
use crate::silk::tables::*;
fn combine_and_check(
pulses_comb: &mut [i32],
pulses_in: &[i32],
max_pulses: i32,
len: usize,
) -> i32 {
for k in 0..len {
let sum = pulses_in[2 * k] + pulses_in[2 * k + 1];
if sum > max_pulses {
return 1;
}
pulses_comb[k] = sum;
}
0
}
pub fn silk_encode_pulses(
ps_range_enc: &mut RangeCoder,
signal_type: i32,
quant_offset_type: i32,
pulses: &[i8],
frame_length: usize,
) {
let mut pulses_comb = [0i32; 8];
let mut abs_pulses = [0i32; MAX_FRAME_LENGTH + SHELL_CODEC_FRAME_LENGTH];
let iter = frame_length.div_ceil(SHELL_CODEC_FRAME_LENGTH);
for i in 0..frame_length {
abs_pulses[i] = pulses[i].abs() as i32;
}
let mut sum_pulses = [0i32; MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH];
let mut n_rshifts = [0i32; MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH];
for i in 0..iter {
let abs_pulses_ptr = &mut abs_pulses[i * SHELL_CODEC_FRAME_LENGTH..];
n_rshifts[i] = 0;
loop {
let mut scale_down = combine_and_check(
&mut pulses_comb,
abs_pulses_ptr,
SILK_MAX_PULSES_TABLE[0] as i32,
8,
);
let pulses_temp8 = pulses_comb;
scale_down += combine_and_check(
&mut pulses_comb,
&pulses_temp8,
SILK_MAX_PULSES_TABLE[1] as i32,
4,
);
let pulses_temp4 = pulses_comb;
scale_down += combine_and_check(
&mut pulses_comb,
&pulses_temp4,
SILK_MAX_PULSES_TABLE[2] as i32,
2,
);
let pulses_temp2 = pulses_comb;
let mut sum_pulse_val = [sum_pulses[i]];
scale_down += combine_and_check(
&mut sum_pulse_val,
&pulses_temp2,
SILK_MAX_PULSES_TABLE[3] as i32,
1,
);
sum_pulses[i] = sum_pulse_val[0];
if scale_down > 0 {
n_rshifts[i] += 1;
for k in 0..SHELL_CODEC_FRAME_LENGTH {
abs_pulses_ptr[k] >>= 1;
}
} else {
break;
}
}
}
let mut min_sum_bits_q5 = i32::MAX;
let mut rate_level_index = 0;
for k in 0..N_RATE_LEVELS - 1 {
let n_bits_ptr = &SILK_PULSES_PER_BLOCK_BITS_Q5[k];
let mut sum_bits_q5 = SILK_RATE_LEVELS_BITS_Q5[(signal_type >> 1) as usize][k] as i32;
for i in 0..iter {
if n_rshifts[i] > 0 {
sum_bits_q5 += n_bits_ptr[SILK_MAX_PULSES + 1] as i32;
} else {
sum_bits_q5 += n_bits_ptr[sum_pulses[i] as usize] as i32;
}
}
if sum_bits_q5 < min_sum_bits_q5 {
min_sum_bits_q5 = sum_bits_q5;
rate_level_index = k;
}
}
ps_range_enc.encode_icdf(
rate_level_index as i32,
&SILK_RATE_LEVELS_ICDF[(signal_type >> 1) as usize],
8,
);
let cdf_ptr = &SILK_PULSES_PER_BLOCK_ICDF[rate_level_index];
for i in 0..iter {
if n_rshifts[i] == 0 {
ps_range_enc.encode_icdf(sum_pulses[i], cdf_ptr, 8);
} else {
ps_range_enc.encode_icdf(SILK_MAX_PULSES as i32 + 1, cdf_ptr, 8);
for _ in 0..n_rshifts[i] - 1 {
ps_range_enc.encode_icdf(
SILK_MAX_PULSES as i32 + 1,
&SILK_PULSES_PER_BLOCK_ICDF[N_RATE_LEVELS - 1],
8,
);
}
ps_range_enc.encode_icdf(
sum_pulses[i],
&SILK_PULSES_PER_BLOCK_ICDF[N_RATE_LEVELS - 1],
8,
);
}
}
for i in 0..iter {
if sum_pulses[i] > 0 {
silk_shell_encoder(
ps_range_enc,
&abs_pulses[i * SHELL_CODEC_FRAME_LENGTH..(i + 1) * SHELL_CODEC_FRAME_LENGTH],
);
}
}
for i in 0..iter {
if n_rshifts[i] > 0 {
let n_ls = n_rshifts[i] - 1;
for k in 0..SHELL_CODEC_FRAME_LENGTH {
let abs_q = pulses[i * SHELL_CODEC_FRAME_LENGTH + k].abs() as i32;
for j in (1..=n_ls).rev() {
let bit = (abs_q >> j) & 1;
ps_range_enc.encode_icdf(bit, &SILK_LSB_ICDF, 8);
}
let bit = abs_q & 1;
ps_range_enc.encode_icdf(bit, &SILK_LSB_ICDF, 8);
}
}
}
let icdf_offset = (7 * (quant_offset_type + signal_type * 2)) as usize;
for i in 0..iter {
let p = sum_pulses[i];
if p > 0 {
let icdf0 = SILK_SIGN_ICDF[icdf_offset + ((p & 0x1F) as usize).min(6)];
let icdf = [icdf0, 0u8];
for j in 0..SHELL_CODEC_FRAME_LENGTH {
let pulse = pulses[i * SHELL_CODEC_FRAME_LENGTH + j];
if pulse != 0 {
let mapped = if pulse > 0 { 1i32 } else { 0i32 };
ps_range_enc.encode_icdf(mapped, &icdf, 8);
}
}
}
}
}