shithub: opus

Download patch

ref: 0e20ca096970ae9c515a35ae72fd637219241cf5
parent: 8f0f4b942166bf9385319fdbbde390e5a21e0f6a
author: Jean-Marc Valin <[email protected]>
date: Mon Feb 11 10:33:53 EST 2008

Enabling "plain folding" in case we don't even have enough bits for intra-frame
prediction

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -259,11 +259,17 @@
       theta = .007*(B*(eBands[i+1]-eBands[i]))/(.1f+abs(q));
 
       /* If pitch isn't available, use intra-frame prediction */
-      if (eBands[i] >= m->pitchEnd)
-         intra_prediction(X+B*eBands[i], W+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i], enc);
-
-      if (q != 0)
+      if (eBands[i] >= m->pitchEnd || q<=0)
       {
+         q -= 1;
+         if (q<0)
+            intra_fold(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i]);
+         else
+            intra_prediction(X+B*eBands[i], W+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i], enc);
+      }
+      
+      if (q > 0)
+      {
          exp_rotation(P+B*eBands[i], B*(eBands[i+1]-eBands[i]), theta, -1, B, 8);
          exp_rotation(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), theta, -1, B, 8);
          alg_quant(X+B*eBands[i], W+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, P+B*eBands[i], 0.7, enc);
@@ -305,10 +311,16 @@
       theta = .007*(B*(eBands[i+1]-eBands[i]))/(.1f+abs(q));
 
       /* If pitch isn't available, use intra-frame prediction */
-      if (eBands[i] >= m->pitchEnd)
-         intra_unquant(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i], dec);
-
-      if (q != 0)
+      if (eBands[i] >= m->pitchEnd || q<=0)
+      {
+         q -= 1;
+         if (q<0)
+            intra_fold(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i]);
+         else
+            intra_unquant(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, norm, P+B*eBands[i], B, eBands[i], dec);
+      }
+      
+      if (q > 0)
       {
          exp_rotation(P+B*eBands[i], B*(eBands[i+1]-eBands[i]), theta, -1, B, 8);
          alg_unquant(X+B*eBands[i], B*(eBands[i+1]-eBands[i]), q, P+B*eBands[i], 0.7, dec);
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -118,19 +118,27 @@
          for (j=0;j<MAX_PULSES;j++)
          {
             int done = 0;
-            alloc->bits[i][j] = log2_frac64(ncwrs64(N, j),BITRES);
-            /* FIXME: Could there be a better test for the max number of pulses that fit in 64 bits? */
-            if (alloc->bits[i][j] > (60<<BITRES))
-               done = 1;
-            /* Add the intra-frame prediction bits */
+            int pulses = j;
+            /* For bands where there's no pitch, id 1 corresponds to intra prediction 
+               with no pulse. id 2 means intra prediction with one pulse, and so on.*/
             if (eBands[i] >= m->pitchEnd)
-            {
-               int max_pos = 2*eBands[i]-eBands[i+1];
-               if (max_pos > 32)
-                  max_pos = 32;
-               alloc->bits[i][j] += (1<<BITRES) + log2_frac(max_pos,BITRES);
+               pulses -= 1;
+            if (pulses < 0)
+               alloc->bits[i][j] = 0;
+            else {
+               alloc->bits[i][j] = log2_frac64(ncwrs64(N, pulses),BITRES);
+               /* FIXME: Could there be a better test for the max number of pulses that fit in 64 bits? */
+               if (alloc->bits[i][j] > (60<<BITRES))
+                  done = 1;
+               /* Add the intra-frame prediction bits */
+               if (eBands[i] >= m->pitchEnd)
+               {
+                  int max_pos = 2*eBands[i]-eBands[i+1];
+                  if (max_pos > 32)
+                     max_pos = 32;
+                  alloc->bits[i][j] += (1<<BITRES) + log2_frac(max_pos,BITRES);
+               }
             }
-            /* We could just update rev_bits here */
             if (done)
                break;
          }
--- a/libcelt/testcelt.c
+++ b/libcelt/testcelt.c
@@ -66,9 +66,9 @@
    }
    
    bytes_per_packet = atoi(argv[2]);
-   if (bytes_per_packet < 20 || bytes_per_packet > 120)
+   if (bytes_per_packet < 15 || bytes_per_packet > 120)
    {
-      fprintf (stderr, "bytes per packet must be between 20 and 120\n");
+      fprintf (stderr, "bytes per packet must be between 15 and 120\n");
       return 1;
    }
    inFile = argv[3];
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -372,3 +372,22 @@
          x[j] = P[j];
    }
 }
+
+void intra_fold(float *x, int N, int K, float *Y, float *P, int B, int N0)
+{
+   int j;
+   float E;
+   
+   E = 1e-10;
+   for (j=0;j<N;j++)
+   {
+      P[j] = Y[j];
+      E += P[j]*P[j];
+   }
+   E = 1.f/sqrt(E);
+   for (j=0;j<N;j++)
+      P[j] *= E;
+   for (j=0;j<N;j++)
+      x[j] = P[j];
+}
+
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -75,4 +75,6 @@
 
 void intra_unquant(float *x, int N, int K, float *Y, float *P, int B, int N0, ec_dec *dec);
 
+void intra_fold(float *x, int N, int K, float *Y, float *P, int B, int N0);
+
 #endif /* VQ_H */