ref: 5a0fae53c7cb604c11014d1de73bbad293083e28
parent: b8002a0ef30d10be1f8e851e72115b376744a3f5
author: Jean-Marc Valin <[email protected]>
date: Mon Dec 14 16:19:37 EST 2009
PLC: Added lag windowing and constraint to synthesis energy
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -54,6 +54,8 @@
#include "float_cast.h"
#include <stdarg.h>
+#define LPC_ORDER 24
+
static const celt_word16 preemph = QCONST16(0.8f,15);
#ifdef FIXED_POINT
@@ -1089,6 +1091,10 @@
celt_word16 *oldBandE;
+#ifndef FIXED_POINT
+ celt_word16 *lpc;
+#endif
+
int last_pitch_index;
int loss_count;
};
@@ -1163,9 +1169,16 @@
st->preemph_memD = (celt_sig*)celt_alloc(C*sizeof(celt_sig));
+#ifndef FIXED_POINT
+ st->lpc = (celt_word16*)celt_alloc(C*LPC_ORDER*sizeof(celt_word16));
+#endif
+
st->loss_count = 0;
if ((st->decode_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) &&
+#ifndef FIXED_POINT
+ (st->lpc!=NULL) &&
+#endif
(st->preemph_memD!=NULL))
{
if (error)
@@ -1208,6 +1221,10 @@
celt_free(st->decode_mem);
celt_free(st->oldBandE);
celt_free(st->preemph_memD);
+
+#ifndef FIXED_POINT
+ celt_free(st->lpc);
+#endif
st->marker = DECODERFREED;
@@ -1217,7 +1234,6 @@
#ifndef FIXED_POINT
#include "plc.c"
#endif
-#define LPC_ORDER 24
static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict pcm)
{
int c, N;
@@ -1271,18 +1287,30 @@
float e[MAX_PERIOD];
float exc[MAX_PERIOD];
float ac[LPC_ORDER+1];
- float lpc[LPC_ORDER];
float decay = 1;
celt_word32 mem[LPC_ORDER]={0};
for (i=0;i<MAX_PERIOD;i++)
exc[i] = st->out_mem[i*C+c];
- _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
- LPC_ORDER, MAX_PERIOD);
- ac[0] *= 1.0001;
- _celt_lpc(lpc, ac, LPC_ORDER);
- fir(exc, lpc, exc, MAX_PERIOD, LPC_ORDER, mem);
+ if (st->loss_count == 0)
+ {
+ _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
+ LPC_ORDER, MAX_PERIOD);
+
+ /* Noise floor -50 dB */
+ ac[0] *= 1.00001;
+ /* Lag windowing */
+ for (i=1;i<=LPC_ORDER;i++)
+ {
+ /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+ ac[i] -= ac[i]*(.008*i)*(.008*i);
+ }
+
+ _celt_lpc(st->lpc, ac, LPC_ORDER);
+ }
+ fir(exc, st->lpc, exc, MAX_PERIOD, LPC_ORDER, mem);
+
/* Check if the waveform is decaying (and if so how fast) */
{
float E1=0, E2=0;
@@ -1301,6 +1329,7 @@
decay = 1;
}
+ float S1=0;
/* Copy excitation, taking decay into account */
for (i=0;i<len+st->mode->overlap;i++)
{
@@ -1310,13 +1339,24 @@
decay *= decay;
}
e[i] = decay*exc[offset+i];
+ S1 += st->out_mem[offset+i]*st->out_mem[offset+i];
}
+ iir(e, st->lpc, e, len+st->mode->overlap, LPC_ORDER, mem);
+
+ {
+ float ratio, S2=0;
+ for (i=0;i<len+overlap;i++)
+ S2 += e[i]*e[i];
+ ratio = sqrt((S1+1)/(S2+1));
+ if (ratio < 1)
+ for (i=0;i<len+overlap;i++)
+ e[i] *= ratio;
+ }
+
for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
st->out_mem[C*i+c] = st->out_mem[C*(N+i)+c];
- iir(e, lpc, e, len+st->mode->overlap, LPC_ORDER, mem);
-
/* Apply TDAC to the concealed audio so that it blends with the
previous and next frames */
for (i=0;i<overlap/2;i++)
@@ -1338,17 +1378,7 @@
}
#endif
- for (c=0;c<C;c++)
- {
- int j;
- for (j=0;j<N;j++)
- {
- celt_sig tmp = MAC16_32_Q15(st->out_mem[C*(MAX_PERIOD-N)+C*j+c],
- preemph,st->preemph_memD[c]);
- st->preemph_memD[c] = tmp;
- pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
- }
- }
+ deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
st->loss_count++;
--- a/libcelt/plc.c
+++ b/libcelt/plc.c
@@ -26,9 +26,9 @@
for (j = 0; j < i; j++)
rr = SUB32(rr,MULT16_16(lpc[j],ac[i - j]));
#ifdef FIXED_POINT
- r = DIV32_16(rr+PSHR32(error,1),ADD16(error,8));
+ r = DIV32_16(rr+PSHR32(error,1),ADD16(error,1));
#else
- r = rr/(error+.003*ac[0]);
+ r = rr/(error+1e-15);
#endif
/* Update LPC coefficients and total error */
lpc[i] = r;
@@ -42,6 +42,8 @@
lpc[j] = MAC16_16_P13(lpc[j],lpc[j],r);
error = SUB16(error,MULT16_16_Q13(r,MULT16_16_Q13(error,r)));
+ if (error<.00001*ac[0])
+ break;
}
return error;
}