ref: 35095c6991197ca6b6bfa6870eecc10cba4042b7
parent: bc2c454886676a4c256b0df3958631c003469151
author: Jean-Marc Valin <[email protected]>
date: Thu Nov 4 09:24:44 EDT 2010
Squashed commit of the following: commit a2cc77cb2744a2cb0551b9bfdf06b97457b6d449 Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Thu Nov 4 11:57:12 2010 -0400 Allowing pitches up to 3000 Hz commit 837412d37bbca32bb34bfb5941e132ff4b0a568c Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Wed Nov 3 16:31:51 2010 -0400 Resynthesis now purely a compile-time option with RESYNTH commit d83fb5a9cc2ec4b6cce938662997643da1c5ed0d Author: Jean-Marc Valin <[email protected]> Date: Wed Nov 3 16:28:25 2010 -0400 Fixes a divide by zero in remove_doubling() commit bb91e05b7f8f91fd15a8a0daae3d8cb6bd8d81db Author: Jean-Marc Valin <[email protected]> Date: Wed Nov 3 15:55:48 2010 -0400 Bring back resynthesis with RESYNTH macro commit 31fe6f6b4997af0a46b8c62f523fe2dfdb7f56ae Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Mon Nov 1 17:27:19 2010 -0400 C89 fix commit ee0dbb1855a82ee8c132ddaffcab4d072bb3455e Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Mon Nov 1 10:55:43 2010 -0400 More fixed-point pitch gain work commit 26f1412188900199b63e187fcb0bd04db53c898a Author: Jean-Marc Valin <[email protected]> Date: Mon Nov 1 10:39:25 2010 -0400 Fixed-point version of the pitch gain calculation code commit 27c73d008e9f50d282c3ad08e2f05f7006013ae1 Author: Jean-Marc Valin <[email protected]> Date: Sun Oct 31 16:50:26 2010 -0400 Some more fixed-point work in remove_doubling() commit 59354672cb3af794a0e46c0b2097d6441c75cdd1 Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Date: Fri Oct 29 16:00:01 2010 -0400 More fixed-point post-filter work commit f3e42fde1b575bc587b2557b8b31a6085421a99c Author: Jean-Marc Valin <[email protected]> Date: Fri Oct 29 14:39:23 2010 -0400 More fixed-point work for the prefilter/postfilter commit db945132d12b25ff25acc0701b91a1d8a81417d5 Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Fri Oct 29 10:57:39 2010 -0400 Making the PLC code consistent with the prefilter/postfilter commit 8f64f5974ac846b8c35d0b692e0472f279206cf0 Author: Jean-Marc Valin <[email protected]> Date: Thu Oct 28 00:33:53 2010 -0400 More tuning for remove_doubling() commit 0c08f2ee9dcc135dd222fef30f5ad93e95e0d364 Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Date: Wed Oct 27 14:27:47 2010 -0400 pitch_search() no longer computes the gain commit a7f85bb6b10d9c509caec521ca444efb3f27df05 Author: Jean-Marc Valin <[email protected]> Date: Wed Oct 27 14:00:53 2010 -0400 remove_doubling() now works on the down-sampled signal commit 06cb70e876873f79fed214ebbca35cb4c5057ec8 Author: Jean-Marc Valin <[email protected]> Date: Wed Oct 27 11:28:53 2010 -0400 Simplification to the pitch continuity code commit 5201927c284a424eb8f21f63d358844b3de8c285 Author: Jean-Marc Valin <[email protected]> Date: Wed Oct 27 11:04:02 2010 -0400 Some more pitch doubling prevention code commit 7ef63fbe1f78f79e1923bc42e06fbdf1ec28ffd3 Author: Jean-Marc Valin <[email protected]> Date: Wed Oct 27 06:49:28 2010 -0400 Minor fix commit eb37eaab32e7df074a7ddf0ae4781e57f827c4ad Author: Jean-Marc Valin <[email protected]> Date: Tue Oct 26 18:32:25 2010 -0400 Enforcing some pitch continuity commit 751ef6edf2ee7721252cedb264bdf9b3f6244a9d Author: Jean-Marc Valin <[email protected]> Date: Tue Oct 26 17:29:47 2010 -0400 Code for preventing pitch doubling/halving commit c12647ecb55b645005efbeede91880db72936f8d Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Mon Oct 25 14:59:13 2010 -0400 Very simple/inefficient signalling of the prefilter period/gain commit b4e1215432e3d89a29c998639a6d8b07e28c5a2a Author: Jean-Marc Valin <[email protected]> Date: Mon Oct 25 14:09:17 2010 -0400 using the actual pitch gain commit e7cd4f07bb073b6955a001e56c0bbf16156f4195 Author: Jean-Marc Valin <[email protected]> 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 <[email protected]> Date: Mon Oct 25 00:12:48 2010 -0400 prefilter implemented as well commit a3fd81b6ca213d4a9f8ddfa2883fd0e238d64d04 Author: Jean-Marc Valin <[email protected]> Date: Sun Oct 24 01:14:10 2010 -0400 Implementing Raymond Chen's comb filter idea So far, only the post-filter is there.
--- a/configure.ac
+++ b/configure.ac
@@ -117,6 +117,13 @@
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
--- 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 @@
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 @@
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 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 @@
}
}
+#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 @@
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 @@
}
#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 @@
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 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 @@
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 @@
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++)
{
- /* 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;
+ 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);
}
- 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<<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);
+ }
+ 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 @@
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 @@
/* 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,24 +1051,32 @@
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 */
while (ec_enc_tell(enc,0) + 8 <= nbCompressedBytes*8)
@@ -937,7 +1092,7 @@
#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,13 +1115,11 @@
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;
@@ -973,7 +1126,7 @@
}
#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 @@
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(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 @@
int last_pitch_index;
int loss_count;
+ int postfilter_period;
+ celt_word16 postfilter_gain;
celt_sig preemph_memD[2];
@@ -1353,6 +1493,12 @@
}
}
+#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 @@
}
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 effEnd;
int codedBands;
int alloc_trim;
+ int postfilter_pitch;
+ celt_word16 postfilter_gain;
SAVE_STACK;
if (pcm==NULL)
@@ -1482,6 +1638,24 @@
}
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 */
@@ -1564,6 +1738,18 @@
/* 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;
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -178,30 +178,6 @@
/** 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.
* Samples with a range beyond ±1.0 are supported but will
* be clipped by decoders using the integer API and should
@@ -219,26 +195,6 @@
* decoding is possible.
*/
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
--- a/libcelt/entenc.c
+++ b/libcelt/entenc.c
@@ -45,7 +45,15 @@
}
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;
}
--- a/libcelt/mathops.c
+++ b/libcelt/mathops.c
@@ -74,15 +74,15 @@
{
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;
}
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -53,8 +53,8 @@
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,
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -104,8 +104,8 @@
};
/* 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
--- 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 @@
}
}
+#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 @@
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 @@
}
*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<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]);
+
+ 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 */
--- 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
--- a/libcelt/plc.c
+++ b/libcelt/plc.c
@@ -166,7 +166,7 @@
}
#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);
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -283,8 +283,8 @@
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;
--- a/libcelt/testcelt.c
+++ b/libcelt/testcelt.c
@@ -134,7 +134,7 @@
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 @@
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));