From 2af92cd99f1f78f596a49dc951d17faeb9363dd3 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Thu, 27 Oct 2016 14:14:28 -0400 Subject: [PATCH] Fixes an unstable energy issue for low-bitrate hybrid The transient detector would trigger on low-pitch vowels, but we didn't have enough bits to properly code the high bands as a transient, resulting in partial collapse and unstable energy. --- celt/celt_encoder.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/celt/celt_encoder.c b/celt/celt_encoder.c index 5be76103..6f1b1e49 100644 --- a/celt/celt_encoder.c +++ b/celt/celt_encoder.c @@ -226,7 +226,7 @@ void opus_custom_encoder_destroy(CELTEncoder *st) static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, - opus_val16 *tf_estimate, int *tf_chan) + opus_val16 *tf_estimate, int *tf_chan, int low_rate) { int i; VARDECL(opus_val16, tmp); @@ -236,6 +236,12 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int int c; opus_val16 tf_max; int len2; + /* Forward masking: 6.7 dB/ms. */ +#ifdef FIXED_POINT + int forward_shift = 4; +#else + opus_val16 forward_decay = QCONST16(.0625f,15); +#endif /* Table of 6*64/x, trained on real data to minimize the average error */ static const unsigned char inv_table[128] = { 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, @@ -250,6 +256,18 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int SAVE_STACK; ALLOC(tmp, len, opus_val16); + /* For lower bitrates, let's be more conservative and have a forward masking + decay of 3.3 dB/ms. This avoids having to code transients at very low + bitrate (mostly for hybrid), which can result in unstable energy and/or + partial collapse. */ + if (low_rate) + { +#ifdef FIXED_POINT + forward_shift = 5; +#else + forward_decay = QCONST16(.03125f,15); +#endif + } len2=len/2; for (c=0;c=0;i--) { + /* Backward masking: 13.9 dB/ms. */ #ifdef FIXED_POINT /* FIXME: Use PSHR16() instead */ tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); @@ -1586,7 +1605,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, if (st->complexity >= 1 && !st->lfe) { isTransient = transient_analysis(in, N+overlap, CC, - &tf_estimate, &tf_chan); + &tf_estimate, &tf_chan, effectiveBytes<15); } if (LM>0 && ec_tell(enc)+3<=total_bits) {