+const MERGE_ORDER_44K: &[u8] = &[
+ 4, 4, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 0,
+ 2, 0, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0
+];
+const MERGE_ORDER_40K: &[u8] = &[
+ 4, 4, 2, 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 2, 0, 0,
+ 2, 0, 0, 4, 2, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0
+];
+
+fn synth_filter(src: &[f32], dst: &mut [f32], len: usize, step: usize, bands: usize, idx: usize)
+{
+ let off = (len - step) / bands + 1;
+ let params = match step {
+ 10 => &SPARAMS10[idx],
+ 20 => &SPARAMS20[idx],
+ 40 => &SPARAMS40[idx],
+ _ => &SPARAMS84[idx],
+ };
+
+ if step == 10 {
+ synth_step0_10(src, dst, step, off, params);
+ synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB10[idx]);
+ } else if step == 20 {
+ synth_step0_20(src, dst, step, off, params);
+ synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB20[idx]);
+ } else if step == 40 {
+ synth_step0_40(src, dst, step, off, params);
+ synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB40[idx]);
+ } else {
+ synth_step0_84(src, dst, step, off, params);
+ synth_step1(src, dst, len, bands, step, off, params.p0, &AVC_TAB84[idx]);
+ }
+}
+
+fn synth_recursive(dst: &mut [f32], tmp: &mut [f32], size: usize, order: &[u8], order_idx: &mut usize, dir: bool) {
+ let bands = order[*order_idx] as usize;
+ *order_idx += 1;
+ if bands == 0 { return; }
+ let sub_size = size / bands;
+ let mut sub_dir = false;
+ for (dst, tmp) in dst.chunks_mut(sub_size).take(bands).zip(tmp.chunks_mut(sub_size)) {
+ synth_recursive(dst, tmp, sub_size, order, order_idx, sub_dir);
+ sub_dir = !sub_dir;
+ }
+ for el in tmp.iter_mut().take(size) { *el = 0.0; }
+ let step = if bands == 2 {
+ if sub_size <= 20 {
+ 10
+ } else if sub_size <= 40 {
+ 20
+ } else {
+ 40
+ }
+ } else {
+ 84
+ };
+ for (i, src) in dst.chunks_mut(sub_size).take(bands).enumerate() {
+ let idx = if !dir { i } else { bands - 1 - i };
+ synth_filter(src, tmp, size, step, bands, idx);
+ }
+ dst[..size].copy_from_slice(&tmp[..size]);
+}
+
+fn synth_generic(src: &[f32], dst: &mut [f32], tmpbuf: &mut [f32; COEFFS * 2], is_40khz: bool, size: usize) {
+ let order = if is_40khz { MERGE_ORDER_40K } else { MERGE_ORDER_44K };
+ dst[..size].copy_from_slice(&src[..size]);
+ let mut order_idx = 0;
+ synth_recursive(dst, tmpbuf, size, order, &mut order_idx, false);
+ for el in dst.iter_mut().take(COEFFS) { *el *= 0.125; }
+}
+