diff --git a/configure.ac b/configure.ac index fdad7bbb..8037120a 100644 --- a/configure.ac +++ b/configure.ac @@ -117,6 +117,13 @@ AC_ARG_ENABLE(fixed-point-debug, [ --enable-fixed-point-debug debug fixed-poin AC_DEFINE([FIXED_DEBUG], , [Debug fixed-point implementation]) fi]) +ac_enable_experimental_postfilter="no" +AC_ARG_ENABLE(experimental-postfilter, [ --enable-experimental-postfilter Enable this for testing only if you know what you're doing ], +[if test "$enableval" = yes; then + ac_enable_experimental_postfilter="yes" + AC_DEFINE([ENABLE_POSTFILTER], , [Postfilter]) +fi]) + float_approx=$has_float_approx AC_ARG_ENABLE(float-approx, [ --enable-float-approx enable fast approximations for floating point], [ if test "$enableval" = yes; then diff --git a/libcelt/celt.c b/libcelt/celt.c index 33ef5ddb..091386c2 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -54,6 +54,8 @@ #include "plc.h" static const int trim_cdf[7] = {0, 4, 10, 23, 119, 125, 128}; +#define COMBFILTER_MAXPERIOD 1024 +#define COMBFILTER_MINPERIOD 16 /** Encoder state @brief Encoder state @@ -77,6 +79,9 @@ struct CELTEncoder { int delayedIntra; int tonal_average; + int prefilter_period; + celt_word16 prefilter_gain; + /* VBR-related parameters */ celt_int32 vbr_reservoir; celt_int32 vbr_drift; @@ -86,7 +91,12 @@ struct CELTEncoder { celt_word32 preemph_memE[2]; celt_word32 preemph_memD[2]; +#ifdef RESYNTH + celt_sig syn_mem[2][2*MAX_PERIOD]; +#endif + celt_sig in_mem[1]; /* Size = channels*mode->overlap */ + /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */ /* celt_sig overlap_mem[], Size = channels*mode->overlap */ /* celt_word16 oldEBands[], Size = channels*mode->nbEBands */ }; @@ -95,6 +105,7 @@ int celt_encoder_get_size(const CELTMode *mode, int channels) { int size = sizeof(struct CELTEncoder) + (2*channels*mode->overlap-1)*sizeof(celt_sig) + + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) + channels*mode->nbEBands*sizeof(celt_word16); return size; } @@ -353,6 +364,46 @@ static void deemphasis(celt_sig *in[], celt_word16 *pcm, int N, int _C, const ce } } +#ifdef ENABLE_POSTFILTER +/* FIXME: Handle the case where T = maxperiod */ +static void comb_filter(celt_word32 *y, celt_word32 *x, int T0, int T1, int N, + int C, celt_word16 g0, celt_word16 g1, const celt_word16 *window, int overlap) +{ + int i; + /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ + celt_word16 g00, g01, g02, g10, g11, g12; + celt_word16 t0, t1, t2; + /* zeros at theta = +/- 5*pi/6 */ + t0 = QCONST16(.26795f, 15); + t1 = QCONST16(.46410f, 15); + t2 = QCONST16(.26795f, 15); + g00 = MULT16_16_Q15(g0, t0); + g01 = MULT16_16_Q15(g0, t1); + g02 = MULT16_16_Q15(g0, t2); + g10 = MULT16_16_Q15(g1, t0); + g11 = MULT16_16_Q15(g1, t1); + g12 = MULT16_16_Q15(g1, t2); + for (i=0;iin_mem+C*(st->overlap); - oldBandE = (celt_word16*)(st->in_mem+2*C*(st->overlap)); + prefilter_mem = st->in_mem+C*(st->overlap); + _overlap_mem = prefilter_mem+C*COMBFILTER_MAXPERIOD; + /*_overlap_mem = st->in_mem+C*(st->overlap);*/ + oldBandE = (celt_word16*)(st->in_mem+C*(2*st->overlap+COMBFILTER_MAXPERIOD)); if (enc==NULL) { @@ -669,25 +725,112 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c N = M*st->mode->shortMdctSize; ALLOC(in, C*(N+st->overlap), celt_sig); - for (c=0;coverlap)+st->overlap; - CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap); - for (i=0;imode->preemph[2], SCALEIN(*pcmp)); - *inp = tmp + st->preemph_memE[c]; - st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp) - - MULT16_32_Q15(st->mode->preemph[0], tmp); - inp++; - pcmp+=C; + const celt_word16 * restrict pcmp = pcm+c; + celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap; + + for (i=0;imode->preemph[2], SCALEIN(*pcmp)); + *inp = tmp + st->preemph_memE[c]; + st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp) + - MULT16_32_Q15(st->mode->preemph[0], tmp); + inp++; + pcmp+=C; + } + CELT_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); + CELT_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N); } - CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); + +#ifdef ENABLE_POSTFILTER + { + VARDECL(celt_word16, pitch_buf); + ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, celt_word16); + celt_word32 tmp=0; + celt_word32 mem0[2]={0,0}; + celt_word16 mem1[2]={0,0}; + + pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD+N, + C, mem0, mem1); + pitch_search(st->mode, pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, + COMBFILTER_MAXPERIOD-COMBFILTER_MINPERIOD, &pitch_index, &tmp, 1<prefilter_period, st->prefilter_gain); + } + if (pitch_index > COMBFILTER_MAXPERIOD) + pitch_index = COMBFILTER_MAXPERIOD; + gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); + if (gain1 > QCONST16(.6f,15)) + gain1 = QCONST16(.6f,15); + if (ABS16(gain1-st->prefilter_gain)prefilter_gain; + if (gain1>12)-2; +#else + qg = floor(.5+gain1*8)-2; +#endif + ec_enc_bit_prob(enc, 1, 32768); + octave = EC_ILOG(pitch_index)-5; + ec_enc_uint(enc, octave, 6); + ec_enc_bits(enc, pitch_index-(16<overlap), st->in_mem+c*(st->overlap), st->overlap); +#ifdef ENABLE_POSTFILTER + comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD, + st->prefilter_period, pitch_index, N, C, -st->prefilter_gain, -gain1, st->mode->window, st->mode->overlap); +#endif /* ENABLE_POSTFILTER */ + CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); + +#ifdef ENABLE_POSTFILTER + if (N>COMBFILTER_MAXPERIOD) + { + CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); + } else { + CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); + CELT_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); + } +#endif /* ENABLE_POSTFILTER */ + } + + RESTORE_STACK; } - resynth = optional_resynthesis!=NULL; +#ifdef RESYNTH + resynth = 1; +#else + resynth = 0; +#endif if (st->complexity > 1 && LM>0) { @@ -881,10 +1024,10 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c quant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(enc, 0), enc, C); +#ifdef RESYNTH /* Re-synthesis of the coded audio if required */ if (resynth) { - VARDECL(celt_sig, _out_mem); celt_sig *out_mem[2]; celt_sig *overlap_mem[2]; @@ -897,6 +1040,10 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c /* Synthesis */ denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M); + CELT_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD); + if (C==2) + CELT_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD); + for (c=0;cmode->eBands[st->start];i++) freq[c*N+i] = 0; @@ -904,23 +1051,31 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c for (i=M*st->mode->eBands[st->end];isyn_mem[0]+MAX_PERIOD; + if (C==2) + out_mem[1] = st->syn_mem[1]+MAX_PERIOD; for (c=0;coverlap; - out_mem[c] = _out_mem+c*N; - } compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, C, LM); - /* De-emphasis and put everything back at the right place - in the synthesis history */ - if (optional_resynthesis != NULL) { - deemphasis(out_mem, optional_resynthesis, N, C, st->mode->preemph, st->preemph_memD); - +#ifdef ENABLE_POSTFILTER + for (c=0;cprefilter_period, st->prefilter_period, st->overlap, C, + st->prefilter_gain, st->prefilter_gain, NULL, 0); + comb_filter(out_mem[c]+st->overlap, out_mem[c]+st->overlap, st->prefilter_period, pitch_index, N-st->overlap, C, + st->prefilter_gain, gain1, st->mode->window, st->mode->overlap); } +#endif /* ENABLE_POSTFILTER */ + + deemphasis(out_mem, (celt_word16*)pcm, N, C, st->mode->preemph, st->preemph_memD); } +#endif + + st->prefilter_period = pitch_index; + st->prefilter_gain = gain1; /* If there's any room left (can only happen for very high rates), fill it with zeros */ @@ -937,7 +1092,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c #ifdef FIXED_POINT #ifndef DISABLE_FLOAT_API -int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) +int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) { int j, ret, C, N, LM, M; VARDECL(celt_int16, in); @@ -960,20 +1115,18 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, floa for (j=0;jpostfilter_period, st->postfilter_period, st->overlap, C, + st->postfilter_gain, st->postfilter_gain, NULL, 0); +#endif /* ENABLE_POSTFILTER */ + for (i=0;imode->overlap-N;i++) out_mem[c][i] = out_mem[c][N+i]; @@ -1372,6 +1518,14 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p } for (i=0;ipostfilter_period, st->postfilter_period, st->overlap, C, + -st->postfilter_gain, -st->postfilter_gain, NULL, 0); +#endif /* ENABLE_POSTFILTER */ + for (i=0;imode, shortBlocks, freq, out_syn, overlap_mem, C, LM); +#ifdef ENABLE_POSTFILTER + for (c=0;cpostfilter_period, st->postfilter_period, st->overlap, C, + st->postfilter_gain, st->postfilter_gain, NULL, 0); + comb_filter(out_syn[c]+st->overlap, out_syn[c]+st->overlap, st->postfilter_period, postfilter_pitch, N-st->overlap, C, + st->postfilter_gain, postfilter_gain, st->mode->window, st->mode->overlap); + } + st->postfilter_period = postfilter_pitch; + st->postfilter_gain = postfilter_gain; +#endif /* ENABLE_POSTFILTER */ + deemphasis(out_syn, pcm, N, C, st->mode->preemph, st->preemph_memD); st->loss_count = 0; RESTORE_STACK; diff --git a/libcelt/celt.h b/libcelt/celt.h index b747cabe..234f396d 100644 --- a/libcelt/celt.h +++ b/libcelt/celt.h @@ -176,30 +176,6 @@ EXPORT CELTEncoder *celt_encoder_init(CELTEncoder *st, const CELTMode *mode, int */ EXPORT void celt_encoder_destroy(CELTEncoder *st); -/** Encodes a frame of audio. - @param st Encoder state - @param pcm PCM audio in float format, with a normal range of ±1.0. - * Samples with a range beyond ±1.0 are supported but will - * be clipped by decoders using the integer API and should - * only be used if it is known that the far end supports - * extended dynmaic range. There must be exactly - * frame_size samples per channel. - @param optional_resynthesis If not NULL, the encoder copies the audio signal that - * the decoder would decode. It is the same as calling the - * decoder on the compressed data, just faster. - * This may alias pcm. - @param compressed The compressed data is written here. This may not alias pcm or - * optional_synthesis. - @param nbCompressedBytes Maximum number of bytes to use for compressing the frame - * (can change from one frame to another) - @return Number of bytes written to "compressed". Will be the same as - * "nbCompressedBytes" unless the stream is VBR and will never be larger. - * If negative, an error has occurred (see error codes). It is IMPORTANT that - * the length returned be somehow transmitted to the decoder. Otherwise, no - * decoding is possible. -*/ -EXPORT int celt_encode_resynthesis_float(CELTEncoder *st, const float *pcm, float *optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes); - /** Encodes a frame of audio. @param st Encoder state @param pcm PCM audio in float format, with a normal range of ±1.0. @@ -220,26 +196,6 @@ EXPORT int celt_encode_resynthesis_float(CELTEncoder *st, const float *pcm, floa */ EXPORT int celt_encode_float(CELTEncoder *st, const float *pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes); -/** Encodes a frame of audio. - @param st Encoder state - @param pcm PCM audio in signed 16-bit format (native endian). There must be - * exactly frame_size samples per channel. - @param optional_resynthesis If not NULL, the encoder copies the audio signal that - * the decoder would decode. It is the same as calling the - * decoder on the compressed data, just faster. - * This may alias pcm. - @param compressed The compressed data is written here. This may not alias pcm or - * optional_synthesis. - @param nbCompressedBytes Maximum number of bytes to use for compressing the frame - * (can change from one frame to another) - @return Number of bytes written to "compressed". Will be the same as - * "nbCompressedBytes" unless the stream is VBR and will never be larger. - * If negative, an error has occurred (see error codes). It is IMPORTANT that - * the length returned be somehow transmitted to the decoder. Otherwise, no - * decoding is possible. - */ -EXPORT int celt_encode_resynthesis(CELTEncoder *st, const celt_int16 *pcm, celt_int16 *optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes); - /** Encodes a frame of audio. @param st Encoder state @param pcm PCM audio in signed 16-bit format (native endian). There must be diff --git a/libcelt/entenc.c b/libcelt/entenc.c index e395f331..8b1e1e3a 100644 --- a/libcelt/entenc.c +++ b/libcelt/entenc.c @@ -45,7 +45,15 @@ void ec_byte_writeinit_buffer(ec_byte_buffer *_b, unsigned char *_buf, ec_uint32 } void ec_byte_shrink(ec_byte_buffer *_b, ec_uint32 _size){ - _b->end_ptr=_b->buf+_size-1; + int i; + int d; + int N; + d = _b->storage-_size; + N = _b->storage-(_b->end_ptr-_b->buf)-1; + /* Copy "raw bytes" */ + _b->end_ptr=_b->buf+_size-1-N; + for (i=0;iend_ptr[i+1] = _b->end_ptr[i+1+d]; _b->storage=_size; } diff --git a/libcelt/mathops.c b/libcelt/mathops.c index 3857a9b4..1dca1016 100644 --- a/libcelt/mathops.c +++ b/libcelt/mathops.c @@ -74,15 +74,15 @@ celt_word32 frac_div32(celt_word32 a, celt_word32 b) { celt_word16 rcp; celt_word32 result, rem; - int shift = 30-celt_ilog2(b); + int shift = 29-celt_ilog2(b); a = SHL32(a,shift); b = SHL32(b,shift); /* 16-bit reciprocal */ - rcp = ROUND16(celt_rcp(ROUND16(b,16)),2); - result = SHL32(MULT16_32_Q15(rcp, a),1); + rcp = ROUND16(celt_rcp(ROUND16(b,16)),3); + result = SHL32(MULT16_32_Q15(rcp, a),2); rem = a-MULT32_32_Q31(result, b); - result += SHL32(MULT16_32_Q15(rcp, rem),1); + result += SHL32(MULT16_32_Q15(rcp, rem),2); return result; } diff --git a/libcelt/modes.c b/libcelt/modes.c index 212102e7..f6bfde2d 100644 --- a/libcelt/modes.c +++ b/libcelt/modes.c @@ -53,8 +53,8 @@ static const celt_int16 eband5ms[] = { static const unsigned char band_allocation[] = { /*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 80, 75, 70, 65, 60, 55, 50, 44, 40, 35, 30, 15, 1, 0, 0, 0, 0, 0, 0, 0, - 90, 85, 85, 85, 85, 82, 78, 74, 70, 65, 60, 54, 45, 35, 25, 15, 1, 0, 0, 0, 0, + 95, 90, 80, 75, 65, 60, 55, 50, 44, 40, 35, 30, 15, 1, 0, 0, 0, 0, 0, 0, 0, +100, 95, 90, 88, 85, 82, 78, 74, 70, 65, 60, 54, 45, 35, 25, 15, 1, 0, 0, 0, 0, 120,110,110,110,100, 96, 90, 88, 84, 76, 70, 65, 60, 45, 35, 25, 20, 1, 1, 0, 0, 135,125,125,125,115,112,104,104,100, 96, 83, 78, 70, 55, 46, 36, 32, 28, 20, 8, 0, 170,165,157,155,149,145,143,138,138,138,129,124,108, 96, 88, 83, 72, 56, 44, 28, 2, diff --git a/libcelt/modes.h b/libcelt/modes.h index 826ab400..87604360 100644 --- a/libcelt/modes.h +++ b/libcelt/modes.h @@ -104,8 +104,8 @@ struct CELTMode { }; /* Prototypes for _ec versions of the encoder/decoder calls (not public) */ -int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); -int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); +int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); +int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size, ec_dec *dec); int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size, ec_dec *dec); #endif diff --git a/libcelt/pitch.c b/libcelt/pitch.c index 533f9976..bff5c70b 100644 --- a/libcelt/pitch.c +++ b/libcelt/pitch.c @@ -46,7 +46,8 @@ #include "stack_alloc.h" #include "mathops.h" -static void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 *y, int yshift, int len, int max_pitch, int best_pitch[2]) +static void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 *y, + int yshift, int len, int max_pitch, int best_pitch[2]) { int i, j; celt_word32 Syy=1; @@ -96,28 +97,65 @@ static void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 } } +#include "plc.h" void pitch_downsample(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; + celt_word32 ac[5]; + celt_word16 tmp=Q15ONE; + celt_word16 lpc[4], mem[4]={0,0,0,0}; const int C = CHANNELS(_C); for (i=1;i>1;i++) - x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), SIG_SHIFT); - x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[0][1])+x[0][0]), SIG_SHIFT); + x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), SIG_SHIFT+2); + x_lp[0] = SHR32(HALF32(HALF32(*xmem+x[0][1])+x[0][0]), SIG_SHIFT+2); *xmem = x[0][end-1]; if (C==2) { for (i=1;i>1;i++) - x_lp[i] = SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), SIG_SHIFT); - x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), SIG_SHIFT); + x_lp[i] = SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), SIG_SHIFT+2); + x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), SIG_SHIFT+2); *xmem += x[1][end-1]; } + + _celt_autocorr(x_lp, ac, NULL, 0, + 4, len>>1); + + /* Noise floor -40 dB */ +#ifdef FIXED_POINT + ac[0] += SHR32(ac[0],13); +#else + ac[0] *= 1.0001f; +#endif + /* Lag windowing */ + for (i=1;i<=4;i++) + { + /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ +#ifdef FIXED_POINT + ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); +#else + ac[i] -= ac[i]*(.008f*i)*(.008f*i); +#endif + } + + _celt_lpc(lpc, ac, 4); + for (i=0;i<4;i++) + { + tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp); + lpc[i] = MULT16_16_Q15(lpc[i], tmp); + } + fir(x_lp, lpc, x_lp, len>>1, 4, mem); + + mem[0]=0; + lpc[0]=QCONST16(.8,12); + fir(x_lp, lpc, x_lp, len>>1, 1, mem); + } -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 M) +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 M) { int i, j; - const int lag = MAX_PERIOD; - const int N = M*m->shortMdctSize; + int lag; int best_pitch[2]={0}; VARDECL(celt_word16, x_lp4); VARDECL(celt_word16, y_lp4); @@ -128,6 +166,8 @@ void pitch_search(const CELTMode *m, const celt_word16 * restrict x_lp, celt_wor SAVE_STACK; + lag = len+max_pitch; + ALLOC(x_lp4, len>>2, celt_word16); ALLOC(y_lp4, lag>>2, celt_word16); ALLOC(xcorr, max_pitch>>1, celt_word32); @@ -198,10 +238,135 @@ void pitch_search(const CELTMode *m, const celt_word16 * restrict x_lp, celt_wor } *pitch = 2*best_pitch[0]-offset; - CELT_MOVE(y, y+(N>>1), (lag-N)>>1); - CELT_MOVE(y+((lag-N)>>1), x_lp, N>>1); - RESTORE_STACK; - - /*printf ("%d\n", *pitch);*/ } + +#ifdef ENABLE_POSTFILTER +static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2}; +celt_word16 remove_doubling(celt_word16 *x, int maxperiod, int minperiod, + int N, int *_T0, int prev_period, celt_word16 prev_gain) +{ + int k, i, T, T0, k0; + celt_word16 g, g0; + celt_word16 pg; + celt_word32 xy,xx,yy; + celt_word32 xcorr[3]; + celt_word32 best_xy, best_yy; + int offset; + + maxperiod /= 2; + minperiod /= 2; + *_T0 /= 2; + prev_period /= 2; + N /= 2; + x += maxperiod; + if (*_T0>=maxperiod) + *_T0=maxperiod-1; + + T = T0 = *_T0; + xx=xy=yy=0; + for (i=0;i>1; + t = VSHR32(x2y2, 2*(sh-7)); + g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g = g0 = xy/sqrt(1+xx*yy); +#endif + k0 = 1; + /* Look for any pitch at T/k */ + for (k=2;k<=15;k++) + { + int T1, T1b; + celt_word16 g1; + celt_word16 cont=0; + T1 = (2*T0+k)/(2*k); + if (T1 < minperiod) + break; + /* Look for another strong correlation at T1b */ + if (k==2) + { + if (T1+T0>maxperiod) + T1b = T0; + else + T1b = T0+T1; + } else + { + T1b = (2*second_check[k]*T0+k)/(2*k); + } + xy=yy=0; + for (i=0;i>1; + t = VSHR32(x2y2, 2*(sh-7)); + g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g1 = xy/sqrt(1+2.f*xx*1.f*yy); +#endif + if (abs(T1-prev_period)<=1) + cont = prev_gain; + else if (abs(T1-prev_period)<=2 && 5*k*k < T0) + cont = HALF32(prev_gain); + else + cont = 0; + if (g1 > QCONST16(.3f,15) + MULT16_16_Q15(QCONST16(.4f,15),g0)-cont) + { + best_xy = xy; + best_yy = yy; + T = T1; + g = g1; + } + } + if (best_yy <= best_xy) + pg = Q15ONE; + else + pg = SHR32(frac_div32(best_xy,best_yy+1),16); + + for (k=0;k<3;k++) + { + int T1 = T+k-1; + xy = 0; + for (i=0;i MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0])) + offset = 1; + else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2])) + offset = -1; + else + offset = 0; + if (pg > g) + pg = g; + *_T0 = 2*T+offset; + + if (*_T0<2*minperiod) + *_T0=2*minperiod; + return pg; +} + +#endif /* ENABLE_POSTFILTER */ diff --git a/libcelt/pitch.h b/libcelt/pitch.h index 3695a65a..be3e1d48 100644 --- a/libcelt/pitch.h +++ b/libcelt/pitch.h @@ -43,6 +43,10 @@ void pitch_downsample(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 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 M); +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 M); + +celt_word16 remove_doubling(celt_word16 *x, int maxperiod, int minperiod, + int N, int *T0, int prev_period, celt_word16 prev_gain); #endif diff --git a/libcelt/plc.c b/libcelt/plc.c index 2204c02c..5625c679 100644 --- a/libcelt/plc.c +++ b/libcelt/plc.c @@ -166,7 +166,7 @@ void _celt_autocorr( } #ifdef FIXED_POINT { - float ac0=0; + celt_word32 ac0=0; int shift; for(i=0;ieBands[j+1]-m->eBands[j])<>3; /* Tilt of the allocation curve */ for (j=start;jeBands[j+1]-m->eBands[j])*(alloc_trim-3)*(m->nbEBands-j-1) - <<(LM+BITRES)>>5; + trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(2*alloc_trim-7)*(m->nbEBands-j-1) + <<(LM+BITRES)>>6; lo = 0; hi = m->nbAllocVectors - 1; diff --git a/libcelt/testcelt.c b/libcelt/testcelt.c index 9d553638..6bfd0dd2 100644 --- a/libcelt/testcelt.c +++ b/libcelt/testcelt.c @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) err = fread(in, sizeof(short), frame_size*channels, fin); if (feof(fin)) break; - len = celt_encode_resynthesis(enc, in, in, frame_size, data, bytes_per_packet); + len = celt_encode(enc, in, frame_size, data, bytes_per_packet); if (len <= 0) fprintf (stderr, "celt_encode() failed: %s\n", celt_strerror(len)); @@ -194,7 +194,7 @@ int main(int argc, char *argv[]) celt_mode_destroy(mode); free(in); free(out); -#if !(defined (FIXED_POINT) && defined(STATIC_MODES)) +#ifdef RESYNTH if (rmsd > 0) { rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));