First step in quant_band() cleanup: N=1 case.
[opus.git] / celt / bands.c
index 1d49386..412e37f 100644 (file)
@@ -17,8 +17,8 @@
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
-   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 #include "mathops.h"
 #include "rate.h"
 
+int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev)
+{
+   int i;
+   for (i=0;i<N;i++)
+   {
+      if (val < thresholds[i])
+         break;
+   }
+   if (i>prev && val < thresholds[prev]+hysteresis[prev])
+      i=prev;
+   if (i<prev && val > thresholds[prev-1]-hysteresis[prev-1])
+      i=prev;
+   return i;
+}
+
 opus_uint32 celt_lcg_rand(opus_uint32 seed)
 {
    return 1664525 * seed + 1013904223;
@@ -99,8 +114,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
                sum = MAC16_16(sum, EXTRACT16(VSHR32(X[j+c*N],shift)),
                                    EXTRACT16(VSHR32(X[j+c*N],shift)));
             } while (++j<M*eBands[i+1]);
-            /* We're adding one here to make damn sure we never end up with a pitch vector that's
-               larger than unity norm */
+            /* We're adding one here to ensure the normalized band isn't larger than unity norm */
             bandE[i+c*m->nbEBands] = EPSILON+VSHR32(EXTEND32(celt_sqrt(sum)),-shift);
          } else {
             bandE[i+c*m->nbEBands] = EPSILON;
@@ -112,7 +126,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
 }
 
 /* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bandE, int end, int C, int M)
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
@@ -154,7 +168,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
 }
 
 /* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bandE, int end, int C, int M)
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
@@ -173,18 +187,21 @@ void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_nor
 #endif /* FIXED_POINT */
 
 /* De-normalise the energy to produce the synthesis from the unit-energy bands */
-void denormalise_bands(const CELTMode *m, const celt_norm * restrict X, celt_sig * restrict freq, const celt_ener *bandE, int end, int C, int M)
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
+      celt_sig * OPUS_RESTRICT freq, const celt_ener *bandE, int start, int end, int C, int M)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
    N = M*m->shortMdctSize;
    celt_assert2(C<=2, "denormalise_bands() not implemented for >2 channels");
    c=0; do {
-      celt_sig * restrict f;
-      const celt_norm * restrict x;
+      celt_sig * OPUS_RESTRICT f;
+      const celt_norm * OPUS_RESTRICT x;
       f = freq+c*N;
-      x = X+c*N;
-      for (i=0;i<end;i++)
+      x = X+c*N+M*eBands[start];
+      for (i=0;i<M*eBands[start];i++)
+         *f++ = 0;
+      for (i=start;i<end;i++)
       {
          int j, band_end;
          opus_val32 g = SHR32(bandE[i+c*m->nbEBands],1);
@@ -195,13 +212,14 @@ void denormalise_bands(const CELTMode *m, const celt_norm * restrict X, celt_sig
             x++;
          } while (++j<band_end);
       }
+      celt_assert(start <= end);
       for (i=M*eBands[end];i<N;i++)
          *f++ = 0;
    } while (++c<C);
 }
 
 /* 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 CC, int size,
+void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
       int start, int end, opus_val16 *logE, opus_val16 *prev1logE,
       opus_val16 *prev2logE, int *pulses, opus_uint32 seed)
 {
@@ -213,6 +231,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
       int depth;
 #ifdef FIXED_POINT
       int shift;
+      opus_val32 thresh32;
 #endif
 
       N0 = m->eBands[i+1]-m->eBands[i];
@@ -220,7 +239,8 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
       depth = (1+pulses[i])/((m->eBands[i+1]-m->eBands[i])<<LM);
 
 #ifdef FIXED_POINT
-      thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1) ));
+      thresh32 = SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1);
+      thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,thresh32));
       {
          opus_val32 t;
          t = N0<<LM;
@@ -238,24 +258,27 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
          celt_norm *X;
          opus_val16 prev1;
          opus_val16 prev2;
-         opus_val16 Ediff;
+         opus_val32 Ediff;
          opus_val16 r;
          int renormalize=0;
          prev1 = prev1logE[c*m->nbEBands+i];
          prev2 = prev2logE[c*m->nbEBands+i];
-         if (C<CC)
+         if (C==1)
          {
             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);
+         Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2));
+         Ediff = MAX32(0, Ediff);
 
 #ifdef FIXED_POINT
          if (Ediff < 16384)
-            r = 2*MIN16(16383,SHR32(celt_exp2(-Ediff),1));
-         else
+         {
+            opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(Ediff)),1);
+            r = 2*MIN16(16383,r32);
+         } else {
             r = 0;
+         }
          if (LM==3)
             r = MULT16_16_Q14(23170, MIN32(23169, r));
          r = SHR16(MIN16(thresh, r),1);
@@ -393,7 +416,7 @@ int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
 {
    int i, c, N0;
    int sum = 0, nbBands=0;
-   const opus_int16 * restrict eBands = m->eBands;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
    int decision;
    int hf_sum=0;
 
@@ -408,7 +431,7 @@ int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
       {
          int j, N, tmp=0;
          int tcount[3] = {0,0,0};
-         celt_norm * restrict x = X+M*eBands[i]+c*N0;
+         celt_norm * OPUS_RESTRICT x = X+M*eBands[i]+c*N0;
          N = M*(eBands[i+1]-eBands[i]);
          if (N<=8)
             continue;
@@ -625,6 +648,41 @@ static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
    return qn;
 }
 
+static unsigned quant_band_n1(int encode, celt_norm *X, celt_norm *Y, int b,
+      opus_int32 *remaining_bits, ec_ctx *ec, celt_norm *lowband_out)
+{
+#ifdef RESYNTH
+   int resynth = 1;
+#else
+   int resynth = !encode;
+#endif
+   int c;
+   int stereo;
+   celt_norm *x = X;
+   stereo = Y != NULL;
+   c=0; do {
+      int sign=0;
+      if (*remaining_bits>=1<<BITRES)
+      {
+         if (encode)
+         {
+            sign = x[0]<0;
+            ec_enc_bits(ec, sign, 1);
+         } else {
+            sign = ec_dec_bits(ec, 1);
+         }
+         *remaining_bits -= 1<<BITRES;
+         b-=1<<BITRES;
+      }
+      if (resynth)
+         x[0] = sign ? -NORM_SCALING : NORM_SCALING;
+      x = Y;
+   } while (++c<1+stereo);
+   if (lowband_out)
+      lowband_out[0] = SHR16(X[0],4);
+   return 1;
+}
+
 /* This function is responsible for encoding and decoding a band for both
    the mono and stereo case. Even in the mono case, it can split the band
    in two and transmit the energy difference with the two half-bands. It
@@ -665,29 +723,7 @@ static unsigned quant_band(int encode, const CELTMode *m, int i, celt_norm *X, c
    /* Special case for one sample */
    if (N==1)
    {
-      int c;
-      celt_norm *x = X;
-      c=0; do {
-         int sign=0;
-         if (*remaining_bits>=1<<BITRES)
-         {
-            if (encode)
-            {
-               sign = x[0]<0;
-               ec_enc_bits(ec, sign, 1);
-            } else {
-               sign = ec_dec_bits(ec, 1);
-            }
-            *remaining_bits -= 1<<BITRES;
-            b-=1<<BITRES;
-         }
-         if (resynth)
-            x[0] = sign ? -NORM_SCALING : NORM_SCALING;
-         x = Y;
-      } while (++c<1+stereo);
-      if (lowband_out)
-         lowband_out[0] = SHR16(X[0],4);
-      return 1;
+      return quant_band_n1(encode, X, Y, b, remaining_bits, ec, lowband_out);
    }
 
    if (!stereo && level == 0)
@@ -697,7 +733,7 @@ static unsigned quant_band(int encode, const CELTMode *m, int i, celt_norm *X, c
          recombine = tf_change;
       /* Band recombining to increase frequency resolution */
 
-      if (lowband && (recombine || ((N_B&1) == 0 && tf_change<0) || B0>1))
+      if (lowband_scratch && lowband && (recombine || ((N_B&1) == 0 && tf_change<0) || B0>1))
       {
          int j;
          for (j=0;j<N;j++)
@@ -901,8 +937,8 @@ static unsigned quant_band(int encode, const CELTMode *m, int i, celt_norm *X, c
          fill &= ((1<<B)-1)<<B;
          delta = 16384;
       } else {
-         imid = bitexact_cos(itheta);
-         iside = bitexact_cos(16384-itheta);
+         imid = bitexact_cos((opus_int16)itheta);
+         iside = bitexact_cos((opus_int16)(16384-itheta));
          /* This is the mid vs side allocation that minimizes squared error
             in that band. */
          delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
@@ -1171,15 +1207,16 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
 {
    int i;
    opus_int32 remaining_bits;
-   const opus_int16 * restrict eBands = m->eBands;
-   celt_norm * restrict norm, * restrict norm2;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
    VARDECL(celt_norm, _norm);
-   VARDECL(celt_norm, lowband_scratch);
+   celt_norm *lowband_scratch;
    int B;
    int M;
    int lowband_offset;
    int update_lowband = 1;
    int C = Y_ != NULL ? 2 : 1;
+   int norm_offset;
 #ifdef RESYNTH
    int resynth = 1;
 #else
@@ -1189,10 +1226,15 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
 
    M = 1<<LM;
    B = shortBlocks ? M : 1;
-   ALLOC(_norm, C*M*eBands[m->nbEBands], celt_norm);
-   ALLOC(lowband_scratch, M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]), celt_norm);
+   norm_offset = M*eBands[start];
+   /* No need to allocate norm for the last band because we don't need an
+      output in that band */
+   ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
    norm = _norm;
-   norm2 = norm + M*eBands[m->nbEBands];
+   norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
+   /* We can use the last band as scratch space because we don't need that
+      scratch space for the last band */
+   lowband_scratch = X_+M*eBands[m->nbEBands-1];
 
    lowband_offset = 0;
    for (i=start;i<end;i++)
@@ -1202,10 +1244,13 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       int N;
       opus_int32 curr_balance;
       int effective_lowband=-1;
-      celt_norm * restrict X, * restrict Y;
+      celt_norm * OPUS_RESTRICT X, * OPUS_RESTRICT Y;
       int tf_change=0;
       unsigned x_cm;
       unsigned y_cm;
+      int last;
+
+      last = (i==end-1);
 
       X = X_+M*eBands[i];
       if (Y_!=NULL)
@@ -1236,7 +1281,10 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
          X=norm;
          if (Y_!=NULL)
             Y = norm;
+         lowband_scratch = NULL;
       }
+      if (i==end-1)
+         lowband_scratch = NULL;
 
       /* Get a conservative estimate of the collapse_mask's for the bands we're
           going to be folding from. */
@@ -1246,11 +1294,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
          int fold_end;
          int fold_i;
          /* This ensures we never repeat spectral content within one band */
-         effective_lowband = IMAX(M*eBands[start], M*eBands[lowband_offset]-N);
+         effective_lowband = IMAX(0, M*eBands[lowband_offset]-norm_offset-N);
          fold_start = lowband_offset;
-         while(M*eBands[--fold_start] > effective_lowband);
+         while(M*eBands[--fold_start] > effective_lowband+norm_offset);
          fold_end = lowband_offset-1;
-         while(M*eBands[++fold_end] < effective_lowband+N);
+         while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
          x_cm = y_cm = 0;
          fold_i = fold_start; do {
            x_cm |= collapse_masks[fold_i*C+0];
@@ -1268,21 +1316,22 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
 
          /* Switch off dual stereo to do intensity */
          dual_stereo = 0;
-         for (j=M*eBands[start];j<M*eBands[i];j++)
-            norm[j] = HALF32(norm[j]+norm2[j]);
+         if (resynth)
+            for (j=0;j<M*eBands[i]-norm_offset;j++)
+               norm[j] = HALF32(norm[j]+norm2[j]);
       }
       if (dual_stereo)
       {
          x_cm = quant_band(encode, m, i, X, NULL, N, b/2, spread, B, intensity, tf_change,
                effective_lowband != -1 ? norm+effective_lowband : NULL, ec, &remaining_bits, LM,
-               norm+M*eBands[i], bandE, 0, seed, Q15ONE, lowband_scratch, x_cm);
+               last?NULL:norm+M*eBands[i]-norm_offset, bandE, 0, seed, Q15ONE, lowband_scratch, x_cm);
          y_cm = quant_band(encode, m, i, Y, NULL, N, b/2, spread, B, intensity, tf_change,
                effective_lowband != -1 ? norm2+effective_lowband : NULL, ec, &remaining_bits, LM,
-               norm2+M*eBands[i], bandE, 0, seed, Q15ONE, lowband_scratch, y_cm);
+               last?NULL:norm2+M*eBands[i]-norm_offset, bandE, 0, seed, Q15ONE, lowband_scratch, y_cm);
       } else {
          x_cm = quant_band(encode, m, i, X, Y, N, b, spread, B, intensity, tf_change,
                effective_lowband != -1 ? norm+effective_lowband : NULL, ec, &remaining_bits, LM,
-               norm+M*eBands[i], bandE, 0, seed, Q15ONE, lowband_scratch, x_cm|y_cm);
+               last?NULL:norm+M*eBands[i]-norm_offset, bandE, 0, seed, Q15ONE, lowband_scratch, x_cm|y_cm);
          y_cm = x_cm;
       }
       collapse_masks[i*C+0] = (unsigned char)x_cm;