Commit 35095c69 authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

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.
parent bc2c4548
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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);