mirror of
https://github.com/xiph/opus.git
synced 2025-06-07 16:00:56 +00:00
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:
parent
a1bb9c707f
commit
24c9cdaca1
6 changed files with 29 additions and 12 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue