shithub: opus

Download patch

ref: 9a8bac019c5e459d75a19b67ed59e2d37a5cbf08
parent: 24c9cdaca1b497a4d4637dfbc60774b86143fc6c
author: Jean-Marc Valin <[email protected]>
date: Mon May 5 08:02:14 EDT 2008

Using only a sign for the intra prediction instead of using up to 5 bits for
an offset.

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -331,7 +331,7 @@
          if (q<0)
             intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], norm, P+C*eBands[i], eBands[i], eBands[m->nbEBands+1]);
          else
-            intra_prediction(m, X+C*eBands[i], W+C*eBands[i], eBands[i+1]-eBands[i], q, norm, P+C*eBands[i], eBands[i], enc);
+            intra_prediction(m, X+C*eBands[i], W+C*eBands[i], eBands[i+1]-eBands[i], q, norm, P+C*eBands[i], eBands[i], eBands[m->nbEBands+1], enc);
       }
       
       if (q > 0)
@@ -389,7 +389,7 @@
          if (q<0)
             intra_fold(m, X+C*eBands[i], eBands[i+1]-eBands[i], norm, P+C*eBands[i], eBands[i], eBands[m->nbEBands+1]);
          else
-            intra_unquant(m, X+C*eBands[i], eBands[i+1]-eBands[i], q, norm, P+C*eBands[i], eBands[i], dec);
+            intra_unquant(m, X+C*eBands[i], eBands[i+1]-eBands[i], q, norm, P+C*eBands[i], eBands[i], eBands[m->nbEBands+1], dec);
       }
       
       if (q > 0)
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -47,6 +47,7 @@
 #define BITOVERFLOW 10000
 
 #ifndef STATIC_MODES
+#if 0
 static int log2_frac(ec_uint32 val, int frac)
 {
    int i;
@@ -70,6 +71,7 @@
    }
    return L;
 }
+#endif
 
 static int log2_frac64(ec_uint64 val, int frac)
 {
@@ -135,14 +137,9 @@
                /* FIXME: Could there be a better test for the max number of pulses that fit in 64 bits? */
                if (bits[i][j] > (60<<BITRES))
                   done = 1;
-               /* Add the intra-frame prediction bits */
+               /* Add the intra-frame prediction sign bit */
                if (eBands[i] >= m->pitchEnd)
-               {
-                  int max_pos = 2*eBands[i]-eBands[i+1];
-                  if (max_pos > 32)
-                     max_pos = 32;
-                  bits[i][j] += (1<<BITRES) + log2_frac(max_pos,BITRES);
-               }
+                  bits[i][j] += (1<<BITRES);
             }
             if (done)
                break;
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -267,76 +267,41 @@
 #define MAX_INTRA 32
 #define LOG_MAX_INTRA 5
 
-void intra_prediction(const CELTMode *m, celt_norm_t * restrict x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, ec_enc *enc)
+void intra_prediction(const CELTMode *m, celt_norm_t * restrict x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int Nmax, ec_enc *enc)
 {
-   int i,j,c;
-   int best=0;
-   celt_word16_t best_num=-VERY_LARGE16;
-   celt_word16_t best_den=0;
+   int i,j;
    celt_word16_t s = 1;
    int sign;
    celt_word32_t E;
    celt_word16_t pred_gain;
-   int max_pos = N0-N;
-   celt_word32_t yy=0;
-   VARDECL(celt_norm_t, Xr);
+   celt_word32_t xy=0;
    const int C = CHANNELS(m);
-   SAVE_STACK;
-
-   ALLOC(Xr, C*N, celt_norm_t);
    
-   if (max_pos > MAX_INTRA)
-      max_pos = MAX_INTRA;
-
-   /* Reverse the samples of x without reversing the channels */
-   for (c=0;c<C;c++)
+   if (K>10)
+      pred_gain = pg[10];
+   else
+      pred_gain = pg[K];
+   E = EPSILON;
+   if (N0 >= (Nmax>>1))
    {
-      celt_norm_t * restrict Xrp = &Xr[C*N-C+c];
-      const celt_norm_t * restrict xp = &x[c];
-      j=0; do {
-         *Xrp = *xp;
-         Xrp -= C;
-         xp += C;
-      } while (++j<N); /* Promises we loop at least once */
-   }
-   /* Compute yy for i=0 */
-   j=0;
-   do {
-      yy = MAC16_16(yy, Y[j], Y[j]);
-   } while (++j<C*N); /* Promises we loop at least once */
-
-   for (i=0;i<max_pos;i++)
-   {
-      celt_word32_t xy=0;
-      celt_word16_t num, den;
-      const celt_word16_t * restrict xp = Xr;
-      const celt_word16_t * restrict yp = Y+C*i;
-      j=0;
-      do {
-         xy = MAC16_16(xy, *xp++, *yp++);
-      } while (++j<C*N); /* Promises we loop at least once */
-      /* Using xy^2/yy as the score but without having to do the division */
-      num = MULT16_16_Q15(ROUND16(xy,14),ROUND16(xy,14));
-      den = ROUND16(yy,14);
-      /* If you're really desperate for speed, just use xy as the score */
-      /* OPT: Make sure to use a conditional move here */
-      if (MULT16_16(best_den, num) >  MULT16_16(den, best_num))
+      for (i=0;i<C;i++)
       {
-         best_num = num;
-         best_den = den;
-         best = i;
-         /* Store xy as the sign. We'll normalise it to +/- 1 later. */
-         s = ROUND16(xy,14);
+         for (j=0;j<N;j++)
+         {
+            P[j*C+i] = Y[(Nmax-N0-j-1)*C+i];
+            E += P[j*C+i]*P[j*C+i];
+         }
       }
-      /* Update yy for the next iteration */
-      yp = Y+C*i;
-      j=0;
-      do {
-         yy = yy - MULT16_16(*yp, *yp) + MULT16_16(yp[C*N], yp[C*N]);
-         yp++;
-      } while (++j<C);
+   } else {
+      for (j=0;j<C*N;j++)
+      {
+         P[j] = Y[j];
+         E = MAC16_16(E, P[j],P[j]);
+      }
    }
-   if (s<0)
+   for (j=0;j<C*N;j++)
+      xy = MAC16_16(xy, P[j], x[j]);
+   if (xy<0)
    {
       s = -1;
       sign = 1;
@@ -344,30 +309,10 @@
       s = 1;
       sign = 0;
    }
-   /*printf ("%d %d ", sign, best);*/
    ec_enc_bits(enc,sign,1);
-   if (max_pos == MAX_INTRA)
-      ec_enc_bits(enc,best,LOG_MAX_INTRA);
-   else
-      ec_enc_uint(enc,best,max_pos);
 
-   /*printf ("%d %f\n", best, best_score);*/
-   
-   if (K>10)
-      pred_gain = pg[10];
-   else
-      pred_gain = pg[K];
-   E = EPSILON;
-   for (c=0;c<C;c++)
-   {
-      for (j=0;j<N;j++)
-      {
-         P[C*j+c] = s*Y[C*best+C*(N-j-1)+c];
-         E = MAC16_16(E, P[C*j+c],P[C*j+c]);
-      }
-   }
    /*pred_gain = pred_gain/sqrt(E);*/
-   pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
+   pred_gain = s*MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
    for (j=0;j<C*N;j++)
       P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
    if (K>0)
@@ -378,51 +323,45 @@
       for (j=0;j<C*N;j++)
          x[j] = P[j];
    }
-   /*printf ("quant ");*/
-   /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
-   RESTORE_STACK;
 }
 
-void intra_unquant(const CELTMode *m, celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, ec_dec *dec)
+void intra_unquant(const CELTMode *m, celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int Nmax, ec_dec *dec)
 {
-   int j, c;
-   int sign;
+   int i, j;
    celt_word16_t s;
-   int best;
    celt_word32_t E;
    celt_word16_t pred_gain;
    const int C = CHANNELS(m);
-   int max_pos = N0-N;
-   if (max_pos > MAX_INTRA)
-      max_pos = MAX_INTRA;
-   
-   sign = ec_dec_bits(dec, 1);
-   if (sign == 0)
+      
+   if (ec_dec_bits(dec, 1) == 0)
       s = 1;
    else
       s = -1;
    
-   if (max_pos == MAX_INTRA)
-      best = C*ec_dec_bits(dec, LOG_MAX_INTRA);
-   else
-      best = C*ec_dec_uint(dec, max_pos);
-   /*printf ("%d %d ", sign, best);*/
-
    if (K>10)
       pred_gain = pg[10];
    else
       pred_gain = pg[K];
    E = EPSILON;
-   for (c=0;c<C;c++)
+   if (N0 >= (Nmax>>1))
    {
-      for (j=0;j<N;j++)
+      for (i=0;i<C;i++)
       {
-         P[C*j+c] = s*Y[best+C*(N-j-1)+c];
-         E = MAC16_16(E, P[C*j+c],P[C*j+c]);
+         for (j=0;j<N;j++)
+         {
+            P[j*C+i] = Y[(Nmax-N0-j-1)*C+i];
+            E += P[j*C+i]*P[j*C+i];
+         }
       }
+   } else {
+      for (j=0;j<C*N;j++)
+      {
+         P[j] = Y[j];
+         E = MAC16_16(E, P[j],P[j]);
+      }
    }
    /*pred_gain = pred_gain/sqrt(E);*/
-   pred_gain = MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
+   pred_gain = s*MULT16_16_Q15(pred_gain,celt_rcp(SHL32(celt_sqrt(E),9)));
    for (j=0;j<C*N;j++)
       P[j] = PSHR32(MULT16_16(pred_gain, P[j]),8);
    if (K==0)
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -73,9 +73,9 @@
  * @param N0 Number of valid offsets
  * @param enc Entropy encoder state
  */
-void intra_prediction(const CELTMode *m, celt_norm_t * restrict x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, ec_enc *enc);
+void intra_prediction(const CELTMode *m, celt_norm_t * restrict x, celt_mask_t *W, int N, int K, celt_norm_t *Y, celt_norm_t * restrict P, int N0, int Nmax, ec_enc *enc);
 
-void intra_unquant(const CELTMode *m, celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t *P, int N0, ec_dec *dec);
+void intra_unquant(const CELTMode *m, celt_norm_t *x, int N, int K, celt_norm_t *Y, celt_norm_t *P, int N0, int Nmax, ec_dec *dec);
 
 /** Encode the entire band as a "fold" from other parts of the spectrum. No bits required (only use is case of an emergency!) */
 void intra_fold(const CELTMode *m, celt_norm_t *x, int N, celt_norm_t *Y, celt_norm_t *P, int N0, int Nmax);