ref: 37378626205c46690629dd6291ec528703b4ae60
parent: 16f15924f81a147b0799de51c4431035192f50f4
author: Jean-Marc Valin <[email protected]>
date: Tue Oct 11 11:03:38 EDT 2011
Using a noise-based PLC for the CELT layer in hybrid mode
--- a/celt/celt.c
+++ b/celt/celt.c
@@ -2007,8 +2007,7 @@
celt_sig *overlap_mem[2];
opus_val16 *lpc;
opus_val32 *out_syn[2];
- opus_val16 *oldBandE, *oldLogE2, *backgroundLogE;
- int plc=1;
+ opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
SAVE_STACK;
c=0; do {
@@ -2018,8 +2017,9 @@
} while (++c<C);
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
oldBandE = lpc+C*LPC_ORDER;
- oldLogE2 = oldBandE + C*st->mode->nbEBands;
- backgroundLogE = oldLogE2 + C*st->mode->nbEBands;
+ oldLogE = oldBandE + 2*st->mode->nbEBands;
+ oldLogE2 = oldLogE + 2*st->mode->nbEBands;
+ backgroundLogE = oldLogE2 + 2*st->mode->nbEBands;
out_syn[0] = out_mem[0]+MAX_PERIOD-N;
if (C==2)
@@ -2027,8 +2027,9 @@
len = N+st->mode->overlap;
- if (st->loss_count >= 5)
+ if (st->loss_count >= 5 || st->start!=0)
{
+ /* Noise-based PLC/CNG */
VARDECL(celt_sig, freq);
VARDECL(celt_norm, X);
VARDECL(celt_ener, bandE);
@@ -2043,14 +2044,24 @@
ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
- log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C);
-
+ if (st->loss_count >= 5)
+ log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C);
+ else {
+ /* Energy decay */
+ opus_val16 decay = st->loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
+ c=0; do
+ {
+ for (i=st->start;i<st->end;i++)
+ oldBandE[c*st->mode->nbEBands+i] -= decay;
+ } while (++c<C);
+ log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
+ }
seed = st->rng;
for (c=0;c<C;c++)
{
for (i=0;i<(st->mode->eBands[st->start]<<LM);i++)
X[c*N+i] = 0;
- for (i=0;i<st->mode->effEBands;i++)
+ for (i=st->start;i<st->mode->effEBands;i++)
{
int j;
int boffs;
@@ -2083,26 +2094,25 @@
freq[c*N+i] = 0;
} while (++c<C);
compute_inv_mdcts(st->mode, 0, freq, out_syn, overlap_mem, C, LM);
- plc = 0;
- } else if (st->loss_count == 0)
- {
- opus_val16 pitch_buf[DECODE_BUFFER_SIZE>>1];
- /* Corresponds to a min pitch of 67 Hz. It's possible to save CPU in this
- search by using only part of the decode buffer */
- int poffset = 720;
- pitch_downsample(decode_mem, pitch_buf, DECODE_BUFFER_SIZE, C);
- /* Max pitch is 100 samples (480 Hz) */
- pitch_search(pitch_buf+((poffset)>>1), pitch_buf, DECODE_BUFFER_SIZE-poffset,
- poffset-100, &pitch_index);
- pitch_index = poffset-pitch_index;
- st->last_pitch_index = pitch_index;
} else {
- pitch_index = st->last_pitch_index;
- fade = QCONST16(.8f,15);
- }
+ /* Pitch-based PLC */
+ if (st->loss_count == 0)
+ {
+ opus_val16 pitch_buf[DECODE_BUFFER_SIZE>>1];
+ /* Corresponds to a min pitch of 67 Hz. It's possible to save CPU in this
+ search by using only part of the decode buffer */
+ int poffset = 720;
+ pitch_downsample(decode_mem, pitch_buf, DECODE_BUFFER_SIZE, C);
+ /* Max pitch is 100 samples (480 Hz) */
+ pitch_search(pitch_buf+((poffset)>>1), pitch_buf, DECODE_BUFFER_SIZE-poffset,
+ poffset-100, &pitch_index);
+ pitch_index = poffset-pitch_index;
+ st->last_pitch_index = pitch_index;
+ } else {
+ pitch_index = st->last_pitch_index;
+ fade = QCONST16(.8f,15);
+ }
- if (plc)
- {
c=0; do {
VARDECL(opus_val32, e);
opus_val16 exc[MAX_PERIOD];
@@ -2298,7 +2308,7 @@
overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
} while (++c<CC);
lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*CC);
- oldBandE = lpc+LPC_ORDER;
+ oldBandE = lpc+CC*LPC_ORDER;
oldLogE = oldBandE + 2*st->mode->nbEBands;
oldLogE2 = oldLogE + 2*st->mode->nbEBands;
backgroundLogE = oldLogE2 + 2*st->mode->nbEBands;
--- a/celt/quant_bands.c
+++ b/celt/quant_bands.c
@@ -540,7 +540,7 @@
}
void log2Amp(const CELTMode *m, int start, int end,
- celt_ener *eBands, opus_val16 *oldEBands, int _C)
+ celt_ener *eBands, const opus_val16 *oldEBands, int _C)
{
int c, i;
const int C = CHANNELS(_C);
--- a/celt/quant_bands.h
+++ b/celt/quant_bands.h
@@ -39,7 +39,7 @@
celt_ener *bandE, opus_val16 *bandLogE, int _C);
void log2Amp(const CELTMode *m, int start, int end,
- celt_ener *eBands, opus_val16 *oldEBands, int _C);
+ celt_ener *eBands, const opus_val16 *oldEBands, int _C);
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,