From 90f20c6260a093fc5fba631dcec285e25468d09c Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Fri, 28 Oct 2016 16:44:38 -0400 Subject: [PATCH] Define "weak transients" for low bitrate hybrid These rely on TF rather than short windows to avoid partial collapse. --- celt/celt_encoder.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/celt/celt_encoder.c b/celt/celt_encoder.c index 6f1b1e49..608156d5 100644 --- a/celt/celt_encoder.c +++ b/celt/celt_encoder.c @@ -226,7 +226,8 @@ 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, int low_rate) + opus_val16 *tf_estimate, int *tf_chan, int low_rate, + int *weak_transient) { int i; VARDECL(opus_val16, tmp); @@ -256,6 +257,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int SAVE_STACK; ALLOC(tmp, len, opus_val16); + *weak_transient = 0; /* 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 @@ -381,7 +383,12 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int } } is_transient = mask_metric>200; - + /* For low bitrates, define "weak transients" that need to be + handled differently to avoid partial collapse. */ + if (low_rate && is_transient && mask_metric<600) { + is_transient = 0; + *weak_transient = 1; + } /* Arbitrary metric for VBR boost */ tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ @@ -1388,6 +1395,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, opus_val16 surround_trim = 0; opus_int32 equiv_rate; int hybrid; + int weak_transient = 0; VARDECL(opus_val16, surround_dynalloc); ALLOC_STACK; @@ -1605,7 +1613,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, effectiveBytes<15); + &tf_estimate, &tf_chan, effectiveBytes<15, &weak_transient); } if (LM>0 && ec_tell(enc)+3<=total_bits) { @@ -1784,6 +1792,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan); for (i=effEnd;i