Fixed a bug in the PLC and added code to estimate the pitch from the synthesis

instead of relying on the one previously transmitted by the encoder.
This commit is contained in:
Jean-Marc Valin 2008-05-02 10:34:07 +10:00
parent a1bb9c707f
commit 24c9cdaca1
6 changed files with 29 additions and 12 deletions

View file

@ -69,8 +69,6 @@ struct CELTEncoder {
celt_word16_t * restrict preemph_memE; /* Input is 16-bit, so why bother with 32 */ celt_word16_t * restrict preemph_memE; /* Input is 16-bit, so why bother with 32 */
celt_sig_t * restrict preemph_memD; celt_sig_t * restrict preemph_memD;
kiss_fftr_cfg fft;
celt_sig_t *in_mem; celt_sig_t *in_mem;
celt_sig_t *out_mem; celt_sig_t *out_mem;
@ -97,8 +95,6 @@ CELTEncoder EXPORT *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);
st->fft = pitch_state_alloc(MAX_PERIOD);
st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t)); st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t)); st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
@ -122,8 +118,6 @@ void EXPORT celt_encoder_destroy(CELTEncoder *st)
ec_byte_writeclear(&st->buf); ec_byte_writeclear(&st->buf);
pitch_state_free(st->fft);
celt_free(st->in_mem); celt_free(st->in_mem);
celt_free(st->out_mem); celt_free(st->out_mem);
@ -257,7 +251,7 @@ int EXPORT celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, u
CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap); CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
/* Pitch analysis: we do it early to save on the peak stack space */ /* Pitch analysis: we do it early to save on the peak stack space */
find_spectral_pitch(st->mode, st->fft, &st->mode->psy, in, st->out_mem, st->mode->window, 2*N-2*N4, &pitch_index); find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */ ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
@ -496,18 +490,35 @@ static void celt_decode_lost(CELTDecoder * restrict st, short * restrict pcm)
{ {
int c, N; int c, N;
int pitch_index; int pitch_index;
int i, len;
VARDECL(celt_sig_t, freq); VARDECL(celt_sig_t, freq);
const int C = CHANNELS(st->mode); const int C = CHANNELS(st->mode);
int offset;
SAVE_STACK; SAVE_STACK;
N = st->block_size; N = st->block_size;
ALLOC(freq,C*N, celt_sig_t); /**< Interleaved signal MDCTs */ ALLOC(freq,C*N, celt_sig_t); /**< Interleaved signal MDCTs */
len = N+st->mode->overlap;
#if 0
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->mode, st->mode->window, st->out_mem+pitch_index*C, freq); compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD-N)); #else
find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, len, MAX_PERIOD-len-100, &pitch_index);
pitch_index = MAX_PERIOD-len-pitch_index;
offset = MAX_PERIOD-pitch_index;
while (offset+len >= MAX_PERIOD)
offset -= pitch_index;
compute_mdcts(st->mode, st->mode->window, st->out_mem+offset*C, freq);
for (i=0;i<N;i++)
freq[i] = MULT16_32_Q15(QCONST16(.9f,15),freq[i]);
#endif
CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->mode->overlap-N));
/* Compute inverse MDCTs */ /* Compute inverse MDCTs */
compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem); compute_inv_mdcts(st->mode, st->mode->window, freq, st->out_mem);

View file

@ -157,6 +157,7 @@ void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
fprintf(file, "allocVectors%d_%d,\t/* allocVectors */\n", mode->Fs, mode->mdctSize); fprintf(file, "allocVectors%d_%d,\t/* allocVectors */\n", mode->Fs, mode->mdctSize);
fprintf(file, "allocCache%d_%d_%d,\t/* bits */\n", mode->Fs, mode->mdctSize, mode->nbChannels); fprintf(file, "allocCache%d_%d_%d,\t/* bits */\n", mode->Fs, mode->mdctSize, mode->nbChannels);
fprintf(file, "{%d, 0, 0},\t/* mdct */\n", 2*mode->mdctSize); fprintf(file, "{%d, 0, 0},\t/* mdct */\n", 2*mode->mdctSize);
fprintf(file, "0,\t/* fft */\n");
fprintf(file, "window%d,\t/* window */\n", mode->overlap); fprintf(file, "window%d,\t/* window */\n", mode->overlap);
fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs); fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs);
fprintf(file, "0,\t/* prob */\n"); fprintf(file, "0,\t/* prob */\n");

View file

@ -339,6 +339,8 @@ CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size,
mode->marker_end = MODEVALID; mode->marker_end = MODEVALID;
#endif /* !STATIC_MODES */ #endif /* !STATIC_MODES */
mdct_init(&mode->mdct, 2*mode->mdctSize); mdct_init(&mode->mdct, 2*mode->mdctSize);
mode->fft = pitch_state_alloc(MAX_PERIOD);
mode->prob = quant_prob_alloc(mode); mode->prob = quant_prob_alloc(mode);
if (error) if (error)
*error = CELT_OK; *error = CELT_OK;
@ -374,6 +376,7 @@ void EXPORT celt_mode_destroy(CELTMode *mode)
#endif #endif
#endif #endif
mdct_clear(&mode->mdct); mdct_clear(&mode->mdct);
pitch_state_free(mode->fft);
quant_prob_free(mode->prob); quant_prob_free(mode->prob);
celt_free((CELTMode *)mode); celt_free((CELTMode *)mode);
} }

View file

@ -37,6 +37,7 @@
#include "arch.h" #include "arch.h"
#include "mdct.h" #include "mdct.h"
#include "psy.h" #include "psy.h"
#include "pitch.h"
#ifdef STATIC_MODES #ifdef STATIC_MODES
#include "static_modes.h" #include "static_modes.h"
@ -88,6 +89,7 @@ struct CELTMode {
/* Stuff that could go in the {en,de}coder, but we save space this way */ /* Stuff that could go in the {en,de}coder, but we save space this way */
mdct_lookup mdct; mdct_lookup mdct;
kiss_fftr_cfg fft;
const celt_word16_t *window; const celt_word16_t *window;

View file

@ -104,7 +104,7 @@ static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
#define INPUT_SHIFT 15 #define INPUT_SHIFT 15
void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, int len, int *pitch) void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, int len, int max_pitch, int *pitch)
{ {
int c, i; int c, i;
VARDECL(celt_word16_t, _X); VARDECL(celt_word16_t, _X);
@ -224,6 +224,6 @@ void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyD
real16_ifft(fft, X, Y, lag); real16_ifft(fft, X, Y, lag);
/* The peak in the correlation gives us the pitch */ /* The peak in the correlation gives us the pitch */
*pitch = find_max16(Y, lag-len); *pitch = find_max16(Y, max_pitch);
RESTORE_STACK; RESTORE_STACK;
} }

View file

@ -48,6 +48,6 @@ void pitch_state_free(kiss_fftr_cfg st);
/** Find the optimal delay for the pitch prediction. Computation is /** Find the optimal delay for the pitch prediction. Computation is
done in the frequency domain, both to save time and to make it done in the frequency domain, both to save time and to make it
easier to apply psychoacoustic weighting */ easier to apply psychoacoustic weighting */
void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, int len, int *pitch); void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, int len, int max_pitch, int *pitch);
#endif #endif