Commit 5a0fae53 authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

PLC: Added lag windowing and constraint to synthesis energy

parent b8002a0e
......@@ -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 @@ struct CELTDecoder {
celt_word16 *oldBandE;
#ifndef FIXED_POINT
celt_word16 *lpc;
#endif
int last_pitch_index;
int loss_count;
};
......@@ -1163,9 +1169,16 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
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 @@ void celt_decoder_destroy(CELTDecoder *st)
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 @@ void celt_decoder_destroy(CELTDecoder *st)
#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,17 +1287,29 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
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) */
{
......@@ -1301,6 +1329,7 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
decay = 1;
}
float S1=0;
/* Copy excitation, taking decay into account */
for (i=0;i<len+st->mode->overlap;i++)
{
......@@ -1310,13 +1339,24 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
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 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
}
#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++;
......
......@@ -26,9 +26,9 @@ int p
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 @@ int p
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;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment