static void subband_transform(DCAEncContext *c, const int32_t *input) { int ch, subs, i, k, j; for (ch = 0; ch < c->fullband_channels; ch++) { /* History is copied because it is also needed for PSY */ int32_t hist[512]; int hist_start = 0; const int chi = c->channel_order_tab[ch]; for (i = 0; i < 512; i++) hist[i] = c->history[i][ch]; for (subs = 0; subs < SUBBAND_SAMPLES; subs++) { int32_t accum[64]; int32_t resp; int band; /* Calculate the convolutions at once */ for (i = 0; i < 64; i++) accum[i] = 0; for (k = 0, i = hist_start, j = 0; i < 512; k = (k + 1) & 63, i++, j++) accum[k] += mul32(hist[i], c->band_interpolation[j]); for (i = 0; i < hist_start; k = (k + 1) & 63, i++, j++) accum[k] += mul32(hist[i], c->band_interpolation[j]); for (k = 16; k < 32; k++) accum[k] = accum[k] - accum[31 - k]; for (k = 32; k < 48; k++) accum[k] = accum[k] + accum[95 - k]; for (band = 0; band < 32; band++) { resp = 0; for (i = 16; i < 48; i++) { int s = (2 * band + 1) * (2 * (i + 16) + 1); resp += mul32(accum[i], cos_t(s << 3)) >> 3; } c->subband[subs][band][ch] = ((band + 1) & 2) ? -resp : resp; } /* Copy in 32 new samples from input */ for (i = 0; i < 32; i++) hist[i + hist_start] = input[(subs * 32 + i) * c->channels + chi]; hist_start = (hist_start + 32) & 511; } } }
static void fft(const int32_t in[2 * 256], cplx32 out[256]) { cplx32 buf[256], rin[256], rout[256]; int i, j, k, l; /* do two transforms in parallel */ for (i = 0; i < 256; i++) { /* Apply the Hann window */ rin[i].re = mul32(in[2 * i], 0x3fffffff - (cos_t(8 * i + 2) >> 1)); rin[i].im = mul32(in[2 * i + 1], 0x3fffffff - (cos_t(8 * i + 6) >> 1)); } /* pre-rotation */ for (i = 0; i < 256; i++) { buf[i].re = mul32(cos_t(4 * i + 2), rin[i].re) - mul32(sin_t(4 * i + 2), rin[i].im); buf[i].im = mul32(cos_t(4 * i + 2), rin[i].im) + mul32(sin_t(4 * i + 2), rin[i].re); } for (j = 256, l = 1; j != 1; j >>= 1, l <<= 1) { for (k = 0; k < 256; k += j) { for (i = k; i < k + j / 2; i++) { cplx32 sum, diff; int t = 8 * l * i; sum.re = buf[i].re + buf[i + j / 2].re; sum.im = buf[i].im + buf[i + j / 2].im; diff.re = buf[i].re - buf[i + j / 2].re; diff.im = buf[i].im - buf[i + j / 2].im; buf[i].re = half32(sum.re); buf[i].im = half32(sum.im); buf[i + j / 2].re = mul32(diff.re, cos_t(t)) - mul32(diff.im, sin_t(t)); buf[i + j / 2].im = mul32(diff.im, cos_t(t)) + mul32(diff.re, sin_t(t)); } } } /* post-rotation */ for (i = 0; i < 256; i++) { int b = ff_reverse[i]; rout[i].re = mul32(buf[b].re, cos_t(4 * i)) - mul32(buf[b].im, sin_t(4 * i)); rout[i].im = mul32(buf[b].im, cos_t(4 * i)) + mul32(buf[b].re, sin_t(4 * i)); } for (i = 0; i < 256; i++) { /* separate the results of the two transforms */ cplx32 o1, o2; o1.re = rout[i].re - rout[255 - i].re; o1.im = rout[i].im + rout[255 - i].im; o2.re = rout[i].im - rout[255 - i].im; o2.im = -rout[i].re - rout[255 - i].re; /* combine them into one long transform */ out[i].re = mul32( o1.re + o2.re, cos_t(2 * i + 1)) + mul32( o1.im - o2.im, sin_t(2 * i + 1)); out[i].im = mul32( o1.im + o2.im, cos_t(2 * i + 1)) + mul32(-o1.re + o2.re, sin_t(2 * i + 1)); } }
static inline int32_t sin_t(int x) { return cos_t(x - 512); }