ref: 6ad03ae03e3b37dc472c291e4e77997bf64e6965
parent: bd2e9a34fba837386082e5e16f1b878a16f2274e
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Fri Dec 22 15:14:10 EST 2023
Prevent overshoots from CELT PLC with prediction Constrains the energy prediction to something safe.
--- a/celt/celt_decoder.c
+++ b/celt/celt_decoder.c
@@ -1183,6 +1183,36 @@
/* Decode the global flags (first symbols in the stream) */
intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
+ /* If recovering from packet loss, make sure we make the energy prediction safe to reduce the
+ risk of getting loud artifacts. */
+ if (!intra_ener && st->loss_duration != 0) {
+ c=0; do
+ {
+ opus_val16 safety = 0;
+ int missing = IMIN(10, st->loss_duration>>LM);
+ if (LM==0) safety = QCONST16(1.5f,DB_SHIFT);
+ else if (LM==1) safety = QCONST16(.5f,DB_SHIFT);
+ for (i=start;i<end;i++)
+ {
+ if (oldBandE[c*nbEBands+i] < MAX16(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) {
+ /* If energy is going down already, continue the trend. */
+ opus_val32 slope;
+ opus_val32 E0, E1, E2;
+ E0 = oldBandE[c*nbEBands+i];
+ E1 = oldLogE[c*nbEBands+i];
+ E2 = oldLogE2[c*nbEBands+i];
+ slope = MAX32(E1 - E0, HALF32(E2 - E0));
+ E0 -= MAX32(0, (1+missing)*slope);
+ oldBandE[c*nbEBands+i] = MAX32(-QCONST16(20.f,DB_SHIFT), E0);
+ } else {
+ /* Otherwise take the min of the last frames. */
+ oldBandE[c*nbEBands+i] = MIN16(MIN16(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]);
+ }
+ /* Shorter frames have more natural fluctuations -- play it safe. */
+ oldBandE[c*nbEBands+i] -= safety;
+ }
+ } while (++c<2);
+ }
/* Get band energies */
unquant_coarse_energy(mode, start, end, oldBandE,
intra_ener, dec, C, LM);
--
⑨