shithub: opus

Download patch

ref: 9b4ed5e2907d632659193766e02eaf98db9aff4e
parent: 128d0c1cb7832ebb23b847192fcd839d5d5c090e
author: Jean-Marc Valin <[email protected]>
date: Wed Nov 24 13:01:20 EST 2010

Implementing intensity stereo.

There's no explicit signaling for it yet.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -490,6 +490,7 @@
    int B0=B;
    int time_divide=0;
    int recombine=0;
+   int inv = 0;
    celt_word16 mid=0, side=0;
 
    N_B /= B;
@@ -599,32 +600,18 @@
       /* Decide on the resolution to give to the split parameter theta */
       offset = ((m->logN[i]+(LM<<BITRES))>>1) - (stereo ? QTHETA_OFFSET_STEREO : QTHETA_OFFSET);
       qn = compute_qn(N, b, offset, stereo);
-
       qalloc = 0;
+      if (stereo && b<12*N && i>=9)
+         qn = 1;
       if (qn!=1)
       {
          if (encode)
          {
-            if (stereo)
-               stereo_split(X, Y, N);
-
-            mid = vector_norm(X, N);
-            side = vector_norm(Y, N);
-            /* TODO: Renormalising X and Y *may* help fixed-point a bit at very high rate.
-                     Let's do that at higher complexity */
-            /*mid = renormalise_vector(X, Q15ONE, N, 1);
-            side = renormalise_vector(Y, Q15ONE, N, 1);*/
-
             /* theta is the atan() of the ratio between the (normalized)
                side and mid. With just that parameter, we can re-scale both
                mid and side because we know that 1) they have unit norm and
                2) they are orthogonal. */
-   #ifdef FIXED_POINT
-            /* 0.63662 = 2/pi */
-            itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
-   #else
-            itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
-   #endif
+            itheta = stereo_itheta(X, Y, stereo, N);
 
             itheta = (itheta*qn+8192)>>14;
          }
@@ -674,9 +661,31 @@
             qalloc = log2_frac(ft,BITRES) - log2_frac(fs,BITRES) + 1;
          }
          itheta = (celt_int32)itheta*16384/qn;
-      } else {
-         if (stereo && encode)
+         if (encode && stereo)
+            stereo_split(X, Y, N);
+         /* TODO: Renormalising X and Y *may* help fixed-point a bit at very high rate.
+                  Let's do that at higher complexity */
+      } else if (stereo) {
+         if (encode)
+         {
+            inv = itheta > 8192;
+            if (inv)
+            {
+               int j;
+               for (j=0;j<N;j++)
+                  Y[j] = -Y[j];
+            }
             intensity_stereo(m, X, Y, bandE, i, N);
+         }
+         if (b>2<<BITRES)
+         {
+            if (encode)
+               ec_enc_bit_prob(ec, inv, 16384);
+            else
+               inv = ec_dec_bit_prob(ec, 16384);
+            qalloc = 1<<BITRES;
+         } else
+            inv = 0;
       }
 
       if (itheta == 0)
@@ -847,6 +856,12 @@
       {
          if (N!=2)
             stereo_merge(X, Y, mid, side, N);
+         if (inv)
+         {
+            int j;
+            for (j=0;j<N;j++)
+               Y[j] = -Y[j];
+         }
       } else if (level == 0)
       {
          int k;
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -338,19 +338,6 @@
    RESTORE_STACK;
 }
 
-celt_word16 vector_norm(const celt_norm *X, int N)
-{
-   int i;
-   celt_word32 E = EPSILON;
-   const celt_norm *xptr = X;
-   for (i=0;i<N;i++)
-   {
-      E = MAC16_16(E, *xptr, *xptr);
-      xptr++;
-   }
-   return celt_sqrt(E);
-}
-
 void renormalise_vector(celt_norm *X, int N, celt_word16 gain)
 {
    int i;
@@ -381,3 +368,42 @@
    /*return celt_sqrt(E);*/
 }
 
+int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N)
+{
+   int i;
+   int itheta;
+   celt_word16 mid, side;
+   celt_word32 Emid, Eside;
+
+   Emid = Eside = EPSILON;
+   if (stereo)
+   {
+      for (i=0;i<N;i++)
+      {
+         celt_norm m, s;
+         m = X[i]+Y[i];
+         s = X[i]-Y[i];
+         Emid = MAC16_16(Emid, m, m);
+         Eside = MAC16_16(Eside, s, s);
+      }
+   } else {
+      for (i=0;i<N;i++)
+      {
+         celt_norm m, s;
+         m = X[i];
+         s = Y[i];
+         Emid = MAC16_16(Emid, m, m);
+         Eside = MAC16_16(Eside, s, s);
+      }
+   }
+   mid = celt_sqrt(Emid);
+   side = celt_sqrt(Eside);
+#ifdef FIXED_POINT
+   /* 0.63662 = 2/pi */
+   itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
+#else
+   itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
+#endif
+
+   return itheta;
+}
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -66,6 +66,6 @@
 
 void renormalise_vector(celt_norm *X, int N, celt_word16 gain);
 
-celt_word16 vector_norm(const celt_norm *X, int N);
+int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N);
 
 #endif /* VQ_H */