use oxideav_celt::range_decoder::RangeDecoder;
use oxideav_core::Result;
use crate::silk::tables;
pub fn decode_excitation(
rc: &mut RangeDecoder<'_>,
frame_len: usize,
_subframe_len: usize,
signal_type: u8,
_quant_offset_type: u8,
seed: u32,
) -> Result<Vec<f32>> {
let rate_icdf: &[u8] = if signal_type == 2 {
&tables::RATE_LEVEL_VOICED_ICDF
} else {
&tables::RATE_LEVEL_INACTIVE_ICDF
};
let rate_level = rc.decode_icdf(rate_icdf, 8).min(10);
let n_shells = frame_len.div_ceil(16);
let mut pulse_counts = vec![0i32; n_shells];
let pulse_icdf = &tables::PULSE_COUNT_ICDF[rate_level];
for i in 0..n_shells {
let count = rc.decode_icdf(pulse_icdf, 8) as i32;
pulse_counts[i] = count;
}
let mut excitation = vec![0f32; frame_len];
let mut s = seed;
for i in 0..frame_len {
s = s.wrapping_mul(196_314_165).wrapping_add(907_633_515);
let shell = pulse_counts.get(i / 16).copied().unwrap_or(0) as f32;
let base = (shell + 1.0) * 40.0; let sign = if s & 0x8000_0000 != 0 { -1.0 } else { 1.0 };
let noise = ((s >> 8) as i32 as f32) / (i32::MAX as f32);
let v = sign * base * (0.25 + 0.75 * noise.abs());
excitation[i] = v;
s = s.wrapping_add(v as u32);
}
Ok(excitation)
}