shithub: aacenc

Download patch

ref: f8b39149f76c85a5277558b2b64aac7589a7b93a
parent: 393dfe3ecdd3796893ce3e0bd95c2e67687f8eca
author: knik <knik>
date: Sat Nov 23 12:31:52 EST 2002

OuterLoop replaced by FixNoise/BalanceEnergy routines
AACQuantize:
 local variables instead of allocated and freed memory
SearchStepSize:
 long/short block adjustment to run faster

--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -1,6 +1,7 @@
 /*
  * FAAC - Freeware Advanced Audio Coder
  * Copyright (C) 2001 Menno Bakker
+ * Copyright (C) 2002 Krzysztof Nikiel
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,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.12 2002/08/30 16:21:44 knik Exp $
+ * $Id: aacquant.c,v 1.13 2002/11/23 17:31:52 knik Exp $
  */
 
 #include <math.h>
@@ -33,7 +34,31 @@
 #define QUANTFAC(rx)  adj43[rx]
 #define ROUNDFAC 0.4054
 
+static int FixNoise(CoderInfo *coderInfo,
+		    const double *xr,
+		    double *xr_pow,
+		    int *xi,
+		    double *xmin);
 
+static int SortForGrouping(CoderInfo* coderInfo,
+                           PsyInfo *psyInfo,
+                           ChannelInfo *channelInfo,
+                           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 bits);
+
+static int CountBits(CoderInfo *coderInfo, int *ix, const double *xr);
+
+static int CountBitsLong(CoderInfo *coderInfo, int *xi);
+
+
 double *pow43;
 double *adj43;
 double *adj43asm;
@@ -79,6 +104,73 @@
     }
 }
 
+static void BalanceEnergy(CoderInfo *coderInfo,
+			  const double *xr, const int *xi)
+{
+  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;
+  int l;
+  double en0, enq;
+  int shift;
+
+  for (sb = 0; sb < nsfb; sb++)
+  {
+    double qfac_1 = pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
+
+    start = coderInfo->sfb_offset[sb];
+    end   = coderInfo->sfb_offset[sb+1];
+
+    en0 = 0.0;
+    enq = 0.0;
+    for (l = start; l < end; l++)
+    {
+      double xq = pow43[xi[l]];
+
+      en0 += xr[l] * xr[l];
+      enq += xq * xq;
+    }
+
+    if (enq == 0.0)
+      continue;
+
+    enq *= qfac_1 * qfac_1;
+
+    shift = log(sqrt(enq / en0)) * logstep_1 + 1000.5;
+    shift -= 1000;
+
+    shift += coderInfo->scale_factor[sb];
+
+    if (shift < sfcmin)
+      shift = sfcmin;
+    if (shift > sfcmax)
+      shift = sfcmax;
+    coderInfo->scale_factor[sb] = shift;
+  }
+}
+
+static void UpdateRequant(CoderInfo *coderInfo, int *xi)
+{
+  double *requant_xr = coderInfo->requantFreq;
+  int sb;
+  int i;
+
+  for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
+  {
+    double invQuantFac =
+      pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
+    int start = coderInfo->sfb_offset[sb];
+    int end = coderInfo->sfb_offset[sb + 1];
+
+    for (i = start; i < end; i++)
+      requant_xr[i] = pow43[xi[i]] * invQuantFac;
+  }
+}
+
 int AACQuantize(CoderInfo *coderInfo,
                 PsyInfo *psyInfo,
                 ChannelInfo *channelInfo,
@@ -89,18 +181,14 @@
 {
     int sb, i, do_q = 0;
     int bits, sign;
-    double *xr_pow, *xmin;
-    int *xi;
+    double xr_pow[FRAME_LEN];
+    double xmin[MAX_SCFAC_BANDS];
+    int xi[FRAME_LEN];
 
     /* Use local copy's */
     int *scale_factor = coderInfo->scale_factor;
 
 
-    xr_pow = (double*)AllocMemory(FRAME_LEN*sizeof(double));
-    xmin = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-    xi = (int*)AllocMemory(FRAME_LEN*sizeof(int));
-
-
     if (coderInfo->block_type == ONLY_SHORT_WINDOW) {
         SortForGrouping(coderInfo, psyInfo, channelInfo, cb_width, xr);
     } else {
@@ -126,13 +214,19 @@
     }
 
     if (do_q) {
-        bits = SearchStepSize(coderInfo, desired_rate, xr_pow, xi);
-        coderInfo->old_value = coderInfo->global_gain;
-
         CalcAllowedDist(psyInfo, coderInfo->sfb_offset,
-            coderInfo->nr_of_sfb, xr, xmin);
-        OuterLoop(coderInfo, xr, xr_pow, xi, xmin, desired_rate);
+			coderInfo->nr_of_sfb, xr, xmin, desired_rate);
+	bits = SearchStepSize(coderInfo, 0.8 * desired_rate, xr_pow, xi);
+	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;
@@ -165,11 +259,6 @@
             coderInfo->sfb_offset[i+1]-coderInfo->sfb_offset[i]);
     }
 
-
-    if (xmin) FreeMemory(xmin);
-    if (xr_pow) FreeMemory(xr_pow);
-    if (xi) FreeMemory(xi);
-
     return bits;
 }
 
@@ -179,11 +268,22 @@
                           int *xi)
 {
     int flag_GoneOver = 0;
-    int CurrentStep = coderInfo->CurrentStep;
+    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;
@@ -212,11 +312,21 @@
         } 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;
 }
 
@@ -262,6 +372,30 @@
         xp += 4;
     }
 }
+
+static double QuantizeBand(const double *xp, int *pi, double istep,
+			   int offset, int end)
+{
+  int j;
+  double energy = 0.0;
+  double xtmp;
+  fi_union *fi;
+
+  fi = (fi_union *)pi;
+  for (j = offset; j < end; j++)
+  {
+    double x0 = istep * xp[j];
+
+    x0 += MAGIC_FLOAT; fi[j].f = x0;
+    fi[j].f = x0 + (adj43asm - MAGIC_INT)[fi[j].i];
+    fi[j].i -= MAGIC_INT;
+
+    xtmp = pow43[pi[j]];
+    energy += xtmp * xtmp;
+  }
+
+  return energy;
+}
 #else
 static void Quantize(const double *xr, int *ix, double istep)
 {
@@ -352,255 +486,122 @@
     return bits;
 }
 
-static int InnerLoop(CoderInfo *coderInfo,
-                     double *xr_pow,
-                     int *xi,
-                     int max_bits)
-{
-    int bits;
-
-    /*  count bits */
-    bits = CountBits(coderInfo, xi, xr_pow);
-
-    /*  increase quantizer stepsize until needed bits are below maximum */
-    while (bits > max_bits) {
-        coderInfo->global_gain += 1;
-        bits = CountBits(coderInfo, xi, xr_pow);
-    }
-
-    return bits;
-}
-
 static void CalcAllowedDist(PsyInfo *psyInfo, int *cb_offset, int num_cb,
-                            double *xr, double *xmin)
+                            double *xr, double *xmin, int bits)
 {
-    int sfb, start, end, i;
-    double en0, xmin0;
+    int sfb, start, end;
+    double xmin0;
+    double amp = pow(2.0, 3.5 / 1420.0 * (double)bits) * 0.08;
 
-    end = 0;
     for (sfb = 0; sfb < num_cb; sfb++)
     {
         start = cb_offset[sfb];
         end = cb_offset[sfb + 1];
 
-        for (en0 = 0.0, i = start; i < end; i++)
-        {
-            en0 += xr[i] * xr[i];
-        }
-        en0 /= (end - start);
-
-        xmin0 = psyInfo->maskEn[sfb];
+        xmin0 = psyInfo->maskThr[sfb];
         if (xmin0 > 0.0)
-            xmin0 = en0 * psyInfo->maskThr[sfb] / xmin0;
-        xmin[sfb] = xmin0;
+	  xmin0 = psyInfo->maskEn[sfb] / xmin0;
+
+	xmin[sfb] = xmin0 * amp;
     }
 }
 
-static int OuterLoop(CoderInfo *coderInfo,
-                     double *xr,
-                     double *xr_pow,
-                     int *xi,
-                     double *xmin,
-                     int target_bits)
+static double AmpBand(CoderInfo *coderInfo, double *xr_pow, int *xi,
+		      int sfb, double origen, double enmin)
 {
-    int sb;
-    int notdone, over, better;
-    int store_global_gain, outer_loop_count;
-    int best_global_gain, age;
+  double ifqstep;
+  const double logstep_1 = 1.0 / log(pow(2.0, 0.25));
+  double amp0 = sqrt(origen / enmin);
+  double quanten;
+  int i;
+  int sfac, sfacadd;
+  int start = coderInfo->sfb_offset[sfb];
+  int end = coderInfo->sfb_offset[sfb + 1];
+  const int sfacmax = 30;
 
-    calcNoiseResult noiseInfo;
-    calcNoiseResult bestNoiseInfo;
+  if (amp0 < 1e-3) // 1e-3 = -60dB
+    return 0;
+  amp0 = 1.0 / amp0;
+  sfacadd = log(amp0) * logstep_1 + 0.5;
+  sfac = coderInfo->scale_factor[sfb] + sfacadd;
 
-    double sfQuantFac = pow(2.0, 0.1875);
-    int *scale_factor = coderInfo->scale_factor;
-
-    int *best_scale_factor;
-    int *save_xi;
-    double *distort;
-
-    distort = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-    best_scale_factor = (int*)AllocMemory(MAX_SCFAC_BANDS*sizeof(int));
-
-    save_xi = (int*)AllocMemory(FRAME_LEN*sizeof(int));
-
-    notdone = 1;
-    outer_loop_count = 0;
-
-    do { /* outer iteration loop */
-
-        over = 0;
-        outer_loop_count++;
-
-        InnerLoop(coderInfo, xr_pow, xi, target_bits);
-
-        store_global_gain = coderInfo->global_gain;
-
-        over = CalcNoise(coderInfo, xr, xi, coderInfo->requantFreq, distort, xmin, &noiseInfo);
-
-        if (outer_loop_count == 1)
-            better = 1;
-        else
-            better = QuantCompare(&bestNoiseInfo, &noiseInfo);
-
-        if (better) {
-            bestNoiseInfo = noiseInfo;
-            best_global_gain = store_global_gain;
-
-            for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) {
-                best_scale_factor[sb] = scale_factor[sb];
-            }
-            memcpy(save_xi, xi, sizeof(int)*BLOCK_LEN_LONG);
-            age = 0;
-        } else
-            age++;
-
-	if ((age > 3) || ((bestNoiseInfo.over_count == 0) && (age > 0)))
-            break;
-
-        notdone = BalanceNoise(coderInfo, distort, xr_pow);
-
-        for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
-            if (scale_factor[sb] > 30)
-                notdone = 0;
-
-        if (notdone == 0)
-            break;
-
-    } while (1);
-
-    coderInfo->global_gain = best_global_gain;
-    for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) {
-        scale_factor[sb] = best_scale_factor[sb];
+  if (sfac > sfacmax)
+  {
+    sfac = sfacmax;
+    sfacadd = sfac - coderInfo->scale_factor[sfb];
     }
-    memcpy(xi, save_xi, sizeof(int)*BLOCK_LEN_LONG);
-
-    if (best_scale_factor) FreeMemory(best_scale_factor);
-    if (save_xi) FreeMemory(save_xi);
-    if (distort) FreeMemory(distort);
-
+  if (sfacadd < 1)
     return 0;
-}
 
-static int CalcNoise(CoderInfo *coderInfo,
-                     double *xr,
-                     int *xi,
-                     double *requant_xr,
-                     double *error_energy,
-                     double *xmin,
-                     calcNoiseResult *res
-                     )
-{
-    int i, sb, sbw;
-    int over = 0, count = 0;
-    double invQuantFac;
-    double linediff, noise;
+  ifqstep = pow(2.0, sfacadd * 0.1875);
 
-    double over_noise = 1;
-    double tot_noise = 1;
-    double max_noise = 1E-20;
+l0:
+  for (i = start; i < end; i++)
+    xr_pow[i] *= ifqstep;
 
-    for (sb = 0; sb < coderInfo->nr_of_sfb; sb++) {
+  ifqstep = pow(2.0, 0.1875);
 
-        sbw = coderInfo->sfb_offset[sb+1] - coderInfo->sfb_offset[sb];
-
-        invQuantFac = pow(2.0, -0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
-
-        error_energy[sb] = 0.0;
-
-        for (i = coderInfo->sfb_offset[sb]; i < coderInfo->sfb_offset[sb+1]; i++){
-            requant_xr[i] = pow43[xi[i]] * invQuantFac;
-
-            /* measure the distortion in each scalefactor band */
-            linediff = fabs(xr[i]) - requant_xr[i];
-            error_energy[sb] += linediff * linediff;
+  if ((quanten =
+      QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end))
+      < enmin)
+  {
+    if (sfac < sfacmax)
+    {
+      sfac++;
+      goto l0;
         }
-        error_energy[sb] = error_energy[sb] / sbw;
-
-        noise = error_energy[sb] / xmin[sb];
-
-        /* multiplying here is adding in dB */
-        tot_noise *= max(noise, 1E-20);
-        if (noise>1) {
-            over++;
-            /* multiplying here is adding in dB */
-            over_noise *= noise;
-        }
-        max_noise = max(max_noise,noise);
-        error_energy[sb] = noise;
-        count++;
     }
 
-    res->tot_count  = count;
-    res->over_count = over;
-    res->tot_noise   = 10.*log10(max(1e-20,tot_noise ));
-    res->over_noise  = 10.*log10(max(1e+00,over_noise));
-    res->max_noise   = 10.*log10(max(1e-20,max_noise ));
+  sfacadd = sfac - coderInfo->scale_factor[sfb];
+  coderInfo->scale_factor[sfb] = sfac;
 
-    return over;
+  return quanten;
 }
 
-
-static int QuantCompare(calcNoiseResult *best,
-                        calcNoiseResult *calc)
+static int FixNoise(CoderInfo *coderInfo,
+		    const double *xr,
+		    double *xr_pow,
+		    int *xi,
+		    double *xmin)
 {
-    int better;
+    int i, sb;
+    int start, end;
+    double quanten, origen;
+    double quantfac;
+    double noise = 0.0;
+    double tmp;
+    int notdone = 0;
 
-    better = calc->over_count  < best->over_count
-        ||  ( calc->over_count == best->over_count  &&
-        calc->over_noise  < best->over_noise )
-        ||  ( calc->over_count == best->over_count  &&
-        calc->over_noise == best->over_noise  &&
-        calc->tot_noise   < best->tot_noise  );
-
-    return better;
-}
-
-static int BalanceNoise(CoderInfo *coderInfo,
-                        double *distort,
-                        double *xrpow)
-{
-    int status = 0, sb;
-
-    AmpScalefacBands(coderInfo, distort, xrpow);
-
     for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
-        if (coderInfo->scale_factor[sb] == 0)
-            status = 1;
+    {
+      if (!xmin[sb])
+        continue;
 
-    return status;
-}
+      start = coderInfo->sfb_offset[sb];
+      end = coderInfo->sfb_offset[sb+1];
 
-static void AmpScalefacBands(CoderInfo *coderInfo,
-                             double *distort,
-                             double *xr_pow)
-{
-    int start, end, l, sfb;
-    double ifqstep, distort_thresh;
+      quantfac = pow(2.0, 0.25*(coderInfo->scale_factor[sb] - coderInfo->global_gain));
 
-    ifqstep = pow(2.0, 0.1875);
+      quanten = 0.0;
+      origen = 0.0;
+      for (i = start; i < end; i++)
+      {
+	tmp = pow43[xi[i]];
+	quanten += tmp * tmp;
 
-    distort_thresh = -900;
-    for (sfb = 0; sfb < coderInfo->nr_of_sfb; sfb++) {
-        distort_thresh = max(distort[sfb], distort_thresh);
+	tmp = xr[i] * quantfac;
+	origen += tmp * tmp;
     }
 
-    if (distort_thresh>1.0)
-        distort_thresh=1.0;
+      if (quanten < xmin[sb]) // band energy to low
+        noise += AmpBand(coderInfo, xr_pow, xi, sb, origen, xmin[sb]) - origen;
     else
-        distort_thresh *= .95;
-
-    for ( sfb = 0; sfb < coderInfo->nr_of_sfb; sfb++ ) {
-        if (distort[sfb] > distort_thresh) {
-            coderInfo->scale_factor[sfb]++;
-            start = coderInfo->sfb_offset[sfb];
-            end   = coderInfo->sfb_offset[sfb+1];
-            for ( l = start; l < end; l++ ) {
-                xr_pow[l] *= ifqstep;
+	notdone++;
+      //printf("%d: %g - %g(%d)\n", sb, quanten, xmin[sb], coderInfo->scale_factor[sb]);
             }
-        }
-    }
-}
 
+    return notdone;
+}
 
 static int SortForGrouping(CoderInfo* coderInfo,
                            PsyInfo *psyInfo,