Replace log2_frac in the delta offset calculation.
authorTimothy B. Terriberry <tterribe@xiph.org>
Thu, 13 Jan 2011 00:34:34 +0000 (16:34 -0800)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Thu, 13 Jan 2011 02:21:35 +0000 (21:21 -0500)
Adds a new bitexact_log2tan() function which is much simpler, and
 more accurate.
The new approximation has an RMS error of 0.0038 bits from the
 correctly rounded result over the range of inputs we use, compared
 to an RMS error of 0.013 for the old log2_frac() method.
The actual computation of delta is also changed to use FRAC_MUL16,
 since this allows us to keep the full accuracy of the new method
 while avoiding 16-bit overflow.
The old delta computation actually could overflow 16 bits: it needed
 8 for the log2_frac() result, 1 for the sign of the difference, and
 8 more for N.

libcelt/bands.c

index 0527b3d..830925f 100644 (file)
@@ -61,6 +61,18 @@ static celt_int16 bitexact_cos(celt_int16 x)
    return 1+x2;
 }
 
+static int bitexact_log2tan(int isin,int icos)
+{
+   int lc;
+   int ls;
+   lc=EC_ILOG(icos);
+   ls=EC_ILOG(isin);
+   icos<<=15-lc;
+   isin<<=15-ls;
+   return (ls-lc<<11)
+         +FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
+         -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
+}
 
 #ifdef FIXED_POINT
 /* Compute the amplitude (sqrt energy) in each of the bands */
@@ -760,7 +772,7 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
          iside = bitexact_cos(16384-itheta);
          /* This is the mid vs side allocation that minimizes squared error
             in that band. */
-         delta = (N-1)*(log2_frac(iside,BITRES+2)-log2_frac(imid,BITRES+2))>>2;
+         delta = FRAC_MUL16(N-1<<7,bitexact_log2tan(iside,imid));
       }
 
 #ifdef FIXED_POINT