From 35095c6991197ca6b6bfa6870eecc10cba4042b7 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Thu, 4 Nov 2010 13:24:44 -0400 Subject: [PATCH] Squashed commit of the following: commit a2cc77cb2744a2cb0551b9bfdf06b97457b6d449 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Thu Nov 4 13:11:21 2010 -0400 Adding a switch to enable the post-filter (off by default) commit 8e860dc0dfbe57e59fcbd5352588c5edff020e27 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Thu Nov 4 11:57:12 2010 -0400 Allowing pitches up to 3000 Hz commit 837412d37bbca32bb34bfb5941e132ff4b0a568c Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Wed Nov 3 20:47:11 2010 -0400 Pitch estimation tuning to prevent some cases of pitch halving commit 34e20f24c85b40fffd1a15c5b632f2f78b26f081 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Nov 3 16:31:51 2010 -0400 Resynthesis now purely a compile-time option with RESYNTH commit d83fb5a9cc2ec4b6cce938662997643da1c5ed0d Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Nov 3 16:28:25 2010 -0400 Fixes a divide by zero in remove_doubling() commit bb91e05b7f8f91fd15a8a0daae3d8cb6bd8d81db Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Nov 3 15:55:48 2010 -0400 Bring back resynthesis with RESYNTH macro commit 31fe6f6b4997af0a46b8c62f523fe2dfdb7f56ae Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Tue Nov 2 17:55:04 2010 -0400 Tuning the allocation tilt to give more bits to higher frequencies. Especially useful now that the post-filter can reduce low freq noise. commit 919ba48f0369a87885334756cdfac2a448ce52d0 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Nov 1 17:27:19 2010 -0400 C89 fix commit ee0dbb1855a82ee8c132ddaffcab4d072bb3455e Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Nov 1 11:45:10 2010 -0400 Complete fixed-point port of the pitch code (I think). commit 4c7b3fd12a8f7469607b5ac57c85301a5de9fa81 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Nov 1 10:55:43 2010 -0400 More fixed-point pitch gain work commit 26f1412188900199b63e187fcb0bd04db53c898a Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Nov 1 10:39:25 2010 -0400 Fixed-point version of the pitch gain calculation code commit 27c73d008e9f50d282c3ad08e2f05f7006013ae1 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Sun Oct 31 16:50:26 2010 -0400 Some more fixed-point work in remove_doubling() commit 59354672cb3af794a0e46c0b2097d6441c75cdd1 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Sun Oct 31 09:57:36 2010 -0400 Fixed a stupid fixed-point pf bug in the gain handling commit be9e7dabf6c8b32bc049da260b58ff6085dc1ac3 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Sat Oct 30 01:52:09 2010 -0400 Fixed-point: fixed frac_div32() that was broken a few commits ago. commit 5b06270afc41a88915252cea14411be43650e704 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 17:45:44 2010 -0400 This fixes VBR when encoding the pitch period with raw bits commit 10e0488458ae558aa80d0b30cce70841ad081f73 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 16:50:31 2010 -0400 Pitch period is now encoder with equal probability for each octave (rather than each lag). Max pitch gain allowed is now 0.625. commit ca19396c1c1511c0e208b400efb51384fc7c200d Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 16:00:01 2010 -0400 More fixed-point post-filter work commit f3e42fde1b575bc587b2557b8b31a6085421a99c Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 14:39:23 2010 -0400 More fixed-point work for the prefilter/postfilter commit db945132d12b25ff25acc0701b91a1d8a81417d5 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 14:14:02 2010 -0400 Making the pitch estimation work in fixed-point Even if there's still lots of float operations left. commit acb3f96e04802ac4601295f83bef1f32593e261a Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Fri Oct 29 10:57:39 2010 -0400 Making the PLC code consistent with the prefilter/postfilter commit 8f64f5974ac846b8c35d0b692e0472f279206cf0 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Thu Oct 28 00:33:53 2010 -0400 More tuning for remove_doubling() commit 0c08f2ee9dcc135dd222fef30f5ad93e95e0d364 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 17:48:02 2010 -0400 Doing an interpolation step to improve the accuracy of the pitch estimate Also increasing the gain slightly. commit 23d303e992f1fdc3d2668652603ae6311d3b91c5 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 16:56:42 2010 -0400 Implements a fixed 3-tap prefilter/postfilter to make the gain roll off with frequency commit 881c5928adc1af9eb75c4b68e9eba94ab1d65adc Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 14:47:30 2010 -0400 Partially whitening the down-sampled signal before the pitch search commit 4a8687deea8587007f14051cb966f6fd748893a1 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 14:27:47 2010 -0400 pitch_search() no longer computes the gain commit a7f85bb6b10d9c509caec521ca444efb3f27df05 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 14:00:53 2010 -0400 remove_doubling() now works on the down-sampled signal commit 06cb70e876873f79fed214ebbca35cb4c5057ec8 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 11:28:53 2010 -0400 Simplification to the pitch continuity code commit 5201927c284a424eb8f21f63d358844b3de8c285 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Wed Oct 27 11:04:02 2010 -0400 Some more pitch doubling prevention code commit 7ef63fbe1f78f79e1923bc42e06fbdf1ec28ffd3 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Wed Oct 27 06:49:28 2010 -0400 Minor fix commit eb37eaab32e7df074a7ddf0ae4781e57f827c4ad Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Tue Oct 26 18:32:25 2010 -0400 Enforcing some pitch continuity commit 751ef6edf2ee7721252cedb264bdf9b3f6244a9d Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Tue Oct 26 17:29:47 2010 -0400 Code for preventing pitch doubling/halving commit c12647ecb55b645005efbeede91880db72936f8d Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Tue Oct 26 00:04:34 2010 -0400 Finally getting perfect reconstruction when pitch changes Post-filter now delays the filter coefs by the overlap so that the pre-filter and post-filter are synchronised. commit f854311d945bb375039a4a4a4fea782b648581f8 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Oct 25 14:59:13 2010 -0400 Very simple/inefficient signalling of the prefilter period/gain commit b4e1215432e3d89a29c998639a6d8b07e28c5a2a Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Oct 25 14:09:17 2010 -0400 using the actual pitch gain commit e7cd4f07bb073b6955a001e56c0bbf16156f4195 Author: Jean-Marc Valin <jean-marc.valin@octasic.com> Date: Mon Oct 25 12:16:11 2010 -0400 Adding some pitch prediction though side information still isn't coded commit 77a03aa27c9b6ed2fe80c27a1196b460ccb5079e Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Mon Oct 25 00:12:48 2010 -0400 prefilter implemented as well commit a3fd81b6ca213d4a9f8ddfa2883fd0e238d64d04 Author: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Sun Oct 24 01:14:10 2010 -0400 Implementing Raymond Chen's comb filter idea So far, only the post-filter is there. --- configure.ac | 7 ++ libcelt/celt.c | 306 ++++++++++++++++++++++++++++++++++++--------- libcelt/celt.h | 44 ------- libcelt/entenc.c | 10 +- libcelt/mathops.c | 8 +- libcelt/modes.c | 4 +- libcelt/modes.h | 4 +- libcelt/pitch.c | 189 ++++++++++++++++++++++++++-- libcelt/pitch.h | 6 +- libcelt/plc.c | 2 +- libcelt/rate.c | 4 +- libcelt/testcelt.c | 4 +- 12 files changed, 457 insertions(+), 131 deletions(-) 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;i<overlap;i++) + { + celt_word16 f; + f = MULT16_16_Q15(window[i],window[i]); + y[i] = x[i] + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0]) + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0-1]) + + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0+1]) + + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1]) + + MULT16_32_Q15(MULT16_16_Q15(f,g10),x[i-T1-1]) + + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1+1]); + + } + for (i=overlap;i<N;i++) + y[i] = x[i] + + MULT16_32_Q15(g11,x[i-T1]) + + MULT16_32_Q15(g10,x[i-T1-1]) + + MULT16_32_Q15(g12,x[i-T1+1]); +} +#endif /* ENABLE_POSTFILTER */ + static const signed char tf_select_table[4][8] = { {0, -1, 0, -1, 0,-1, 0,-1}, {0, -1, 0, -2, 1, 0, 1 -1}, @@ -550,7 +601,7 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, const celt_word16 *bandLogE, int nbEBands, int LM, int C, int N0) { int i; - int trim_index = 3; + int trim_index = 2; if (C==2) { celt_word16 sum = 0; /* Q10 */ @@ -601,10 +652,10 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X, } #ifdef FIXED_POINT -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(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) { #else -int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) +int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) { #endif int i, c, N; @@ -624,6 +675,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c VARDECL(int, fine_priority); VARDECL(int, tf_res); celt_sig *_overlap_mem; + celt_sig *prefilter_mem; celt_word16 *oldBandE; int shortBlocks=0; int isTransient=0; @@ -636,6 +688,8 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c int codedBands; int tf_sum; int alloc_trim; + int pitch_index=0; + celt_word16 gain1 = 0; SAVE_STACK; if (nbCompressedBytes<0 || pcm==NULL) @@ -648,8 +702,10 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c return CELT_BAD_ARG; M=1<<LM; - _overlap_mem = st->in_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;c<C;c++) + /* Find pitch period and gain */ { - const celt_word16 * restrict pcmp = pcm+c; - celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap; - CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap); - for (i=0;i<N;i++) + VARDECL(celt_sig, _pre); + celt_sig *pre[2]; + SAVE_STACK; + c = 0; + ALLOC(_pre, C*(N+COMBFILTER_MAXPERIOD), celt_sig); + + pre[0] = _pre; + pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); + + for (c=0;c<C;c++) + { + const celt_word16 * restrict pcmp = pcm+c; + celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap; + + for (i=0;i<N;i++) + { + /* Apply pre-emphasis */ + celt_sig tmp = MULT16_16(st->mode->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); + } + +#ifdef ENABLE_POSTFILTER { - /* Apply pre-emphasis */ - celt_sig tmp = MULT16_16(st->mode->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; + 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<<LM); + pitch_index = COMBFILTER_MAXPERIOD-pitch_index; + + gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, + N, &pitch_index, st->prefilter_period, st->prefilter_gain); } - CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); + 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)<QCONST16(.1,15)) + gain1=st->prefilter_gain; + if (gain1<QCONST16(.2f,15)) + { + ec_enc_bit_prob(enc, 0, 32768); + gain1 = 0; + } else { + int qg; + int octave; +#ifdef FIXED_POINT + qg = ((gain1+2048)>>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<<octave), 4+octave); + ec_enc_bits(enc, qg, 2); + gain1 = QCONST16(.125f,15)*(qg+2); + } + /*printf("%d %f\n", pitch_index, gain1);*/ +#else /* ENABLE_POSTFILTER */ + ec_enc_bit_prob(enc, 0, 32768); +#endif /* ENABLE_POSTFILTER */ + + for (c=0;c<C;c++) + { + CELT_COPY(in+c*(N+st->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;c<C;c++) for (i=0;i<M*st->mode->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];i<N;i++) freq[c*N+i] = 0; - ALLOC(_out_mem, C*N, celt_sig); + out_mem[0] = st->syn_mem[0]+MAX_PERIOD; + if (C==2) + out_mem[1] = st->syn_mem[1]+MAX_PERIOD; for (c=0;c<C;c++) - { overlap_mem[c] = _overlap_mem + c*st->overlap; - 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;c<C;c++) + { + comb_filter(out_mem[c], out_mem[c], st->prefilter_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;j<C*N;j++) in[j] = FLOAT2INT16(pcm[j]); - if (optional_resynthesis != NULL) { - ret=celt_encode_with_ec(st,in,in,frame_size,compressed,nbCompressedBytes, enc); - for (j=0;j<C*N;j++) - optional_resynthesis[j]=in[j]*(1.f/32768.f); - } else { - ret=celt_encode_with_ec(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc); - } + ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, enc); +#ifdef RESYNTH + for (j=0;j<C*N;j++) + ((float*)pcm)[j]=in[j]*(1.f/32768.f); +#endif RESTORE_STACK; return ret; } #endif /*DISABLE_FLOAT_API*/ #else -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(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) { int j, ret, C, N, LM, M; VARDECL(celt_sig, in); @@ -996,13 +1149,11 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, celt_ in[j] = SCALEOUT(pcm[j]); } - if (optional_resynthesis != NULL) { - ret = celt_encode_with_ec_float(st,in,in,frame_size,compressed,nbCompressedBytes, enc); - for (j=0;j<C*N;j++) - optional_resynthesis[j] = FLOAT2INT16(in[j]); - } else { - ret = celt_encode_with_ec_float(st,in,NULL,frame_size,compressed,nbCompressedBytes, enc); - } + ret = celt_encode_with_ec_float(st,in,frame_size,compressed,nbCompressedBytes, enc); +#ifdef RESYNTH + for (j=0;j<C*N;j++) + ((celt_int16*)pcm)[j] = FLOAT2INT16(in[j]); +#endif RESTORE_STACK; return ret; } @@ -1010,29 +1161,16 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, celt_ int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) { - return celt_encode_with_ec(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL); + return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); } #ifndef DISABLE_FLOAT_API int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) { - return celt_encode_with_ec_float(st, pcm, NULL, frame_size, compressed, nbCompressedBytes, NULL); + return celt_encode_with_ec_float(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); } #endif /* DISABLE_FLOAT_API */ -int celt_encode_resynthesis(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - return celt_encode_with_ec(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL); -} - -#ifndef DISABLE_FLOAT_API -int celt_encode_resynthesis_float(CELTEncoder * restrict st, const float * pcm, float * optional_resynthesis, int frame_size, unsigned char *compressed, int nbCompressedBytes) -{ - return celt_encode_with_ec_float(st, pcm, optional_resynthesis, frame_size, compressed, nbCompressedBytes, NULL); -} -#endif /* DISABLE_FLOAT_API */ - - int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...) { va_list ap; @@ -1146,6 +1284,8 @@ struct CELTDecoder { int last_pitch_index; int loss_count; + int postfilter_period; + celt_word16 postfilter_gain; celt_sig preemph_memD[2]; @@ -1353,6 +1493,12 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p } } +#ifdef ENABLE_POSTFILTER + /* Apply post-filter to the MDCT overlap of the previous frame */ + comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C, + st->postfilter_gain, st->postfilter_gain, NULL, 0); +#endif /* ENABLE_POSTFILTER */ + for (i=0;i<MAX_PERIOD+st->mode->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;i<N-overlap;i++) out_mem[c][MAX_PERIOD-N+overlap+i] = e[overlap+i]; + +#ifdef ENABLE_POSTFILTER + /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */ + comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap, C, + -st->postfilter_gain, -st->postfilter_gain, NULL, 0); +#endif /* ENABLE_POSTFILTER */ + for (i=0;i<overlap;i++) + out_mem[c][MAX_PERIOD+i] = e[i]; } { @@ -1423,6 +1577,8 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da int effEnd; int codedBands; int alloc_trim; + int postfilter_pitch; + celt_word16 postfilter_gain; SAVE_STACK; if (pcm==NULL) @@ -1482,6 +1638,24 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da } nbAvailableBytes = len-nbFilledBytes; + if (ec_dec_bit_prob(dec, 32768)) + { +#ifdef ENABLE_POSTFILTER + int qg, octave; + octave = ec_dec_uint(dec, 6); + postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave); + qg = ec_dec_bits(dec, 2); + postfilter_gain = QCONST16(.125f,15)*(qg+2); +#else /* ENABLE_POSTFILTER */ + RESTORE_STACK; + return CELT_CORRUPTED_DATA; +#endif /* ENABLE_POSTFILTER */ + + } else { + postfilter_gain = 0; + postfilter_pitch = 0; + } + /* Decode the global flags (first symbols in the stream) */ intra_ener = ec_dec_bit_prob(dec, 8192); /* Get band energies */ @@ -1565,6 +1739,18 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da /* Compute inverse MDCTs */ compute_inv_mdcts(st->mode, shortBlocks, freq, out_syn, overlap_mem, C, LM); +#ifdef ENABLE_POSTFILTER + for (c=0;c<C;c++) + { + comb_filter(out_syn[c], out_syn[c], st->postfilter_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;i<N;i++) + _b->end_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<len>>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<len>>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; +} + +#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<N;i++) + { + xy = MAC16_16(xy, x[i], x[i-T0]); + xx = MAC16_16(xx, x[i], x[i]); + yy = MAC16_16(yy, x[i-T0],x[i-T0]); + } + best_xy = xy; + best_yy = yy; +#ifdef FIXED_POINT + { + celt_word32 x2y2; + int sh, t; + x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy)); + sh = celt_ilog2(x2y2)>>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<N;i++) + { + xy = MAC16_16(xy, x[i], x[i-T1]); + yy = MAC16_16(yy, x[i-T1], x[i-T1]); - /*printf ("%d\n", *pitch);*/ + xy = MAC16_16(xy, x[i], x[i-T1b]); + yy = MAC16_16(yy, x[i-T1b], x[i-T1b]); + } +#ifdef FIXED_POINT + { + celt_word32 x2y2; + int sh, t; + x2y2 = 1+MULT32_32_Q31(xx,yy); + sh = celt_ilog2(x2y2)>>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<N;i++) + xy = MAC16_16(xy, x[i], x[i-T1]); + xcorr[k] = xy; + } + if ((xcorr[2]-xcorr[0]) > 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;i<n;i++) ac0 += SHR32(MULT16_16(xx[i],xx[i]),8); diff --git a/libcelt/rate.c b/libcelt/rate.c index cd9c2b02..9763b6fa 100644 --- a/libcelt/rate.c +++ b/libcelt/rate.c @@ -283,8 +283,8 @@ int compute_allocation(const CELTMode *m, int start, int end, int *offsets, int thresh[j] = 3*(C*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>3; /* Tilt of the allocation curve */ for (j=start;j<end;j++) - trim_offset[j] = C*(m->eBands[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)); -- GitLab