ref: dbeb86fd0531b618b501a76414536b27d8d4484f
parent: 1c6c3d17a7d1868ef49834405f5f0ee9f59a5a00
author: Jean-Marc Valin <[email protected]>
date: Mon Aug 15 06:01:00 EDT 2011
Making the IMDCT work on interleaved data Saves a copy in the decoder
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -440,42 +440,38 @@
const int C = CHANNELS(_C);
const int N = mode->shortMdctSize<<LM;
const int overlap = OVERLAP(mode);
+ VARDECL(opus_val32, x);
+ SAVE_STACK;
+
+ ALLOC(x, N+overlap, opus_val32);
c=0; do {
int j;
- VARDECL(opus_val32, x);
- VARDECL(opus_val32, tmp);
- int b;
- int N2 = N;
- int B = 1;
- SAVE_STACK;
+ int b;
+ int N2 = N;
+ int B = 1;
- ALLOC(x, N+overlap, opus_val32);
- ALLOC(tmp, N, opus_val32);
+ if (shortBlocks)
+ {
+ N2 = mode->shortMdctSize;
+ B = shortBlocks;
+ }
+ /* Prevents problems from the imdct doing the overlap-add */
+ CELT_MEMSET(x, 0, overlap);
- if (shortBlocks)
- {
- N2 = mode->shortMdctSize;
- B = shortBlocks;
- }
- /* Prevents problems from the imdct doing the overlap-add */
- CELT_MEMSET(x, 0, overlap);
+ for (b=0;b<B;b++)
+ {
+ /* IMDCT on the interleaved the sub-frames */
+ clt_mdct_backward(&mode->mdct, &X[b+c*N2*B], x+N2*b, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM, B);
+ }
- for (b=0;b<B;b++)
- {
- /* De-interleaving the sub-frames */
- for (j=0;j<N2;j++)
- tmp[j] = X[(j*B+b)+c*N2*B];
- clt_mdct_backward(&mode->mdct, tmp, x+N2*b, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM);
- }
-
- for (j=0;j<overlap;j++)
- out_mem[c][j] = x[j] + overlap_mem[c][j];
- for (;j<N;j++)
- out_mem[c][j] = x[j];
- for (j=0;j<overlap;j++)
- overlap_mem[c][j] = x[N+j];
- RESTORE_STACK;
+ for (j=0;j<overlap;j++)
+ out_mem[c][j] = x[j] + overlap_mem[c][j];
+ for (;j<N;j++)
+ out_mem[c][j] = x[j];
+ for (j=0;j<overlap;j++)
+ overlap_mem[c][j] = x[N+j];
} while (++c<C);
+ RESTORE_STACK;
}
static void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int _C, int downsample, const opus_val16 *coef, celt_sig *mem)
--- a/libcelt/mdct.c
+++ b/libcelt/mdct.c
@@ -202,7 +202,8 @@
RESTORE_STACK;
}
-void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out, const opus_val16 * restrict window, int overlap, int shift)
+void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out,
+ const opus_val16 * restrict window, int overlap, int shift, int stride)
{
int i;
int N, N2, N4;
@@ -227,7 +228,7 @@
{
/* Temp pointers to make it really clear to the compiler what we're doing */
const kiss_fft_scalar * restrict xp1 = in;
- const kiss_fft_scalar * restrict xp2 = in+N2-1;
+ const kiss_fft_scalar * restrict xp2 = in+stride*(N2-1);
kiss_fft_scalar * restrict yp = f2;
const kiss_twiddle_scalar *t = &l->trig[0];
for(i=0;i<N4;i++)
@@ -238,8 +239,8 @@
/* works because the cos is nearly one */
*yp++ = yr - S_MUL(yi,sine);
*yp++ = yi + S_MUL(yr,sine);
- xp1+=2;
- xp2-=2;
+ xp1+=2*stride;
+ xp2-=2*stride;
}
}
--- a/libcelt/mdct.h
+++ b/libcelt/mdct.h
@@ -60,6 +60,7 @@
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
(scales implicitly by 1/2) */
-void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const opus_val16 * restrict window, int overlap, int shift);
+void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out,
+ const opus_val16 * restrict window, int overlap, int shift, int stride);
#endif
--- a/libcelt/tests/mdct-test.c
+++ b/libcelt/tests/mdct-test.c
@@ -122,7 +122,7 @@
{
for (k=0;k<nfft;++k)
out[k] = 0;
- clt_mdct_backward(&cfg,in,out, window, nfft/2, 0);
+ clt_mdct_backward(&cfg,in,out, window, nfft/2, 0, 1);
check_inv(in,out,nfft,isinverse);
} else {
clt_mdct_forward(&cfg,in,out,window, nfft/2, 0);