Moved mdct state and window to the mode so it can be shared between multiple

encoders and decoders.
This commit is contained in:
Jean-Marc Valin 2008-02-29 21:08:49 +11:00
parent 37131e3ab3
commit 81b38c2295
5 changed files with 50 additions and 47 deletions

View file

@ -73,11 +73,9 @@ struct CELTEncoder {
celt_sig_t *preemph_memE; celt_sig_t *preemph_memE;
celt_sig_t *preemph_memD; celt_sig_t *preemph_memD;
mdct_lookup mdct_lookup;
kiss_fftr_cfg fft; kiss_fftr_cfg fft;
struct PsyDecay psy; struct PsyDecay psy;
celt_word16_t *window;
celt_sig_t *in_mem; celt_sig_t *in_mem;
celt_sig_t *mdct_overlap; celt_sig_t *mdct_overlap;
celt_sig_t *out_mem; celt_sig_t *out_mem;
@ -110,21 +108,13 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode)
ec_byte_writeinit(&st->buf); ec_byte_writeinit(&st->buf);
ec_enc_init(&st->enc,&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); st->fft = kiss_fftr_alloc(MAX_PERIOD*C, 0, 0);
psydecay_init(&st->psy, MAX_PERIOD*C/2, st->mode->Fs); 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->in_mem = celt_alloc(N*C*sizeof(celt_sig_t));
st->mdct_overlap = 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)); 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;i<st->overlap;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->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
st->preemph = QCONST16(0.8f,15); st->preemph = QCONST16(0.8f,15);
@ -146,11 +136,9 @@ void celt_encoder_destroy(CELTEncoder *st)
ec_byte_writeclear(&st->buf); ec_byte_writeclear(&st->buf);
mdct_clear(&st->mdct_lookup);
kiss_fft_free(st->fft); kiss_fft_free(st->fft);
psydecay_clear(&st->psy); psydecay_clear(&st->psy);
celt_free(st->window);
celt_free(st->in_mem); celt_free(st->in_mem);
celt_free(st->mdct_overlap); celt_free(st->mdct_overlap);
celt_free(st->out_mem); 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 */ /** 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; int i, c;
celt_word32_t E = 0; 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 */ /** 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; int i, c, N4;
VARDECL(celt_word32_t *x); 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");*/ /*for (i=0;i<(B+1)*C*N;i++) printf ("%f(%d) ", in[i], i); printf ("\n");*/
/* Compute MDCTs */ /* 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 */ #if 0 /* Mask disabled until it can be made to do something useful */
compute_mdct_masking(X, mask, B*C*N, st->Fs); 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;i<N;i++) for (i=0;i<N;i++)
{ {
in[C*i+c] = MULT16_32_Q15(st->window[i], in[C*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->window[N+i], in[C*(B*N+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); 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;i<N*B*C;i++)printf("%f ", X[i]);printf("\n");*/ /*for (i=0;i<N*B*C;i++)printf("%f ", X[i]);printf("\n");*/
/* Compute MDCTs of the pitch part */ /* Compute MDCTs of the pitch part */
pitch_power = compute_mdcts(&st->mdct_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); 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)); 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 */ /* De-emphasis and put everything back at the right place in the synthesis history */
for (c=0;c<C;c++) for (c=0;c<C;c++)
{ {
@ -465,9 +453,6 @@ struct CELTDecoder {
celt_word16_t preemph; celt_word16_t preemph;
celt_sig_t *preemph_memD; celt_sig_t *preemph_memD;
mdct_lookup mdct_lookup;
celt_word16_t *window;
celt_sig_t *mdct_overlap; celt_sig_t *mdct_overlap;
celt_sig_t *out_mem; celt_sig_t *out_mem;
@ -497,20 +482,9 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode)
N4 = (N-st->overlap)/2; N4 = (N-st->overlap)/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->mdct_overlap = celt_alloc(N*C*sizeof(celt_sig_t));
st->out_mem = celt_alloc(MAX_PERIOD*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;i<st->overlap;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->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
st->preemph = QCONST16(0.8f,15); st->preemph = QCONST16(0.8f,15);
@ -530,9 +504,7 @@ void celt_decoder_destroy(CELTDecoder *st)
if (check_mode(st->mode) != CELT_OK) if (check_mode(st->mode) != CELT_OK)
return; return;
mdct_clear(&st->mdct_lookup);
celt_free(st->window);
celt_free(st->mdct_overlap); celt_free(st->mdct_overlap);
celt_free(st->out_mem); celt_free(st->out_mem);
@ -559,11 +531,11 @@ static void celt_decode_lost(CELTDecoder *st, short *pcm)
pitch_index = st->last_pitch_index; pitch_index = st->last_pitch_index;
/* Use the pitch MDCT as the "guessed" signal */ /* 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)); CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N));
/* Compute inverse MDCTs */ /* 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;c<C;c++) for (c=0;c<C;c++)
{ {
@ -641,7 +613,7 @@ int celt_decode(CELTDecoder *st, unsigned char *data, int len, celt_int16_t *pcm
} }
/* Pitch MDCT */ /* Pitch MDCT */
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);
{ {
VARDECL(celt_ener_t *bandEp); 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)); CELT_MOVE(st->out_mem, st->out_mem+C*B*N, C*(MAX_PERIOD-B*N));
/* Compute inverse MDCTs */ /* 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;c<C;c++) for (c=0;c<C;c++)
{ {

View file

@ -87,7 +87,7 @@ void mdct_clear(mdct_lookup *l)
celt_free(l->trig); celt_free(l->trig);
} }
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 i;
int N, N2, N4; 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 i;
int N, N2, N4, N8; int N, N2, N4, N8;

View file

@ -42,6 +42,9 @@
and scaling in many places. and scaling in many places.
*/ */
#ifndef MDCT_H
#define MDCT_H
#include "kiss_fft.h" #include "kiss_fft.h"
typedef struct { typedef struct {
@ -54,8 +57,9 @@ void mdct_init(mdct_lookup *l,int N);
void mdct_clear(mdct_lookup *l); void mdct_clear(mdct_lookup *l);
/** Compute a forward MDCT and scale by 2/N */ /** 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) */ /** 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

View file

@ -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) CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int lookahead, int *error)
{ {
int res; int res;
int N, N2, N4, i;
CELTMode *mode; CELTMode *mode;
/* The good thing here is that permutation of the arguments will automatically be invalid */ /* 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_allocation_table(mode, res);
compute_alloc_cache(mode); compute_alloc_cache(mode);
/*printf ("%d bands\n", mode->nbEBands);*/ /*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;i<mode->overlap;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_start = MODEVALID;
mode->marker_end = MODEVALID; mode->marker_end = MODEVALID;
return mode; return mode;
@ -283,6 +300,9 @@ void celt_mode_destroy(CELTMode *mode)
} }
} }
celt_free((int**)mode->bits); celt_free((int**)mode->bits);
mdct_clear(&mode->mdct);
celt_free(mode->window);
mode->marker_start = MODEFREED; mode->marker_start = MODEFREED;
mode->marker_end = MODEFREED; mode->marker_end = MODEFREED;
celt_free((CELTMode *)mode); celt_free((CELTMode *)mode);

View file

@ -35,6 +35,7 @@
#include "celt_types.h" #include "celt_types.h"
#include "celt.h" #include "celt.h"
#include "arch.h" #include "arch.h"
#include "mdct.h"
/** Mode definition (opaque) /** Mode definition (opaque)
@brief Mode definition @brief Mode definition
@ -61,6 +62,12 @@ struct CELTMode {
const int * const *bits; /**< Cache for pulses->bits mapping in each band */ const int * const *bits; /**< Cache for pulses->bits mapping in each band */
celt_uint32_t marker_end; 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); int check_mode(const CELTMode *mode);