From 8ddd7f400d124ab14697409cf286ad7b3f7039fb Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Tue, 22 Apr 2008 13:37:16 +1000 Subject: [PATCH] mdct_backward now does the WOLA, so there isn't much left in compute_inv_mdcts --- libcelt/celt.c | 40 +++++++++++++++++++++------------------- libcelt/mdct.c | 47 +++++++++++++++++++++++++++++++++-------------- libcelt/mdct.h | 2 +- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/libcelt/celt.c b/libcelt/celt.c index 63e8c607..cc09c392 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -102,7 +102,7 @@ CELTEncoder EXPORT *celt_encoder_create(const CELTMode *mode) st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t)); st->mdct_overlap = celt_alloc(st->overlap*C*sizeof(celt_sig_t)); - st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t)); + st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t)); st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); @@ -185,37 +185,39 @@ static void compute_mdcts(const CELTMode *mode, const celt_word16_t * restrict w static void compute_inv_mdcts(const CELTMode *mode, const celt_word16_t * restrict window, celt_sig_t *X, celt_sig_t * restrict out_mem, celt_sig_t * restrict mdct_overlap) { int c, N4; - VARDECL(celt_word32_t, x); - VARDECL(celt_word32_t, tmp); const int C = CHANNELS(mode); const mdct_lookup *lookup = MDCT(mode); const int N = FRAMESIZE(mode); const int overlap = OVERLAP(mode); - SAVE_STACK; - ALLOC(x, 2*N, celt_word32_t); - ALLOC(tmp, N, celt_word32_t); N4 = (N-overlap)>>1; for (c=0;cmode, X, freq, bandE); - CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD-N)); + CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N)); compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem, st->mdct_overlap); /* De-emphasis and put everything back at the right place in the synthesis history */ @@ -462,7 +464,7 @@ CELTDecoder EXPORT *celt_decoder_create(const CELTMode *mode) st->overlap = mode->overlap; st->mdct_overlap = celt_alloc(st->overlap*C*sizeof(celt_sig_t)); - st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t)); + st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t)); st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); @@ -614,7 +616,7 @@ int EXPORT celt_decode(CELTDecoder * restrict st, unsigned char *data, int len, denormalise_bands(st->mode, X, freq, bandE); - CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD-N)); + CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N)); /* Compute inverse MDCTs */ compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem, st->mdct_overlap); diff --git a/libcelt/mdct.c b/libcelt/mdct.c index a5ab3c35..075ab5e5 100644 --- a/libcelt/mdct.c +++ b/libcelt/mdct.c @@ -189,18 +189,20 @@ void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * int i; int N, N2, N4; VARDECL(kiss_fft_scalar, f); + VARDECL(kiss_fft_scalar, f2); SAVE_STACK; N = l->n; N2 = N>>1; N4 = N>>2; ALLOC(f, N2, kiss_fft_scalar); + ALLOC(f2, N2, kiss_fft_scalar); /* Pre-rotate */ { /* 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; - kiss_fft_scalar * restrict yp = out; + kiss_fft_scalar * restrict yp = f2; kiss_fft_scalar *t = &l->trig[0]; for(i=0;ikfft, out, f, N4); + cpx32_ifft(l->kfft, f2, f, N4); /* Post-rotate */ { @@ -235,7 +237,7 @@ void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * { const kiss_fft_scalar * restrict fp1 = f; const kiss_fft_scalar * restrict fp2 = f+N2-1; - kiss_fft_scalar * restrict yp = out+N4; + kiss_fft_scalar * restrict yp = f2; for(i = 0; i < N4; i++) { *yp++ =-*fp1*2; @@ -247,28 +249,45 @@ void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * /* Mirror on both sides for TDAC */ { + kiss_fft_scalar * restrict fp1 = f2+N4-1; kiss_fft_scalar * restrict xp1 = out+N2-1; - kiss_fft_scalar * restrict xp2 = out+N2; kiss_fft_scalar * restrict yp1 = out+N4-overlap/2; + const celt_word16_t * restrict wp1 = window; + const celt_word16_t * restrict wp2 = window+overlap-1; + for(i = 0; i< N4-overlap/2; i++) + { + *xp1 = *fp1; + xp1--; + fp1--; + } + for(; i < N4; i++) + { + kiss_fft_scalar x1; + x1 = *fp1--; + *yp1++ +=-MULT16_32_Q15(*wp1, x1); + *xp1-- += MULT16_32_Q15(*wp2, x1); + wp1++; + wp2--; + } + } + { + kiss_fft_scalar * restrict fp2 = f2+N4; + kiss_fft_scalar * restrict xp2 = out+N2; kiss_fft_scalar * restrict yp2 = out+N-1-(N4-overlap/2); const celt_word16_t * restrict wp1 = window; const celt_word16_t * restrict wp2 = window+overlap-1; for(i = 0; i< N4-overlap/2; i++) { - *xp1 = *xp1; - *xp2 = *xp2; - xp1--; + *xp2 = *fp2; xp2++; + fp2++; } for(; i < N4; i++) { - kiss_fft_scalar x1, x2; - x1 = *xp1; - x2 = *xp2; - *yp1++ =-MULT16_32_Q15(*wp1, x1); - *yp2-- = MULT16_32_Q15(*wp1, x2); - *xp1-- = MULT16_32_Q15(*wp2, x1); - *xp2++ = MULT16_32_Q15(*wp2, x2); + kiss_fft_scalar x2; + x2 = *fp2++; + *yp2-- = MULT16_32_Q15(*wp1, x2); + *xp2++ = MULT16_32_Q15(*wp2, x2); wp1++; wp2--; } diff --git a/libcelt/mdct.h b/libcelt/mdct.h index 991d7c38..3917234d 100644 --- a/libcelt/mdct.h +++ b/libcelt/mdct.h @@ -60,7 +60,7 @@ void mdct_clear(mdct_lookup *l); /** Compute a forward MDCT and scale by 2/N */ void mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16_t *window, int overlap); -/** Compute a backward MDCT (no scaling) */ +/** Compute a backward MDCT (no scaling) and performs weighted overlap-add */ void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16_t * restrict window, int overlap); #endif