shithub: aacenc

Download patch

ref: 71b835a6126b922bd62ba448ad0d2bb13562ca2c
parent: 972a5284df9d375bafdde74f33b3aac75df06d18
author: Krzysztof Nikiel <knik@users.sourceforge.net>
date: Sun Aug 13 05:35:26 EDT 2017

rewritten quantizer

--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -17,7 +17,6 @@
  * 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.33 2012/03/01 18:34:17 knik Exp $
  */
 
 #include <math.h>
@@ -27,49 +26,22 @@
 #include "aacquant.h"
 #include "coder.h"
 #include "huffman.h"
-#include "psych.h"
 #include "util.h"
 
-#define TAKEHIRO_IEEE754_HACK 1
+#include "quantize.c"
 
-#define XRPOW_FTOI(src,dest) ((dest) = (int)(src))
-#define QUANTFAC(rx)  adj43[rx]
-#define ROUNDFAC 0.4054
 
-static int FixNoise(CoderInfo *coderInfo,
-		    const double *xr,
-		    double *xr_pow,
-		    int *xi,
-		    double *xmin,
-		    double *pow43,
-		    double *adj43);
-
-static void CalcAllowedDist(CoderInfo *coderInfo, PsyInfo *psyInfo,
-			    double *xr, double *xmin, int quality);
-
-
 void AACQuantizeInit(CoderInfo *coderInfo, unsigned int numChannels,
-		     AACQuantCfg *aacquantCfg)
+                     AACQuantCfg *aacquantCfg)
 {
     unsigned int channel, i;
 
-    aacquantCfg->pow43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double));
-    aacquantCfg->adj43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double));
 
+    aacquantCfg->pow43 = (double*)AllocMemory(PRECALC_SIZE*sizeof(double));
     aacquantCfg->pow43[0] = 0.0;
     for(i=1;i<PRECALC_SIZE;i++)
         aacquantCfg->pow43[i] = pow((double)i, 4.0/3.0);
 
-#if TAKEHIRO_IEEE754_HACK
-    aacquantCfg->adj43[0] = 0.0;
-    for (i = 1; i < PRECALC_SIZE; i++)
-      aacquantCfg->adj43[i] = i - 0.5 - pow(0.5 * (aacquantCfg->pow43[i - 1] + aacquantCfg->pow43[i]),0.75);
-#else // !TAKEHIRO_IEEE754_HACK
-    for (i = 0; i < PRECALC_SIZE-1; i++)
-        aacquantCfg->adj43[i] = (i + 1) - pow(0.5 * (aacquantCfg->pow43[i] + aacquantCfg->pow43[i + 1]), 0.75);
-    aacquantCfg->adj43[i] = 0.5;
-#endif
-
     for (channel = 0; channel < numChannels; channel++) {
         coderInfo[channel].requantFreq = (double*)AllocMemory(BLOCK_LEN_LONG*sizeof(double));
     }
@@ -76,20 +48,16 @@
 }
 
 void AACQuantizeEnd(CoderInfo *coderInfo, unsigned int numChannels,
-		   AACQuantCfg *aacquantCfg)
+                    AACQuantCfg *aacquantCfg)
 {
     unsigned int channel;
 
+
     if (aacquantCfg->pow43)
-	{
-      FreeMemory(aacquantCfg->pow43);
-      aacquantCfg->pow43 = NULL;
-	}
-    if (aacquantCfg->adj43)
-	{
-      FreeMemory(aacquantCfg->adj43);
-      aacquantCfg->adj43 = NULL;
-	}
+    {
+        FreeMemory(aacquantCfg->pow43);
+        aacquantCfg->pow43 = NULL;
+    }
 
     for (channel = 0; channel < numChannels; channel++) {
         if (coderInfo[channel].requantFreq) FreeMemory(coderInfo[channel].requantFreq);
@@ -96,58 +64,8 @@
     }
 }
 
-static void BalanceEnergy(CoderInfo *coderInfo,
-			  const double *xr, const int *xi,
-			  double *pow43)
-{
-  const double ifqstep = pow(2.0, 0.25);
-  const double logstep_1 = 1.0 / log(ifqstep);
-  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;
-
-    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;
-
-      if (!sb && !xi[l])
-	continue;
-
-      xq = pow43[xi[l]];
-
-      en0 += xr[l] * xr[l];
-      enq += xq * xq;
-    }
-
-    if (enq == 0.0)
-      continue;
-
-    enq *= qfac_1 * qfac_1;
-
-    shift = (int)(log(sqrt(enq / en0)) * logstep_1 + 1000.5);
-    shift -= 1000;
-
-    shift += coderInfo->scale_factor[sb];
-    coderInfo->scale_factor[sb] = shift;
-  }
-}
-
 static void UpdateRequant(CoderInfo *coderInfo, int *xi,
-			  double *pow43)
+                          double *pow43)
 {
   double *requant_xr = coderInfo->requantFreq;
   int sb;
@@ -166,17 +84,13 @@
 }
 
 int AACQuantize(CoderInfo *coderInfo,
-                PsyInfo *psyInfo,
-                ChannelInfo *channelInfo,
                 int *cb_width,
                 int num_cb,
                 double *xr,
-		AACQuantCfg *aacquantCfg)
+                AACQuantCfg *aacquantCfg)
 {
-    int sb, i, do_q = 0;
+    int sb, i;
     int bits = 0, sign;
-    double xr_pow[FRAME_LEN];
-    double xmin[MAX_SCFAC_BANDS];
     int xi[FRAME_LEN];
 
     /* Use local copy's */
@@ -187,31 +101,18 @@
     for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
         scale_factor[sb] = 0;
 
-    /* Compute xr_pow */
-    for (i = 0; i < FRAME_LEN; i++) {
-        double temp = fabs(xr[i]);
-        xr_pow[i] = sqrt(temp * sqrt(temp));
-        do_q += (temp > 1E-20);
-    }
+    if (BlocQuant(coderInfo, xr, xi, (double)aacquantCfg->quality/100))
+    {
+        UpdateRequant(coderInfo, xi, aacquantCfg->pow43);
 
-    if (do_q) {
-        CalcAllowedDist(coderInfo, psyInfo, xr, xmin, aacquantCfg->quality);
-	coderInfo->global_gain = 0;
-	FixNoise(coderInfo, xr, xr_pow, xi, xmin,
-		 aacquantCfg->pow43, aacquantCfg->adj43);
-	BalanceEnergy(coderInfo, xr, xi, aacquantCfg->pow43);
-	UpdateRequant(coderInfo, xi, aacquantCfg->pow43);
-
         for ( i = 0; i < FRAME_LEN; i++ )  {
             sign = (xr[i] < 0) ? -1 : 1;
             xi[i] *= sign;
             coderInfo->requantFreq[i] *= sign;
         }
-    } else {
-        coderInfo->global_gain = 0;
-        SetMemory(xi, 0, FRAME_LEN*sizeof(int));
     }
 
+
     BitSearch(coderInfo, xi);
 
     /* offset the difference of common_scalefac and scalefactors by SF_OFFSET  */
@@ -221,11 +122,6 @@
         }
     }
     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
     // clamp to valid diff range
     {
       int previous_scale_factor = coderInfo->global_gain;
@@ -279,353 +175,9 @@
     return bits;
 }
 
-
-#if TAKEHIRO_IEEE754_HACK
-
-typedef union {
-    float f;
-    int i;
-} fi_union;
-
-#define MAGIC_FLOAT (65536*(128))
-#define MAGIC_INT 0x4b000000
-
-#if 0
-static void Quantize(const double *xp, int *pi, double istep)
-{
-    int j;
-    fi_union *fi;
-
-    fi = (fi_union *)pi;
-    for (j = FRAME_LEN/4 - 1; j >= 0; --j) {
-        double x0 = istep * xp[0];
-        double x1 = istep * xp[1];
-        double x2 = istep * xp[2];
-        double x3 = istep * xp[3];
-
-        x0 += MAGIC_FLOAT; fi[0].f = x0;
-        x1 += MAGIC_FLOAT; fi[1].f = x1;
-        x2 += MAGIC_FLOAT; fi[2].f = x2;
-        x3 += MAGIC_FLOAT; fi[3].f = x3;
-
-        fi[0].f = x0 + (adj43asm - MAGIC_INT)[fi[0].i];
-        fi[1].f = x1 + (adj43asm - MAGIC_INT)[fi[1].i];
-        fi[2].f = x2 + (adj43asm - MAGIC_INT)[fi[2].i];
-        fi[3].f = x3 + (adj43asm - MAGIC_INT)[fi[3].i];
-
-        fi[0].i -= MAGIC_INT;
-        fi[1].i -= MAGIC_INT;
-        fi[2].i -= MAGIC_INT;
-        fi[3].i -= MAGIC_INT;
-        fi += 4;
-        xp += 4;
-    }
-}
-#endif
-static void QuantizeBand(const double *xp, int *pi, double istep,
-			 int offset, int end, double *adj43)
-{
-  int j;
-  fi_union *fi;
-
-  fi = (fi_union *)pi;
-  for (j = offset; j < end; j++)
-  {
-    double x0 = istep * xp[j];
-
-    x0 += MAGIC_FLOAT; fi[j].f = (float)x0;
-    fi[j].f = x0 + (adj43 - MAGIC_INT)[fi[j].i];
-    fi[j].i -= MAGIC_INT;
-  }
-}
-#else
-#if 0
-static void Quantize(const double *xr, int *ix, double istep)
-{
-    int j;
-
-    for (j = FRAME_LEN/8; j > 0; --j) {
-        double x1, x2, x3, x4, x5, x6, x7, x8;
-        int rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8;
-
-        x1 = *xr++ * istep;
-        x2 = *xr++ * istep;
-        XRPOW_FTOI(x1, rx1);
-        x3 = *xr++ * istep;
-        XRPOW_FTOI(x2, rx2);
-        x4 = *xr++ * istep;
-        XRPOW_FTOI(x3, rx3);
-        x5 = *xr++ * istep;
-        XRPOW_FTOI(x4, rx4);
-        x6 = *xr++ * istep;
-        XRPOW_FTOI(x5, rx5);
-        x7 = *xr++ * istep;
-        XRPOW_FTOI(x6, rx6);
-        x8 = *xr++ * istep;
-        XRPOW_FTOI(x7, rx7);
-        x1 += QUANTFAC(rx1);
-        XRPOW_FTOI(x8, rx8);
-        x2 += QUANTFAC(rx2);
-        XRPOW_FTOI(x1,*ix++);
-        x3 += QUANTFAC(rx3);
-        XRPOW_FTOI(x2,*ix++);
-        x4 += QUANTFAC(rx4);
-        XRPOW_FTOI(x3,*ix++);
-        x5 += QUANTFAC(rx5);
-        XRPOW_FTOI(x4,*ix++);
-        x6 += QUANTFAC(rx6);
-        XRPOW_FTOI(x5,*ix++);
-        x7 += QUANTFAC(rx7);
-        XRPOW_FTOI(x6,*ix++);
-        x8 += QUANTFAC(rx8);
-        XRPOW_FTOI(x7,*ix++);
-        XRPOW_FTOI(x8,*ix++);
-    }
-}
-#endif
-static void QuantizeBand(const double *xp, int *ix, double istep,
-			 int offset, int end, double *adj43)
-{
-  int j;
-
-  for (j = offset; j < end; j++)
-  {
-    double x0 = istep * xp[j];
-    x0 += adj43[(int)x0];
-    ix[j] = (int)x0;
-  }
-}
-#endif
-
-static void CalcAllowedDist(CoderInfo *coderInfo, PsyInfo *psyInfo,
-                            double *xr, double *xmin, int quality)
-{
-  int sfb, start, end, l;
-  const double globalthr = 132.0 / (double)quality;
-  int last = coderInfo->lastx;
-  int lastsb = 0;
-  int *cb_offset = coderInfo->sfb_offset;
-  int num_cb = coderInfo->nr_of_sfb;
-  double avgenrg = coderInfo->avgenrg;
-
-  for (sfb = 0; sfb < num_cb; sfb++)
-  {
-    if (last > cb_offset[sfb])
-      lastsb = sfb;
-  }
-
-  for (sfb = 0; sfb < num_cb; sfb++)
-  {
-    double thr, tmp;
-    double enrg = 0.0;
-
-    start = cb_offset[sfb];
-    end = cb_offset[sfb + 1];
-
-    if (sfb > lastsb)
-    {
-      xmin[sfb] = 0;
-      continue;
-    }
-
-    if (coderInfo->block_type != ONLY_SHORT_WINDOW)
-    {
-      double enmax = -1.0;
-      double lmax;
-
-      lmax = start;
-      for (l = start; l < end; l++)
-      {
-	if (enmax < (xr[l] * xr[l]))
-	{
-	  enmax = xr[l] * xr[l];
-	  lmax = l;
-	}
-      }
-
-      start = lmax - 2;
-      end = lmax + 3;
-      if (start < 0)
-	start = 0;
-      if (end > last)
-	end = last;
-    }
-
-    for (l = start; l < end; l++)
-    {
-      enrg += xr[l]*xr[l];
-    }
-
-    thr = enrg/((double)(end-start)*avgenrg);
-    thr = pow(thr, 0.1*(lastsb-sfb)/lastsb + 0.3);
-
-    tmp = 1.0 - ((double)start / (double)last);
-    tmp = tmp * tmp * tmp + 0.075;
-
-    thr = 1.0 / (1.4*thr + tmp);
-
-    xmin[sfb] = ((coderInfo->block_type == ONLY_SHORT_WINDOW) ? 0.65 : 1.12)
-      * globalthr * thr;
-  }
-}
-
-static int FixNoise(CoderInfo *coderInfo,
-		    const double *xr,
-		    double *xr_pow,
-		    int *xi,
-		    double *xmin,
-		    double *pow43,
-		    double *adj43)
-{
-    int i, sb;
-    int start, end;
-    double diffvol;
-    double tmp;
-    const double ifqstep = pow(2.0, 0.1875);
-    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;
-      double sfacfix0 = 1.0, dist0 = 1e50;
-      double maxx;
-
-      start = coderInfo->sfb_offset[sb];
-      end = coderInfo->sfb_offset[sb+1];
-
-      if (!xmin[sb])
-	goto nullsfb;
-
-      maxx = 0.0;
-      for (i = start; i < end; i++)
-      {
-	if (xr_pow[i] > maxx)
-	  maxx = xr_pow[i];
-      }
-
-      //printf("band %d: maxx: %f\n", sb, maxx);
-      if (maxx < 10.0)
-      {
-      nullsfb:
-	for (i = start; i < end; i++)
-	  xi[i] = 0;
-	coderInfo->scale_factor[sb] = 10;
-	continue;
-      }
-
-      sfacfix = 1.0 / maxx;
-      sfac = (int)(log(sfacfix) * log_ifqstep - 0.5);
-      for (i = start; i < end; i++)
-	xr_pow[i] *= sfacfix;
-      maxx *= sfacfix;
-      coderInfo->scale_factor[sb] = sfac;
-      QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end,
-		   adj43);
-      //printf("\tsfac: %d\n", sfac);
-
-    calcdist:
-      diffvol = 0.0;
-      for (i = start; i < end; i++)
-      {
-	tmp = xi[i];
-	diffvol += tmp * tmp;  // ~x^(3/2)
-      }
-
-      if (diffvol < 1e-6)
-	diffvol = 1e-6;
-      tmp = pow(diffvol / (double)(end - start), -0.666);
-
-      if (fabs(fixstep) > maxstep)
-      {
-	double dd = 0.5*(tmp / xmin[sb] - 1.0);
-
-	if (fabs(dd) < fabs(fixstep))
-	{
-	  fixstep = dd;
-
-	  if (fabs(fixstep) < maxstep)
-	    fixstep = maxstep * ((fixstep > 0) ? 1 : -1);
-	}
-      }
-
-      if (fixstep > 0)
-      {
-	if (tmp < dist0)
-	{
-	  dist0 = tmp;
-	  sfacfix0 = sfacfix;
-	}
-	else
-	{
-	  if (fixstep > .1)
-	    fixstep = .1;
-	}
-      }
-      else
-      {
-	dist0 = tmp;
-	sfacfix0 = sfacfix;
-      }
-
-      dist = (tmp > xmin[sb]);
-      fac = 0.0;
-      if (fabs(fixstep) >= maxstep)
-      {
-	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 (maxx * fac >= IXMAX_VAL)
-	{
-	  // restore best noise
-	  fac = sfacfix0 / sfacfix;
-	  for (i = start; i < end; i++)
-	    xr_pow[i] *= fac;
-	  maxx *= fac;
-	  sfacfix *= fac;
-	  coderInfo->scale_factor[sb] = log(sfacfix) * log_ifqstep - 0.5;
-	  QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end,
-		       adj43);
-	  continue;
-	}
-
-	if (coderInfo->scale_factor[sb] < -10)
-	{
-	  for (i = start; i < end; i++)
-	    xr_pow[i] *= fac;
-          maxx *= fac;
-          sfacfix *= fac;
-	  coderInfo->scale_factor[sb] = log(sfacfix) * log_ifqstep - 0.5;
-	  QuantizeBand(xr_pow, xi, IPOW20(coderInfo->global_gain), start, end,
-		       adj43);
-	  goto calcdist;
-	}
-      }
-    }
-    return 0;
-}
-
 int SortForGrouping(CoderInfo* coderInfo,
-                           PsyInfo *psyInfo,
-                           ChannelInfo *channelInfo,
-                           int *sfb_width_table,
-                           double *xr)
+                    int *sfb_width_table,
+                    double *xr)
 {
     int i,j,ii;
     int index = 0;
@@ -686,7 +238,7 @@
 }
 
 void CalcAvgEnrg(CoderInfo *coderInfo,
-		 const double *xr)
+                 const double *xr)
 {
   int end, l;
   int last = 0;
--- a/libfaac/aacquant.h
+++ b/libfaac/aacquant.h
@@ -27,7 +27,6 @@
 #endif /* __cplusplus */
 
 #include "coder.h"
-#include "psych.h"
 
 #define IXMAX_VAL 8191
 #define PRECALC_SIZE (IXMAX_VAL+2)
@@ -41,7 +40,6 @@
 typedef struct
   {
     double *pow43;
-    double *adj43;
     double quality;
   } AACQuantCfg;
 #pragma pack(pop)
@@ -52,8 +50,6 @@
 		    AACQuantCfg *aacquantCfg);
 
 int AACQuantize(CoderInfo *coderInfo,
-                PsyInfo *psyInfo,
-                ChannelInfo *channelInfo,
                 int *cb_width,
                 int num_cb,
                 double *xr,
@@ -60,8 +56,6 @@
 		AACQuantCfg *aacquantcfg);
 
 int SortForGrouping(CoderInfo* coderInfo,
-		    PsyInfo *psyInfo,
-		    ChannelInfo *channelInfo,
 		    int *sfb_width_table,
 		    double *xr);
 void CalcAvgEnrg(CoderInfo *coderInfo,
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,6 @@
  * 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: frame.c,v 1.70 2017/07/01 08:52:28 knik Exp $
  */
 
 /*
@@ -742,8 +741,6 @@
     for (channel = 0; channel < numChannels; channel++) {
 		if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) {
 			SortForGrouping(&coderInfo[channel],
-					&hEncoder->psyInfo[channel],
-					&channelInfo[channel],
 					hEncoder->srInfo->cb_width_short,
 					hEncoder->freqBuff[channel]);
 		}
@@ -772,15 +769,15 @@
     /* Quantize and code the signal */
     for (channel = 0; channel < numChannels; channel++) {
         if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) {
-            AACQuantize(&coderInfo[channel], &hEncoder->psyInfo[channel],
-					&channelInfo[channel], hEncoder->srInfo->cb_width_short,
-					hEncoder->srInfo->num_cb_short, hEncoder->freqBuff[channel],
-					&(hEncoder->aacquantCfg));
+            AACQuantize(&coderInfo[channel],
+                        hEncoder->srInfo->cb_width_short,
+                        hEncoder->srInfo->num_cb_short, hEncoder->freqBuff[channel],
+                        &(hEncoder->aacquantCfg));
         } else {
-            AACQuantize(&coderInfo[channel], &hEncoder->psyInfo[channel],
-					&channelInfo[channel], hEncoder->srInfo->cb_width_long,
-					hEncoder->srInfo->num_cb_long, hEncoder->freqBuff[channel],
-					&(hEncoder->aacquantCfg));
+            AACQuantize(&coderInfo[channel],
+                        hEncoder->srInfo->cb_width_long,
+                        hEncoder->srInfo->num_cb_long, hEncoder->freqBuff[channel],
+                        &(hEncoder->aacquantCfg));
         }
     }
 
@@ -1122,149 +1119,3 @@
     { -1 }
 };
 #endif
-
-/*
-$Log: frame.c,v $
-Revision 1.70  2017/07/01 08:52:28  knik
-fixed CVE-2017-9130 (crash with improper .wav input)
-
-Revision 1.69  2012/03/01 18:34:17  knik
-Build faac against the public API exposed in <faac.h> instead of the private API defined in "libfaac/frame.h".
-
-Revision 1.68  2009/06/05 16:09:38  menno
-Allow higher bitrates
-
-Revision 1.67  2004/11/17 14:26:06  menno
-Infinite loop fix
-dunno if this is good, encoder might be tuned to use energies from before MS encoding. But since the MS encoded samples are used in quantisation this might actually be better. Please test.
-
-Revision 1.66  2004/11/04 12:51:09  aforanna
-version number updated to 1.24.1 due to changes in Winamp and CoolEdit plugins
-
-Revision 1.65  2004/07/18 09:34:24  corrados
-New bandwidth settings for DRM, improved quantization quality adaptation (almost constant bit-rate now)
-
-Revision 1.64  2004/07/13 17:56:37  corrados
-bug fix with new object type definitions
-
-Revision 1.63  2004/07/08 14:01:25  corrados
-New scalefactorband table for 960 transform length, bug fix in HCR
-
-Revision 1.62  2004/07/04 12:10:52  corrados
-made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
-implemented HCR tool, VCB11, CRC, scalable bitstream order
-note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
-960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
-
-Revision 1.61  2004/05/03 11:37:16  danchr
-bump version to unstable 1.24+
-
-Revision 1.60  2004/04/13 13:47:33  danchr
-clarify release <> unstable status
-
-Revision 1.59  2004/04/02 14:56:17  danchr
-fix name clash w/ libavcodec: fft_init -> fft_initialize
-bump version number to 1.24 beta
-
-Revision 1.58  2004/03/17 13:34:20  danchr
-Automatic, untuned setting of lowpass for VBR.
-
-Revision 1.57  2004/03/15 20:16:42  knik
-fixed copyright notice
-
-Revision 1.56  2004/01/23 10:22:26  stux
-*** empty log message ***
-
-Revision 1.55  2003/12/17 20:59:55  knik
-changed default cutoff to 16k
-
-Revision 1.54  2003/11/24 18:09:12  knik
-A safe version of faacEncGetVersion() without string length problem.
-Removed Stux from copyright notice. I don't think he contributed something very
-substantial to faac and this is not the right place to list all contributors.
-
-Revision 1.53  2003/11/16 05:02:52  stux
-moved global tables from fft.c into hEncoder FFT_Tables. Add fft_init and fft_terminate, flowed through all necessary changes. This should remove at least one instance of a memory leak, and fix some thread-safety problems. Version update to 1.23.3
-
-Revision 1.52  2003/11/15 08:13:42  stux
-added FaacEncGetVersion(), version 1.23.2, added myself to faacCopyright :-P, does vanity know no bound ;)
-
-Revision 1.51  2003/11/10 17:48:00  knik
-Allowed independent bitRate and bandWidth setting.
-Small fixes.
-
-Revision 1.50  2003/10/29 10:31:25  stux
-Added channel_map to FaacEncHandle, facilitates free generalised channel remapping in the faac core. Default is straight-through, should be *zero* performance hit... and even probably an immeasurable performance gain, updated FAAC_CFG_VERSION to 104 and FAAC_VERSION to 1.22.0
-
-Revision 1.49  2003/10/12 16:43:39  knik
-average bitrate control made more stable
-
-Revision 1.48  2003/10/12 14:29:53  knik
-more accurate average bitrate control
-
-Revision 1.47  2003/09/24 16:26:54  knik
-faacEncStruct: quantizer specific data enclosed in AACQuantCfg structure.
-Added config option to enforce block type.
-
-Revision 1.46  2003/09/07 16:48:31  knik
-Updated psymodel call. Updated bitrate/cutoff mapping table.
-
-Revision 1.45  2003/08/23 15:02:13  knik
-last frame moved back to the library
-
-Revision 1.44  2003/08/15 11:42:08  knik
-removed single silent flush frame
-
-Revision 1.43  2003/08/11 09:43:47  menno
-thread safety, some tables added to the encoder context
-
-Revision 1.42  2003/08/09 11:39:30  knik
-LFE support enabled by default
-
-Revision 1.41  2003/08/08 10:02:09  menno
-Small fix
-
-Revision 1.40  2003/08/07 08:17:00  knik
-Better LFE support (reduced bandwidth)
-
-Revision 1.39  2003/08/02 11:32:10  stux
-added config.inputFormat, and associated defines and code, faac now handles native endian 16bit, 24bit and float input. Added faacEncGetDecoderSpecificInfo to the dll exports, needed for MP4. Updated DLL .dsp to compile without error. Updated CFG_VERSION to 102. Version number might need to be updated as the API has technically changed. Did not update libfaac.pdf
-
-Revision 1.38  2003/07/10 19:17:01  knik
-24-bit input
-
-Revision 1.37  2003/06/26 19:20:09  knik
-Mid/Side support.
-Copyright info moved from frontend.
-Fixed memory leak.
-
-Revision 1.36  2003/05/12 17:53:16  knik
-updated ABR table
-
-Revision 1.35  2003/05/10 09:39:55  knik
-added approximate ABR setting
-modified default cutoff
-
-Revision 1.34  2003/05/01 09:31:39  knik
-removed ISO psyodel
-disabled m/s coding
-fixed default bandwidth
-reduced max_sfb check
-
-Revision 1.33  2003/04/13 08:37:23  knik
-version number moved to version.h
-
-Revision 1.32  2003/03/27 17:08:23  knik
-added quantizer quality and bandwidth setting
-
-Revision 1.31  2002/10/11 18:00:15  menno
-small bugfix
-
-Revision 1.30  2002/10/08 18:53:01  menno
-Fixed some memory leakage
-
-Revision 1.29  2002/08/19 16:34:43  knik
-added one additional flush frame
-fixed sample buffer memory allocation
-
-*/
--- /dev/null
+++ b/libfaac/quantize.c
@@ -1,0 +1,155 @@
+/****************************************************************************
+    Quantizer core functions
+    quality setting, error distribution, etc.
+
+    Copyright (C) 2017 Krzysztof Nikiel
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+#include <math.h>
+#include "util.h"
+
+// band sound masking
+static void bmask(CoderInfo *coderInfo, double *xr, double *bandqual,
+                  double quality)
+{
+  int sfb, start, end, cnt;
+  int last = coderInfo->lastx;
+  int lastsb = 0;
+  int *cb_offset = coderInfo->sfb_offset;
+  int num_cb = coderInfo->nr_of_sfb;
+  double avgenrg = coderInfo->avgenrg;
+  double pows = 0.16;
+  double powl = 0.9 * pows;
+  enum {MIDF=34};
+
+  for (sfb = 0; sfb < num_cb; sfb++)
+  {
+    if (last > cb_offset[sfb])
+      lastsb = sfb;
+  }
+
+  for (sfb = 0; sfb < num_cb; sfb++)
+  {
+    double avge, maxe;
+    double target;
+
+    start = cb_offset[sfb];
+    end = cb_offset[sfb + 1];
+
+    if (sfb > lastsb)
+    {
+      bandqual[sfb] = 0;
+      continue;
+    }
+
+    avge = 0.0;
+    maxe = 0.0;
+    for (cnt = start; cnt < end; cnt++)
+    {
+        double e = xr[cnt]*xr[cnt];
+        avge += e;
+        if (maxe < e)
+            maxe = e;
+    }
+    avge /= (end - start);
+
+#define NOISETONE 0.2
+    if (coderInfo->block_type == ONLY_SHORT_WINDOW)
+    {
+        target = NOISETONE * pow(avge/avgenrg, pows);
+        target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powl);
+
+        target *= 0.9 + (40.0 / (fabs(start + end - MIDF) + 32));
+    }
+    else
+    {
+        target = NOISETONE * pow(avge/avgenrg, pows);
+        target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powl);
+
+        target *= 0.9 + (40.0 / (0.125 * fabs(start + end - (8*MIDF)) + 32));
+
+        target *= 0.45;
+    }
+    bandqual[sfb] = 5.0 * target * quality;
+  }
+}
+
+// use band quality levels to quantize a block
+static void qlevel(CoderInfo *coderInfo,
+                   const double *xr34,
+                   int *xi,
+                   const double *bandqual)
+{
+    int sb, cnt;
+    int start, end;
+    const double ifqstep = pow(2.0, 0.1875);
+    const double log_ifqstep = 1.0 / log(ifqstep);
+
+    for (sb = 0; sb < coderInfo->nr_of_sfb; sb++)
+    {
+      double sfacfix;
+      int sfac;
+      double maxx;
+
+      start = coderInfo->sfb_offset[sb];
+      end = coderInfo->sfb_offset[sb+1];
+
+      maxx = 0.0;
+      for (cnt = start; cnt < end; cnt++)
+      {
+          if (xr34[cnt] > maxx)
+            maxx = xr34[cnt];
+      }
+
+      if (maxx < 10.0)
+      {
+          for (cnt = start; cnt < end; cnt++)
+              xi[cnt] = 0;
+          coderInfo->scale_factor[sb] = 10;
+          continue;
+      }
+
+      sfac = (int)(log(bandqual[sb] / maxx) * log_ifqstep - 0.5);
+      coderInfo->scale_factor[sb] = sfac;
+      sfacfix = exp(sfac / log_ifqstep);
+      for (cnt = start; cnt < end; cnt++)
+          xi[cnt] = (int)(sfacfix * xr34[cnt] + 0.5);
+    }
+}
+
+int BlocQuant(CoderInfo *coderInfo, double *xr, int *xi, double quality)
+{
+    double xr34[FRAME_LEN];
+    double bandlvl[MAX_SCFAC_BANDS];
+    int cnt;
+    int nonzero = 0;
+
+    for (cnt = 0; cnt < FRAME_LEN; cnt++) {
+        double temp = fabs(xr[cnt]);
+        xr34[cnt] = sqrt(temp * sqrt(temp));
+        nonzero += (temp > 1E-20);
+    }
+
+    SetMemory(xi, 0, FRAME_LEN*sizeof(xi[0]));
+    if (nonzero)
+    {
+        bmask(coderInfo, xr, bandlvl, quality);
+        qlevel(coderInfo, xr34, xi, bandlvl);
+        return 1;
+    }
+
+    return 0;
+}