+ int32_t prev = *hist;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int64_t a = INT64_C(2097471) * src[i] + INT64_C(6291137) * prev;
+ int64_t b = INT64_C(6291137) * src[i] + INT64_C(2097471) * prev;
+ prev = src[i];
+ *dst++ = clip23(norm23(a));
+ *dst++ = clip23(norm23(b));
+ }
+
+ *hist = prev;
+}
+
+static void sub_qmf32_fixed_c(SynthFilterContext *synth,
+ DCADCTContext *imdct,
+ int32_t *pcm_samples,
+ int32_t **subband_samples_lo,
+ int32_t **subband_samples_hi,
+ int32_t *hist1, int *offset, int32_t *hist2,
+ const int32_t *filter_coeff, ptrdiff_t npcmblocks)
+{
+ LOCAL_ALIGNED(32, int32_t, input, [32]);
+ int i, j;
+
+ for (j = 0; j < npcmblocks; j++) {
+ // Load in one sample from each subband
+ for (i = 0; i < 32; i++)
+ input[i] = subband_samples_lo[i][j];
+
+ // One subband sample generates 32 interpolated ones
+ synth->synth_filter_fixed(imdct, hist1, offset,
+ hist2, filter_coeff,
+ pcm_samples, input);
+ pcm_samples += 32;
+ }
+}
+
+static void sub_qmf64_fixed_c(SynthFilterContext *synth,
+ DCADCTContext *imdct,
+ int32_t *pcm_samples,
+ int32_t **subband_samples_lo,
+ int32_t **subband_samples_hi,
+ int32_t *hist1, int *offset, int32_t *hist2,
+ const int32_t *filter_coeff, ptrdiff_t npcmblocks)
+{
+ LOCAL_ALIGNED(32, int32_t, input, [64]);
+ int i, j;
+
+ if (!subband_samples_hi)
+ memset(&input[32], 0, sizeof(input[0]) * 32);
+
+ for (j = 0; j < npcmblocks; j++) {
+ // Load in one sample from each subband
+ if (subband_samples_hi) {
+ // Full 64 subbands, first 32 are residual coded
+ for (i = 0; i < 32; i++)
+ input[i] = subband_samples_lo[i][j] + subband_samples_hi[i][j];
+ for (i = 32; i < 64; i++)
+ input[i] = subband_samples_hi[i][j];
+ } else {
+ // Only first 32 subbands
+ for (i = 0; i < 32; i++)
+ input[i] = subband_samples_lo[i][j];
+ }
+
+ // One subband sample generates 64 interpolated ones
+ synth->synth_filter_fixed_64(imdct, hist1, offset,
+ hist2, filter_coeff,
+ pcm_samples, input);
+ pcm_samples += 64;
+ }
+}
+
+static void decor_c(int32_t *dst, const int32_t *src, int coeff, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] += src[i] * coeff + (1 << 2) >> 3;
+}
+
+static void dmix_sub_xch_c(int32_t *dst1, int32_t *dst2,
+ const int32_t *src, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int32_t cs = mul23(src[i], 5931520 /* M_SQRT1_2 * (1 << 23) */);
+ dst1[i] -= cs;
+ dst2[i] -= cs;
+ }
+}
+
+static void dmix_sub_c(int32_t *dst, const int32_t *src, int coeff, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] -= mul15(src[i], coeff);
+}
+
+static void dmix_add_c(int32_t *dst, const int32_t *src, int coeff, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] += mul15(src[i], coeff);
+}
+
+static void dmix_scale_c(int32_t *dst, int scale, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = mul15(dst[i], scale);
+}
+
+static void dmix_scale_inv_c(int32_t *dst, int scale_inv, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = mul16(dst[i], scale_inv);
+}
+
+static void filter0(int32_t *dst, const int32_t *src, int32_t coeff, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] -= mul22(src[i], coeff);
+}
+
+static void filter1(int32_t *dst, const int32_t *src, int32_t coeff, ptrdiff_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] -= mul23(src[i], coeff);
+}
+
+static void assemble_freq_bands_c(int32_t *dst, int32_t *src0, int32_t *src1,
+ const int32_t *coeff, ptrdiff_t len)
+{
+ int i;
+
+ filter0(src0, src1, coeff[0], len);
+ filter0(src1, src0, coeff[1], len);
+ filter0(src0, src1, coeff[2], len);
+ filter0(src1, src0, coeff[3], len);
+
+ for (i = 0; i < 8; i++, src0--) {
+ filter1(src0, src1, coeff[i + 4], len);
+ filter1(src1, src0, coeff[i + 12], len);
+ filter1(src0, src1, coeff[i + 4], len);
+ }
+
+ for (i = 0; i < len; i++) {
+ *dst++ = *src1++;
+ *dst++ = *++src0;
+ }