shithub: opus

Download patch

ref: d2c484b5e76f0d02b804b81e30672efa771081da
parent: a4dccd3f659eb60b8b3caa8b04688246851454bf
author: Jean-Marc Valin <[email protected]>
date: Mon May 6 12:02:31 EDT 2013

Adds spreading to the surround masking computation

This avoids a single low-energy band from changing the masking results.

--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -1411,13 +1411,23 @@
          st->energy_save[i]=bandLogE[i]-offset;
       st->energy_save=NULL;
    }
+   /* This computes how much masking takes place between surround channels */
    if (st->energy_mask&&!st->lfe)
    {
       opus_val32 mask_avg=0;
       opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0;
       for (c=0;c<C;c++)
+      {
+         opus_val16 followE, followMask;
+         followE = followMask = -QCONST16(14.f, DB_SHIFT);
          for(i=0;i<st->end;i++)
-            mask_avg += bandLogE[nbEBands*c+i]-offset-st->energy_mask[nbEBands*c+i];
+         {
+            /* We use a simple follower to approximate the masking spreading function. */
+            followE = MAX16(followE-QCONST16(1.f, DB_SHIFT), bandLogE[nbEBands*c+i]-offset);
+            followMask = MAX16(followMask-QCONST16(1.f, DB_SHIFT), st->energy_mask[nbEBands*c+i]);
+            mask_avg += followE-followMask;
+         }
+      }
       surround_masking = DIV32_16(mask_avg,C*st->end) + QCONST16(.0f, DB_SHIFT);
       surround_masking = MIN16(MAX16(surround_masking,-QCONST16(1.5f, DB_SHIFT)), 0);
    }