shithub: opus

Download patch

ref: 682b6cf1ad9a8410c19c7c3864344d94abad93fc
parent: 948d27c9bcf48e019e843766f9009f4f38386207
author: Timothy B. Terriberry <[email protected]>
date: Mon Jan 31 08:34:54 EST 2011

Don't destroy stereo history when switching to mono.

The first version of the mono decoder with stereo output collapsed
 the historic energy values stored for anti-collapse down to one
 channel (by taking the max).
This means that a subsequent switch back would continue on using
 the the maximum of the two values instead of the original history,
 which would make anti-collapse produce louder noise (and
 potentially more pre-echo than otherwise).

This patch moves the max into the anti_collapse function itself,
 and does not store the values back into the source array, so the
 full stereo history is maintained if subsequent frames switch
 back.
It also fixes an encoder mismatch, which never took the max
 (assuming, apparently, that the output channel count would never
 change).

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -212,7 +212,7 @@
 }
 
 /* This prevents energy collapse for transients with multiple short MDCTs */
-void anti_collapse(const CELTMode *m, celt_norm *_X, unsigned char *collapse_masks, int LM, int C, int size,
+void anti_collapse(const CELTMode *m, celt_norm *_X, unsigned char *collapse_masks, int LM, int C, int CC, int size,
       int start, int end, celt_word16 *logE, celt_word16 *prev1logE,
       celt_word16 *prev2logE, int *pulses, celt_uint32 seed)
 {
@@ -247,9 +247,18 @@
       c=0; do
       {
          celt_norm *X;
+         celt_word16 prev1;
+         celt_word16 prev2;
          celt_word16 Ediff;
          celt_word16 r;
-         Ediff = logE[c*m->nbEBands+i]-MIN16(prev1logE[c*m->nbEBands+i],prev2logE[c*m->nbEBands+i]);
+         prev1 = prev1logE[c*m->nbEBands+i];
+         prev2 = prev2logE[c*m->nbEBands+i];
+         if (C<CC)
+         {
+            prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]);
+            prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]);
+         }
+         Ediff = logE[c*m->nbEBands+i]-MIN16(prev1,prev2);
          Ediff = MAX16(0, Ediff);
 
 #ifdef FIXED_POINT
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -93,7 +93,7 @@
 
 void stereo_decision(const CELTMode *m, celt_norm * restrict X, int *stereo_mode, int len, int M);
 
-void anti_collapse(const CELTMode *m, celt_norm *_X, unsigned char *collapse_masks, int LM, int C, int size,
+void anti_collapse(const CELTMode *m, celt_norm *_X, unsigned char *collapse_masks, int LM, int C, int CC, int size,
       int start, int end, celt_word16 *logE, celt_word16 *prev1logE,
       celt_word16 *prev2logE, int *pulses, celt_uint32 seed);
 
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -1454,7 +1454,7 @@
 #endif
       if (anti_collapse_on)
       {
-         anti_collapse(st->mode, X, collapse_masks, LM, C, N,
+         anti_collapse(st->mode, X, collapse_masks, LM, C, CC, N,
                st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng);
       }
 
@@ -2204,8 +2204,6 @@
       for (i=0;i<st->mode->nbEBands;i++)
       {
          oldBandE[i]=MAX16(oldBandE[i],oldBandE[st->mode->nbEBands+i]);
-         oldLogE[i]=MAX16(oldLogE[i],oldLogE[st->mode->nbEBands+i]);
-         oldLogE2[i]=MAX16(oldLogE2[i],oldLogE2[st->mode->nbEBands+i]);
          backgroundLogE[i]=MAX16(backgroundLogE[i],backgroundLogE[st->mode->nbEBands+i]);
       }
    }
@@ -2341,7 +2339,7 @@
          fine_quant, fine_priority, len*8-ec_dec_tell(dec, 0), dec, C);
 
    if (anti_collapse_on)
-      anti_collapse(st->mode, X, collapse_masks, LM, C, N,
+      anti_collapse(st->mode, X, collapse_masks, LM, C, CC, N,
             st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng);
 
    log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);