Moved mdct state and window to the mode so it can be shared between multiple
encoders and decoders.
This commit is contained in:
parent
37131e3ab3
commit
81b38c2295
5 changed files with 50 additions and 47 deletions
|
@ -72,12 +72,10 @@ struct CELTEncoder {
|
||||||
celt_word16_t preemph;
|
celt_word16_t preemph;
|
||||||
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++)
|
||||||
{
|
{
|
||||||
|
@ -464,10 +452,7 @@ 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,19 +482,8 @@ 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));
|
||||||
|
|
||||||
|
@ -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++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue