use crate::codecs::g729::impls::constants::L_SUBFR;
use crate::codecs::g729::impls::dsp::arith::add;
use crate::codecs::g729::impls::dsp::shift::{shl, shr};
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16};
pub fn decod_acelp(sign: Word16, index: Word16) -> [Word16; L_SUBFR] {
let mut ctx = DspContext::default();
let mut pos = [Word16(0); 4];
let mut idx = index;
let mut i = Word16(idx.0 & 7);
let i5 = shl(&mut ctx, i, 2);
pos[0] = add(&mut ctx, i, i5);
idx = shr(&mut ctx, idx, 3);
i = Word16(idx.0 & 7);
let i5 = shl(&mut ctx, i, 2);
i = add(&mut ctx, i, i5);
pos[1] = add(&mut ctx, i, Word16(1));
idx = shr(&mut ctx, idx, 3);
i = Word16(idx.0 & 7);
let i5 = shl(&mut ctx, i, 2);
i = add(&mut ctx, i, i5);
pos[2] = add(&mut ctx, i, Word16(2));
idx = shr(&mut ctx, idx, 3);
let j = Word16(idx.0 & 1);
idx = shr(&mut ctx, idx, 1);
i = Word16(idx.0 & 7);
let i5 = shl(&mut ctx, i, 2);
i = add(&mut ctx, i, i5);
i = add(&mut ctx, i, Word16(3));
pos[3] = add(&mut ctx, i, j);
let mut cod = [Word16(0); L_SUBFR];
let mut s = sign;
for p in pos {
let bit = Word16(s.0 & 1);
s = shr(&mut ctx, s, 1);
let index = p.0 as usize;
if index < L_SUBFR {
cod[index] = if bit.0 != 0 {
Word16(8191)
} else {
Word16(-8192)
};
}
}
cod
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decod_acelp_has_4_pulses() {
let cod = decod_acelp(Word16(0b1010), Word16(0x1234));
let non_zero = cod.iter().filter(|c| c.0 != 0).count();
assert_eq!(non_zero, 4);
}
}