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_sig_t * restrict preemph_memD;
kiss_fftr_cfg fft;
celt_sig_t *in_mem;
celt_sig_t *out_mem;
@ -97,8 +95,6 @@ CELTEncoder EXPORT *celt_encoder_create(const CELTMode *mode)
ec_byte_writeinit(&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->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);
pitch_state_free(st->fft);
celt_free(st->in_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);
/* 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 */
@ -496,18 +490,35 @@ static void celt_decode_lost(CELTDecoder * restrict st, short * restrict pcm)
{
int c, N;
int pitch_index;
int i, len;
VARDECL(celt_sig_t, freq);
const int C = CHANNELS(st->mode);
int offset;
SAVE_STACK;
N = st->block_size;
ALLOC(freq,C*N, celt_sig_t); /**< Interleaved signal MDCTs */
len = N+st->mode->overlap;
#if 0
pitch_index = st->last_pitch_index;
/* Use the pitch MDCT as the "guessed" signal */
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_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, "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, "0,\t/* fft */\n");
fprintf(file, "window%d,\t/* window */\n", mode->overlap);
fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs);
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;
#endif /* !STATIC_MODES */
mdct_init(&mode->mdct, 2*mode->mdctSize);
mode->fft = pitch_state_alloc(MAX_PERIOD);
mode->prob = quant_prob_alloc(mode);
if (error)
*error = CELT_OK;
@ -374,6 +376,7 @@ void EXPORT celt_mode_destroy(CELTMode *mode)
#endif
#endif
mdct_clear(&mode->mdct);
pitch_state_free(mode->fft);
quant_prob_free(mode->prob);
celt_free((CELTMode *)mode);
}

View file

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

View file

@ -104,7 +104,7 @@ static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
#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;
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);
/* The peak in the correlation gives us the pitch */
*pitch = find_max16(Y, lag-len);
*pitch = find_max16(Y, max_pitch);
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
done in the frequency domain, both to save time and to make it
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