use crate::filterbank;
use crate::fixedpoint::*;
use crate::tables::SYNTH_OVERLAP_OFFSETS;
pub fn synthesize(
subband_samples: &[i16],
memory: &mut [i16],
output: &mut [i16],
frame_size: i16,
scale_param: i16,
) {
let n = frame_size as usize;
let half = shr(frame_size, 1) as usize; let mut filtered = [0i16; 320];
filterbank::inverse(subband_samples, &mut filtered, frame_size);
if scale_param > 0 {
for i in 0..n {
filtered[i] = shr(filtered[i], scale_param);
}
} else if scale_param < 0 {
let shift = negate(scale_param);
for i in 0..n {
filtered[i] = shl(filtered[i], shift);
}
}
for k in 0..half {
let acc = l_mac(0, SYNTH_OVERLAP_OFFSETS[k], filtered[half - 1 - k]);
let acc = l_mac(acc, SYNTH_OVERLAP_OFFSETS[n - 1 - k], memory[k]);
output[k] = extract_h(l_shl(acc, 2));
}
for k in 0..half {
let acc = l_mac(0, SYNTH_OVERLAP_OFFSETS[half + k], filtered[k]);
let acc = l_mac(acc, negate(SYNTH_OVERLAP_OFFSETS[half - 1 - k]), memory[half - 1 - k]);
output[half + k] = extract_h(l_shl(acc, 2));
}
memory[..half].copy_from_slice(&filtered[half..half + half]);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_synthesize_zeros() {
let subband = [0i16; 320];
let mut memory = [0i16; 160];
let mut output = [0i16; 320];
synthesize(&subband, &mut memory, &mut output, 320, 0);
for (i, &s) in output.iter().enumerate() {
assert_eq!(s, 0, "sample {} should be 0", i);
}
}
#[test]
fn test_memory_update() {
let subband = [0i16; 320];
let mut memory = [0i16; 160];
let mut output = [0i16; 320];
synthesize(&subband, &mut memory, &mut output, 320, 0);
for (i, &m) in memory.iter().enumerate() {
assert_eq!(m, 0, "memory[{}] should be 0", i);
}
}
}