diff --git a/libcelt/celt.c b/libcelt/celt.c index ab12f0ec372e7e967919393095848a4eb8da58ed..d8a12a3c58614dcb97deed1220e210dc8ea926dd 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -183,7 +183,7 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error) st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig)); st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig)); - st->pitch_buf = celt_alloc((MAX_PERIOD>>1)*sizeof(celt_word16)); + st->pitch_buf = celt_alloc(((MAX_PERIOD>>1)+2)*sizeof(celt_word16)); st->oldBandE = (celt_word16*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16)); @@ -644,8 +644,11 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig && norm_rate < 50; if (has_pitch) { - /*find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C);*/ - find_temporal_pitch(st->mode, in, st->pitch_buf, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C, &st->xmem); + /* FIXME: Should probably do a stack save/pop here */ + VARDECL(celt_word16, x_lp); + ALLOC(x_lp, (2*N-2*N4)>>1, celt_word16); + pitch_downsample(in, x_lp, 2*N-2*N4, N, C, &st->xmem, &st->pitch_buf[MAX_PERIOD>>1]); + pitch_search(st->mode, x_lp, st->pitch_buf, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, &st->xmem); } /* Deferred allocation after find_spectral_pitch() to reduce @@ -1236,12 +1239,12 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p { celt_word16 pitch_buf[MAX_PERIOD>>1]; celt_word32 tmp=0; + celt_word32 mem0[2]={0,0}; + celt_word16 mem1[2]={0,0}; /*find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index, C);*/ /* FIXME: Should do a bit of interpolation while decimating */ - for (i=0;i<MAX_PERIOD>>1;i++) - pitch_buf[i] = EXTRACT16(SHR32(st->out_mem[2*i], SIG_SHIFT)); - find_temporal_pitch(st->mode, st->out_mem+MAX_PERIOD-len, pitch_buf, len, MAX_PERIOD-len-100, &pitch_index, C, &tmp); - + pitch_downsample(st->out_mem, pitch_buf, MAX_PERIOD, MAX_PERIOD, C, mem0, mem1); + pitch_search(st->mode, pitch_buf+((MAX_PERIOD-len)>>1), pitch_buf, len, MAX_PERIOD-len-100, &pitch_index, &tmp); pitch_index = MAX_PERIOD-len-pitch_index; st->last_pitch_index = pitch_index; } else { diff --git a/libcelt/pitch.c b/libcelt/pitch.c index 6558bd4c780adcdb1a41c94b7d4c1af4105b4ba0..ccbac34293b204889a12e60756462cc9f827d3ee 100644 --- a/libcelt/pitch.c +++ b/libcelt/pitch.c @@ -98,14 +98,58 @@ void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 *y, in } } -void find_temporal_pitch(const CELTMode *m, const celt_sig * restrict x, celt_word16 * restrict y, int len, int max_pitch, int *pitch, int _C, celt_sig *xmem) +void pitch_downsample(const celt_sig * restrict x, celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem) { - int i, j; + int i; const int C = CHANNELS(_C); + for (i=1;i<len>>1;i++) + x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C]+x[(2*i+1)*C])+x[2*i*C]), SIG_SHIFT); + x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[C])+x[0]), SIG_SHIFT); + *xmem = x[end-C]; + if (C==2) + { + for (i=1;i<len>>1;i++) + x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C+1]+x[(2*i+1)*C+1])+x[2*i*C+1]), SIG_SHIFT); + x_lp[0] += SHR32(HALF32(HALF32(x[C+1])+x[1]), SIG_SHIFT); + *xmem += x[end-C+1]; + } + +#if 0 + { + int j; + float ac[3]={0,0,0}; + float ak[2]; + float det; + for (i=0;i<3;i++) + { + for (j=0;j<(len>>1)-i;j++) + { + ac[i] += x_lp[j]*x_lp[j+i]; + } + } + det = 1./(.1+ac[0]*ac[0]-ac[1]*ac[1]); + ak[0] = det*(ac[0]*ac[1] - ac[1]*ac[2]); + ak[1] = det*(-ac[1]*ac[1] + ac[0]*ac[2]); + /*printf ("%f %f %f\n", 1., -ak[0], -ak[1]);*/ + float mem[2]; + for (j=0;j<len>>1;j++) + { + float tmp = x_lp[j]; + x_lp[j] = x_lp[j] - ak[0]*filt_mem[0] - ak[1]*filt_mem[1]; + filt_mem[1]=mem[0]; + filt_mem[0]=tmp; + } + } +#endif + +} + +void pitch_search(const CELTMode *m, const celt_word16 * restrict x_lp, celt_word16 * restrict y, int len, int max_pitch, int *pitch, celt_sig *xmem) +{ + int i, j; const int lag = MAX_PERIOD; const int N = FRAMESIZE(m); int best_pitch[2]={0}; - VARDECL(celt_word16, x_lp); VARDECL(celt_word16, x_lp4); VARDECL(celt_word16, y_lp4); VARDECL(celt_word32, xcorr); @@ -115,24 +159,10 @@ void find_temporal_pitch(const CELTMode *m, const celt_sig * restrict x, celt_wo SAVE_STACK; - ALLOC(x_lp, len>>1, celt_word16); ALLOC(x_lp4, len>>2, celt_word16); - ALLOC(y_lp4, len>>2, celt_word16); + ALLOC(y_lp4, lag>>2, celt_word16); ALLOC(xcorr, max_pitch>>1, celt_word32); - /* Down-sample by two and downmix to mono */ - for (i=1;i<len>>1;i++) - x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C]+x[(2*i+1)*C])+x[2*i*C]), SIG_SHIFT); - x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[C])+x[0]), SIG_SHIFT); - *xmem = x[N-C]; - if (C==2) - { - for (i=1;i<len>>1;i++) - x_lp[i] = SHR32(HALF32(HALF32(x[(2*i-1)*C+1]+x[(2*i+1)*C+1])+x[2*i*C+1]), SIG_SHIFT); - x_lp[0] += SHR32(HALF32(HALF32(x[C+1])+x[1]), SIG_SHIFT); - *xmem += x[N-C+1]; - } - /* Downsample by 2 again */ for (j=0;j<len>>2;j++) x_lp4[j] = x_lp[2*j]; @@ -200,7 +230,7 @@ void find_temporal_pitch(const CELTMode *m, const celt_sig * restrict x, celt_wo *pitch = 2*best_pitch[0]-offset; CELT_MOVE(y, y+(N>>1), (lag-N)>>1); - CELT_COPY(y+((lag-N)>>1), x_lp, N>>1); + CELT_MOVE(y+((lag-N)>>1), x_lp, N>>1); RESTORE_STACK; diff --git a/libcelt/pitch.h b/libcelt/pitch.h index 51cc8f358907158ca96ef8fa3112a81beb62b7d5..f6d3683902f69a65c5c1ef909b6be92bb8e5f408 100644 --- a/libcelt/pitch.h +++ b/libcelt/pitch.h @@ -46,11 +46,8 @@ kiss_fftr_cfg pitch_state_alloc(int max_lag); 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 *x, const celt_sig *y, const celt_word16 *window, celt_word16 * restrict X, int len, int max_pitch, int *pitch, int _C); +void pitch_downsample(const celt_sig * restrict x, celt_word16 * restrict x_lp, int len, int end, int _C, celt_sig * restrict xmem, celt_word16 * restrict filt_mem); -void find_temporal_pitch(const CELTMode *m, const celt_sig * restrict x, celt_word16 * restrict y, int len, int max_pitch, int *pitch, int _C, celt_sig *xmem); +void pitch_search(const CELTMode *m, const celt_word16 * restrict x_lp, celt_word16 * restrict y, int len, int max_pitch, int *pitch, celt_sig *xmem); #endif