shithub: aacenc

Download patch

ref: f8fb982129460df2d5ae12ac034e22429d3f01f4
parent: a6fd9fd656be01df4b98d66a6a048b5a04a76830
author: knik <knik>
date: Sun Apr 13 04:37:47 EDT 2003

improved quantizer (true VBR)
new noise allocation scheme (better psymodel)

--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -1,7 +1,7 @@
 /*
  * FAAC - Freeware Advanced Audio Coder
  * Copyright (C) 2001 Menno Bakker
- * Copyright (C) 2002 Krzysztof Nikiel
+ * Copyright (C) 2002, 2003 Krzysztof Nikiel
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,7 +17,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: aacquant.c,v 1.16 2003/03/27 17:06:50 knik Exp $
+ * $Id: aacquant.c,v 1.17 2003/04/13 08:37:47 knik Exp $
  */
 
 #include <math.h>
@@ -46,19 +46,10 @@
                            int *sfb_width_table,
                            double *xr);
 
-static int SearchStepSize(CoderInfo *coderInfo,
-                          const int desired_rate,
-                          const double *xr,
-                          int *xi);
-
 static void CalcAllowedDist(PsyInfo *psyInfo, int *cb_offset, int num_cb,
 			    double *xr, double *xmin, int quality);
 
-static int CountBits(CoderInfo *coderInfo, int *ix, const double *xr);
 
-static int CountBitsLong(CoderInfo *coderInfo, int *xi);
-
-
 double *pow43;
 double *adj43;
 double *adj43asm;
@@ -109,8 +100,6 @@
 {
   const double ifqstep = pow(2.0, 0.25);
   const double logstep_1 = 1.0 / log(ifqstep);
-  const int sfcmax = 40;
-  const int sfcmin = -10;
   int sb;
   int nsfb = coderInfo->nr_of_sfb;
   int start, end;
@@ -120,17 +109,24 @@
 
   for (sb = 0; sb < nsfb; sb++)
   {
-    double qfac_1 = pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
+    double qfac_1;
 
     start = coderInfo->sfb_offset[sb];
     end   = coderInfo->sfb_offset[sb+1];
 
+    qfac_1 = pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
+
     en0 = 0.0;
     enq = 0.0;
     for (l = start; l < end; l++)
     {
-      double xq = pow43[xi[l]];
+      double xq;
 
+      if (!sb && !xi[l])
+	continue;
+
+      xq = pow43[xi[l]];
+
       en0 += xr[l] * xr[l];
       enq += xq * xq;
     }
@@ -144,11 +140,6 @@
     shift -= 1000;
 
     shift += coderInfo->scale_factor[sb];
-
-    if (shift < sfcmin)
-      shift = sfcmin;
-    if (shift > sfcmax)
-      shift = sfcmax;
     coderInfo->scale_factor[sb] = shift;
   }
 }
@@ -215,17 +206,11 @@
     if (do_q) {
         CalcAllowedDist(psyInfo, coderInfo->sfb_offset,
 			coderInfo->nr_of_sfb, xr, xmin, quality);
-	bits = SearchStepSize(coderInfo, 9 * quality, xr_pow, xi);
+	coderInfo->global_gain = 0;
 	FixNoise(coderInfo, xr, xr_pow, xi, xmin);
 	BalanceEnergy(coderInfo, xr, xi);
 	UpdateRequant(coderInfo, xi);
 
-#if 0
-	printf("global gain: %d\n", coderInfo->global_gain);
-	for (i = 0; i < coderInfo->nr_of_sfb; i++)
-	  printf("sf %d: %d\n", i, coderInfo->scale_factor[i]);
-#endif
-
         for ( i = 0; i < FRAME_LEN; i++ )  {
             sign = (xr[i] < 0) ? -1 : 1;
             xi[i] *= sign;
@@ -236,7 +221,7 @@
         SetMemory(xi, 0, FRAME_LEN*sizeof(int));
     }
 
-    CountBitsLong(coderInfo, xi);
+    BitSearch(coderInfo, xi);
 
     /* offset the difference of common_scalefac and scalefactors by SF_OFFSET  */
     for (i = 0; i < coderInfo->nr_of_sfb; i++) {
@@ -245,6 +230,11 @@
         }
     }
     coderInfo->global_gain = scale_factor[0];
+#if 0
+	printf("global gain: %d\n", coderInfo->global_gain);
+	for (i = 0; i < coderInfo->nr_of_sfb; i++)
+	  printf("sf %d: %d\n", i, coderInfo->scale_factor[i]);
+#endif
 
     /* place the codewords and their respective lengths in arrays data[] and len[] respectively */
     /* there are 'counter' elements in each array, and these are variable length arrays depending on the input */
@@ -261,74 +251,7 @@
     return bits;
 }
 
-static int SearchStepSize(CoderInfo *coderInfo,
-                          const int desired_rate,
-                          const double *xr,
-                          int *xi)
-{
-    int flag_GoneOver = 0;
-    int CurrentStep = coderInfo->CurrentStep & 0xf;
-    int lastshort = coderInfo->CurrentStep & 0x10;
-    int thisshort = (coderInfo->block_type == ONLY_SHORT_WINDOW) ? 0x10 : 0;
-    int nBits;
-    int StepSize = coderInfo->old_value;
-    int Direction = 0;
-    int blockshift = 0;
 
-    if (thisshort > lastshort)
-      blockshift = -7;
-    if (thisshort < lastshort)
-      blockshift = +7;
-
-    if (blockshift && (StepSize + blockshift) >= 0)
-      StepSize += blockshift;
-
-    do
-    {
-        coderInfo->global_gain = StepSize;
-        nBits = CountBits(coderInfo, xi, xr);
-
-        if (CurrentStep == 1 ) {
-            break; /* nothing to adjust anymore */
-        }
-        if (flag_GoneOver) {
-            CurrentStep /= 2;
-        }
-        if (nBits > desired_rate) { /* increase Quantize_StepSize */
-            if (Direction == -1 && !flag_GoneOver) {
-                flag_GoneOver = 1;
-                CurrentStep /= 2; /* late adjust */
-            }
-            Direction = 1;
-            StepSize += CurrentStep;
-        } else if (nBits < desired_rate) {
-            if (Direction == 1 && !flag_GoneOver) {
-                flag_GoneOver = 1;
-                CurrentStep /= 2; /* late adjust */
-            }
-            Direction = -1;
-            StepSize -= CurrentStep;
-        } else break;
-    } while (1);
-
-    while (nBits > desired_rate)
-    {
-      StepSize++;
-      coderInfo->global_gain = StepSize;
-      nBits = CountBits(coderInfo, xi, xr);
-    }
-
-    CurrentStep = coderInfo->old_value - StepSize;
-    CurrentStep += blockshift;
-
-    coderInfo->CurrentStep = CurrentStep/4 != 0 ? 4 : 2;
-    coderInfo->old_value = coderInfo->global_gain;
-
-    coderInfo->CurrentStep |= thisshort;
-
-    return nBits;
-}
-
 #if 1 /* TAKEHIRO_IEEE754_HACK */
 
 #pragma warning( disable : 4244 4307 )
@@ -433,68 +356,39 @@
 }
 #endif
 
-static int CountBitsLong(CoderInfo *coderInfo, int *xi)
-{
-    int i, bits = 0;
-
-    /* find a good method to section the scalefactor bands into huffman codebook sections */
-    BitSearch(coderInfo, xi);
-
-    /* calculate the amount of bits needed for encoding the huffman codebook numbers */
-    bits += SortBookNumbers(coderInfo, NULL, 0);
-
-    /* calculate the amount of bits needed for the spectral values */
-    coderInfo->spectral_count = 0;
-    for(i = 0; i < coderInfo->nr_of_sfb; i++) {
-        bits += CalcBits(coderInfo,
-            coderInfo->book_vector[i],
-            xi,
-            coderInfo->sfb_offset[i],
-            coderInfo->sfb_offset[i+1] - coderInfo->sfb_offset[i]);
-    }
-
-    /* the number of bits for the scalefactors */
-    bits += WriteScalefactors(coderInfo, NULL, 0);
-
-    /* the total amount of bits required */
-    return bits;
-}
-
-static int CountBits(CoderInfo *coderInfo, int *ix, const double *xr)
-{
-    int bits = 0, i;
-
-    /* since quantize uses table lookup, we need to check this first: */
-    double w = (IXMAX_VAL) / IPOW20(coderInfo->global_gain);
-    for ( i = 0; i < FRAME_LEN; i++ )  {
-        if (xr[i] > w)
-            return LARGE_BITS;
-    }
-
-    Quantize(xr, ix, IPOW20(coderInfo->global_gain));
-
-    bits = CountBitsLong(coderInfo, ix);
-
-    return bits;
-}
-
 static void CalcAllowedDist(PsyInfo *psyInfo, int *cb_offset, int num_cb,
                             double *xr, double *xmin, int quality)
 {
-    int sfb, start, end;
-    double xmin0;
-    const double globalthr = 12.0 / (double)quality;
+  int sfb, start, end, l;
+  const double globalthr = 38.0 / (double)quality;
+  int last = cb_offset[num_cb];
+  double mid = 0.5 * 5.0 / cb_offset[num_cb];
+  double totnrg = 0.0;
+  static const double minfix = 1.5;
 
+  for (l = 0; l < last; l++)
+    totnrg += xr[l] * xr[l];
+
+  totnrg /= last;
+
     for (sfb = 0; sfb < num_cb; sfb++)
     {
+    double thr, tmp;
+    double enrg = 0.0;
+
         start = cb_offset[sfb];
         end = cb_offset[sfb + 1];
 
-        xmin0 = psyInfo->maskEn[sfb];
-        if (xmin0 > 0.0)
-	  xmin0 = psyInfo->maskThr[sfb] * pow(end, 0.6) * globalthr / xmin0;
+    for (l = start; l < end; l++)
+      enrg += xr[l]*xr[l];
 
-	xmin[sfb] = xmin0;
+    thr = pow((double)(end-start)*totnrg/enrg, 0.5*(num_cb-sfb)/num_cb + 0.0);
+
+    tmp = minfix * pow((double)(start + 400) / (double)last, 0.6);
+    if (tmp < thr)
+      thr = tmp;
+
+    xmin[sfb] = psyInfo->maskThr[sfb] * globalthr * thr;
     }
 }
 
@@ -509,12 +403,18 @@
     double quantvol, diffvol;
     double quantfac;
     double tmp;
-    int done = 0;
     const double ifqstep = pow(2.0, 0.1875);
-    const int sfacmax = 30;
+    const double log_ifqstep = 1.0 / log(ifqstep);
+    const double maxstep = 0.05;
 
     for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
     {
+      double sfacfix;
+      double fixstep = 0.25;
+      int sfac;
+      double fac;
+      int dist;
+
       if (!xmin[sb])
         continue;
 
@@ -521,6 +421,30 @@
       start = coderInfo->sfb_offset[sb];
       end = coderInfo->sfb_offset[sb+1];
 
+      tmp = 0.0;
+      for (i = start; i < end; i++)
+      {
+	if (xr_pow[i] > tmp)
+	  tmp = xr_pow[i];
+      }
+
+      //printf("band %d: tmp: %f\n", sb, tmp);
+      if (tmp < 10.0)
+      {
+	for (i = start; i < end; i++)
+	  xi[i] = 0;
+	coderInfo->scale_factor[sb] = 10;
+	continue;
+      }
+
+      sfacfix = 1.0 / tmp;
+      sfac = log(sfacfix) * log_ifqstep - 0.5;
+      for (i = start; i < end; i++)
+	xr_pow[i] *= sfacfix;
+      coderInfo->scale_factor[sb] = sfac;
+      QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end);
+      //printf("\tsfac: %d\n", sfac);
+
     calcdist:
       quantfac = pow(2.0, 0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
 
@@ -529,28 +453,46 @@
       for (i = start; i < end; i++)
       {
 	tmp = pow43[xi[i]];
-	quantvol += tmp;
+	quantvol += tmp * tmp;
 
 	diffvol += fabs(fabs(xr[i]) * quantfac - tmp);
     }
 
-      if (diffvol / quantvol > xmin[sb]) // distorion to high
+      quantvol = sqrt(quantvol/(double)(end-start)) * (double)(end-start);
+      //printf("\tdiffvol: %f, qvol: %f\n", diffvol, quantvol);
+
+      dist = (diffvol / quantvol) > xmin[sb];
+      fac = 0.0;
+      if (fabs(fixstep) > maxstep)
       {
-	if (coderInfo->scale_factor[sb] < sfacmax)
+	if ((dist && (fixstep < 0))
+	    || (!dist && (fixstep > 0)))
 	{
+	  fixstep = -0.5 * fixstep;
+	}
+
+	fac = 1.0 + fixstep;
+      }
+      else if (dist)
+      {
+	fac = 1.0 + fabs(fixstep);
+      }
+
+      if (fac != 0.0)
+      {
+	if (coderInfo->scale_factor[sb] < -10)
+	{
 	  for (i = start; i < end; i++)
-	    xr_pow[i] *= ifqstep;
-	  coderInfo->scale_factor[sb]++;
+	    xr_pow[i] *= fac;
+          sfacfix *= fac;
+	  coderInfo->scale_factor[sb] = log(sfacfix) * log_ifqstep - 0.5;
 	  QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end);
 	  goto calcdist;
 	}
       }
-    else
-	done++;
       //printf("%d: %g\t%g - %g(%d)\n", sb, quantvol, diffvol/quantvol, xmin[sb], coderInfo->scale_factor[sb]);
             }
-
-    return done;
+    return 0;
 }
 
 static int SortForGrouping(CoderInfo* coderInfo,