From 6ad03ae03e3b37dc472c291e4e77997bf64e6965 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jmvalin@jmvalin.ca> Date: Fri, 22 Dec 2023 20:14:10 -0500 Subject: [PATCH] Prevent overshoots from CELT PLC with prediction Constrains the energy prediction to something safe. --- celt/celt_decoder.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/celt/celt_decoder.c b/celt/celt_decoder.c index d6cff2609..98ee8edaf 100644 --- a/celt/celt_decoder.c +++ b/celt/celt_decoder.c @@ -1183,6 +1183,36 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char /* 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); -- GitLab