From 81b38c2295700e450f80d09e97d04dcb87aff617 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Fri, 29 Feb 2008 21:08:49 +1100 Subject: [PATCH] Moved mdct state and window to the mode so it can be shared between multiple encoders and decoders. --- libcelt/celt.c | 58 +++++++++++++------------------------------------ libcelt/mdct.c | 4 ++-- libcelt/mdct.h | 8 +++++-- libcelt/modes.c | 20 +++++++++++++++++ libcelt/modes.h | 7 ++++++ 5 files changed, 50 insertions(+), 47 deletions(-) diff --git a/libcelt/celt.c b/libcelt/celt.c index b1a8a85d..4bd083e6 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -72,12 +72,10 @@ struct CELTEncoder { celt_word16_t preemph; celt_sig_t *preemph_memE; celt_sig_t *preemph_memD; - - mdct_lookup mdct_lookup; + kiss_fftr_cfg fft; struct PsyDecay psy; - - celt_word16_t *window; + celt_sig_t *in_mem; celt_sig_t *mdct_overlap; celt_sig_t *out_mem; @@ -110,21 +108,13 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode) ec_byte_writeinit(&st->buf); ec_enc_init(&st->enc,&st->buf); - mdct_init(&st->mdct_lookup, 2*N); st->fft = kiss_fftr_alloc(MAX_PERIOD*C, 0, 0); psydecay_init(&st->psy, MAX_PERIOD*C/2, st->mode->Fs); - st->window = (celt_word16_t*)celt_alloc(2*N*sizeof(celt_word16_t)); st->in_mem = celt_alloc(N*C*sizeof(celt_sig_t)); st->mdct_overlap = celt_alloc(N*C*sizeof(celt_sig_t)); st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t)); - for (i=0;i<2*N;i++) - st->window[i] = 0; - for (i=0;ioverlap;i++) - st->window[N4+i] = st->window[2*N-N4-i-1] - = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/st->overlap) * sin(.5*M_PI*(i+.5)/st->overlap)); - for (i=0;i<2*N4;i++) - st->window[N-N4+i] = Q15ONE; + st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); st->preemph = QCONST16(0.8f,15); @@ -146,11 +136,9 @@ void celt_encoder_destroy(CELTEncoder *st) ec_byte_writeclear(&st->buf); - mdct_clear(&st->mdct_lookup); kiss_fft_free(st->fft); psydecay_clear(&st->psy); - celt_free(st->window); celt_free(st->in_mem); celt_free(st->mdct_overlap); celt_free(st->out_mem); @@ -178,7 +166,7 @@ inline celt_int16_t SIG2INT16(celt_sig_t x) } /** Apply window and compute the MDCT for all sub-frames and all channels in a frame */ -static celt_word32_t compute_mdcts(mdct_lookup *mdct_lookup, celt_word16_t *window, celt_sig_t *in, celt_sig_t *out, int N, int B, int C) +static celt_word32_t compute_mdcts(const mdct_lookup *mdct_lookup, celt_word16_t *window, celt_sig_t *in, celt_sig_t *out, int N, int B, int C) { int i, c; celt_word32_t E = 0; @@ -208,7 +196,7 @@ static celt_word32_t compute_mdcts(mdct_lookup *mdct_lookup, celt_word16_t *wind } /** Compute the IMDCT and apply window for all sub-frames and all channels in a frame */ -static void compute_inv_mdcts(mdct_lookup *mdct_lookup, celt_word16_t *window, celt_sig_t *X, celt_sig_t *out_mem, celt_sig_t *mdct_overlap, int N, int overlap, int B, int C) +static void compute_inv_mdcts(const mdct_lookup *mdct_lookup, celt_word16_t *window, celt_sig_t *X, celt_sig_t *out_mem, celt_sig_t *mdct_overlap, int N, int overlap, int B, int C) { int i, c, N4; VARDECL(celt_word32_t *x); @@ -285,7 +273,7 @@ int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, i } /*for (i=0;i<(B+1)*C*N;i++) printf ("%f(%d) ", in[i], i); printf ("\n");*/ /* Compute MDCTs */ - curr_power = compute_mdcts(&st->mdct_lookup, st->window, in, freq, N, B, C); + curr_power = compute_mdcts(&st->mode->mdct, st->mode->window, in, freq, N, B, C); #if 0 /* Mask disabled until it can be made to do something useful */ compute_mdct_masking(X, mask, B*C*N, st->Fs); @@ -301,8 +289,8 @@ int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, i { for (i=0;iwindow[i], in[C*i+c]); - in[C*(B*N+i)+c] = MULT16_32_Q15(st->window[N+i], in[C*(B*N+i)+c]); + in[C*i+c] = MULT16_32_Q15(st->mode->window[i], in[C*i+c]); + in[C*(B*N+i)+c] = MULT16_32_Q15(st->mode->window[N+i], in[C*(B*N+i)+c]); } } find_spectral_pitch(st->fft, &st->psy, in, st->out_mem, MAX_PERIOD, (B+1)*N, C, &pitch_index); @@ -326,7 +314,7 @@ int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, i /*for (i=0;imdct_lookup, st->window, st->out_mem+pitch_index*C, freq, N, B, C); + pitch_power = compute_mdcts(&st->mode->mdct, st->mode->window, st->out_mem+pitch_index*C, freq, N, B, C); quant_energy(st->mode, bandE, st->oldBandE, nbCompressedBytes*8/3, &st->enc); @@ -387,7 +375,7 @@ int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, i CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N)); - compute_inv_mdcts(&st->mdct_lookup, st->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); + compute_inv_mdcts(&st->mode->mdct, st->mode->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); /* De-emphasis and put everything back at the right place in the synthesis history */ for (c=0;coverlap)/2; - mdct_init(&st->mdct_lookup, 2*N); - - st->window = (celt_word16_t*)celt_alloc(2*N*sizeof(celt_word16_t)); st->mdct_overlap = celt_alloc(N*C*sizeof(celt_sig_t)); st->out_mem = celt_alloc(MAX_PERIOD*C*sizeof(celt_sig_t)); - - for (i=0;i<2*N;i++) - st->window[i] = 0; - for (i=0;ioverlap;i++) - st->window[N4+i] = st->window[2*N-N4-i-1] - = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/st->overlap) * sin(.5*M_PI*(i+.5)/st->overlap)); - for (i=0;i<2*N4;i++) - st->window[N-N4+i] = Q15ONE; st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t)); @@ -530,9 +504,7 @@ void celt_decoder_destroy(CELTDecoder *st) if (check_mode(st->mode) != CELT_OK) return; - mdct_clear(&st->mdct_lookup); - celt_free(st->window); celt_free(st->mdct_overlap); celt_free(st->out_mem); @@ -559,11 +531,11 @@ static void celt_decode_lost(CELTDecoder *st, short *pcm) pitch_index = st->last_pitch_index; /* Use the pitch MDCT as the "guessed" signal */ - compute_mdcts(&st->mdct_lookup, st->window, st->out_mem+pitch_index*C, freq, N, B, C); + compute_mdcts(&st->mode->mdct, st->mode->window, st->out_mem+pitch_index*C, freq, N, B, C); CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N)); /* Compute inverse MDCTs */ - compute_inv_mdcts(&st->mdct_lookup, st->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); + compute_inv_mdcts(&st->mode->mdct, st->mode->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); for (c=0;cmdct_lookup, st->window, st->out_mem+pitch_index*C, freq, N, B, C); + compute_mdcts(&st->mode->mdct, st->mode->window, st->out_mem+pitch_index*C, freq, N, B, C); { VARDECL(celt_ener_t *bandEp); @@ -670,7 +642,7 @@ int celt_decode(CELTDecoder *st, unsigned char *data, int len, celt_int16_t *pcm CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N)); /* Compute inverse MDCTs */ - compute_inv_mdcts(&st->mdct_lookup, st->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); + compute_inv_mdcts(&st->mode->mdct, st->mode->window, freq, st->out_mem, st->mdct_overlap, N, st->overlap, B, C); for (c=0;ctrig); } -void mdct_forward(mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out) +void mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out) { int i; int N, N2, N4; @@ -132,7 +132,7 @@ void mdct_forward(mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out) } -void mdct_backward(mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out) +void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out) { int i; int N, N2, N4, N8; diff --git a/libcelt/mdct.h b/libcelt/mdct.h index 6d1e0d64..1fc90c5a 100644 --- a/libcelt/mdct.h +++ b/libcelt/mdct.h @@ -42,6 +42,9 @@ and scaling in many places. */ +#ifndef MDCT_H +#define MDCT_H + #include "kiss_fft.h" typedef struct { @@ -54,8 +57,9 @@ void mdct_init(mdct_lookup *l,int N); void mdct_clear(mdct_lookup *l); /** Compute a forward MDCT and scale by 2/N */ -void mdct_forward(mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out); +void mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out); /** Compute a backward MDCT (no scaling) */ -void mdct_backward(mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out); +void mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out); +#endif diff --git a/libcelt/modes.c b/libcelt/modes.c index 924e2600..22b6968e 100644 --- a/libcelt/modes.c +++ b/libcelt/modes.c @@ -212,6 +212,7 @@ static void compute_allocation_table(CELTMode *mode, int res) CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int lookahead, int *error) { int res; + int N, N2, N4, i; CELTMode *mode; /* The good thing here is that permutation of the arguments will automatically be invalid */ @@ -259,6 +260,22 @@ CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int lookahead, compute_allocation_table(mode, res); compute_alloc_cache(mode); /*printf ("%d bands\n", mode->nbEBands);*/ + + N = mode->mdctSize; + N2 = N/2; + N4 = N/4; + mdct_init(&mode->mdct, 2*N); + + mode->window = (celt_word16_t*)celt_alloc(2*N*sizeof(celt_word16_t)); + + for (i=0;i<2*N;i++) + mode->window[i] = 0; + for (i=0;ioverlap;i++) + mode->window[N4+i] = mode->window[2*N-N4-i-1] + = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)); + for (i=0;i<2*N4;i++) + mode->window[N-N4+i] = Q15ONE; + mode->marker_start = MODEVALID; mode->marker_end = MODEVALID; return mode; @@ -283,6 +300,9 @@ void celt_mode_destroy(CELTMode *mode) } } celt_free((int**)mode->bits); + mdct_clear(&mode->mdct); + celt_free(mode->window); + mode->marker_start = MODEFREED; mode->marker_end = MODEFREED; celt_free((CELTMode *)mode); diff --git a/libcelt/modes.h b/libcelt/modes.h index 645fb5f8..2725e8da 100644 --- a/libcelt/modes.h +++ b/libcelt/modes.h @@ -35,6 +35,7 @@ #include "celt_types.h" #include "celt.h" #include "arch.h" +#include "mdct.h" /** Mode definition (opaque) @brief Mode definition @@ -61,6 +62,12 @@ struct CELTMode { const int * const *bits; /**< Cache for pulses->bits mapping in each band */ celt_uint32_t marker_end; + + /* Stuff that could go in the {en,de}coder, but we save space this way */ + mdct_lookup mdct; + + celt_word16_t *window; + }; int check_mode(const CELTMode *mode);