shithub: aacenc

Download patch

ref: 577c6499b68ebc46c68f543f91c0e822fc5f8c0c
parent: abe8e167487822dd932fe4f312fbbd4cd3d6ffcd
author: Krzysztof Nikiel <knik@users.sourceforge.net>
date: Sat Oct 14 08:21:38 EDT 2017

initial windows grouping support

--- a/libfaac/quantize.c
+++ b/libfaac/quantize.c
@@ -20,8 +20,9 @@
 
 #include <immintrin.h>
 #include <math.h>
-#include "util.h"
+#include <stdio.h>
 #include "quantize.h"
+#include "huff2.h"
 
 #ifdef __SSE2__
 # ifdef __GNUC__
@@ -36,23 +37,39 @@
 #endif
 
 #define MAGIC_NUMBER  0.4054
-enum {NULL_SF = 0};
 
 // band sound masking
-static void bmask(CoderInfo *coderInfo, double *xr, double *bandqual,
-                  AACQuantCfg *aacquantCfg)
+static void bmask(CoderInfo *coderInfo, double *xr0, double *bandqual,
+                  int gnum, double quality)
 {
   int sfb, start, end, cnt;
   int *cb_offset = coderInfo->sfb_offset;
   int last;
-  double avgenrg = coderInfo->avgenrg;
+  double avgenrg;
   double powm = 0.4;
-  double quality = (double)aacquantCfg->quality/DEFQUAL;
+  double totenrg = 0.0;
+  int gsize = coderInfo->groups.len[gnum];
+  double *xr;
+  int win;
 
-  last = BLOCK_LEN_LONG;
 
   for (sfb = 0; sfb < coderInfo->sfbn; sfb++)
   {
+      start = coderInfo->sfb_offset[sfb];
+      end = coderInfo->sfb_offset[sfb + 1];
+
+      xr = xr0;
+      for (win = 0; win < gsize; win++)
+      {
+          for (cnt = start; cnt < end; cnt++)
+              totenrg += xr[cnt] * xr[cnt];
+
+          xr += BLOCK_LEN_SHORT;
+      }
+  }
+
+  for (sfb = 0; sfb < coderInfo->sfbn; sfb++)
+  {
     double avge, maxe;
     double target;
 
@@ -61,27 +78,40 @@
 
     avge = 0.0;
     maxe = 0.0;
-    for (cnt = start; cnt < end; cnt++)
+    xr = xr0;
+    for (win = 0; win < gsize; win++)
     {
-        double e = xr[cnt]*xr[cnt];
-        avge += e;
-        if (maxe < e)
-            maxe = e;
+        for (cnt = start; cnt < end; cnt++)
+        {
+            double e = xr[cnt]*xr[cnt];
+            avge += e;
+            if (maxe < e)
+                maxe = e;
+        }
+        xr += BLOCK_LEN_SHORT;
     }
-    avge /= (end - start);
+    maxe *= gsize;
 
 #define NOISETONE 0.2
     if (coderInfo->block_type == ONLY_SHORT_WINDOW)
     {
+        last = BLOCK_LEN_SHORT;
+        avgenrg = totenrg / last;
+        avgenrg *= end - start;
+
         target = NOISETONE * pow(avge/avgenrg, powm);
         target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powm);
+
+        target *= 1.5;
     }
     else
     {
+        last = BLOCK_LEN_LONG;
+        avgenrg = totenrg / last;
+        avgenrg *= end - start;
+
         target = NOISETONE * pow(avge/avgenrg, powm);
         target += (1.0 - NOISETONE) * 0.45 * pow(maxe/avgenrg, powm);
-
-        target *= 0.45;
     }
 
     target *= 10.0 / (1.0 + ((double)(start+end)/last));
@@ -90,19 +120,21 @@
   }
 }
 
-// use band quality levels to quantize a block
+enum {MAXSHORTBAND = 36};
+// use band quality levels to quantize a group of windows
 static void qlevel(CoderInfo *coderInfo,
-                   const double *xr,
-                   int *xi,
-                   const double *bandqual, double *pow43)
+                   const double *xr0,
+                   const double *bandqual,
+                   int gnum
+                  )
 {
     int sb, cnt;
-    int start, end;
     // 1.5dB step
     static const double sfstep = 20.0 / 1.5 / M_LN10;
 #ifdef __SSE2__
     int cpuid[4];
     int sse2 = 0;
+    int gsize = coderInfo->groups.len[gnum];
 
     cpuid[3] = 0;
 # ifdef __GNUC__
@@ -121,6 +153,11 @@
       int sfac;
       double maxx;
       double rmsx;
+      int xitab[8 * MAXSHORTBAND];
+      int *xi;
+      int start, end;
+      const double *xr;
+      int win;
 
       start = coderInfo->sfb_offset[sb];
       end = coderInfo->sfb_offset[sb+1];
@@ -127,79 +164,162 @@
 
       maxx = 0.0;
       rmsx = 0.0;
-      for (cnt = start; cnt < end; cnt++)
+      xr = xr0;
+      for (win = 0; win < gsize; win++)
       {
-          double e = xr[cnt] * xr[cnt];
-          if (maxx < e)
-            maxx = e;
-          rmsx += e;
+          for (cnt = start; cnt < end; cnt++)
+          {
+              double e = xr[cnt] * xr[cnt];
+              if (maxx < e)
+                  maxx = e;
+              rmsx += e;
+          }
+          xr += BLOCK_LEN_SHORT;
       }
-      rmsx /= (end - start);
+      rmsx /= ((end - start) * gsize);
       rmsx = sqrt(rmsx);
       maxx = sqrt(maxx);
 
       if (maxx < 10.0)
       {
-          for (cnt = start; cnt < end; cnt++)
-              xi[cnt] = 0;
-          coderInfo->scale_factor[coderInfo->sfcnt++] = NULL_SF;
+          coderInfo->book[coderInfo->bandcnt] = ZERO_HCB;
+          coderInfo->sf[coderInfo->bandcnt++] = 0;
           continue;
       }
 
+      //printf("qual:%f/%f\n", bandqual[sb], bandqual[sb]/rmsx);
       sfac = lrint(log(bandqual[sb] / rmsx) * sfstep);
       sfacfix = exp(sfac / sfstep);
-      coderInfo->scale_factor[coderInfo->sfcnt++] = sfac;
 
-#ifdef __SSE2__
-      if (sse2)
+      xr = xr0 + start;
+      end -= start;
+      xi = xitab;
+      for (win = 0; win < gsize; win++)
       {
-          for (cnt = start; cnt < end; cnt += 4)
+#ifdef __SSE2__
+          if (sse2)
           {
-              __m128 x = {xr[cnt], xr[cnt + 1], xr[cnt + 2], xr[cnt + 3]};
+              for (cnt = 0; cnt < end; cnt += 4)
+              {
+                  __m128 x = {xr[cnt], xr[cnt + 1], xr[cnt + 2], xr[cnt + 3]};
+                  //printf("%f/%f\n", xr[cnt], xr[cnt] * sfacfix);
 
-              x = _mm_max_ps(x, -x);
-              x *= (__m128){sfacfix, sfacfix, sfacfix, sfacfix};
-              x *= _mm_sqrt_ps(x);
-              x = _mm_sqrt_ps(x);
-              x += (__m128){MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER};
+                  x = _mm_max_ps(x, -x);
+                  x *= (__m128){sfacfix, sfacfix, sfacfix, sfacfix};
+                  x *= _mm_sqrt_ps(x);
+                  x = _mm_sqrt_ps(x);
+                  x += (__m128){MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER};
 
-              *(__m128i*)(xi + cnt) = _mm_cvttps_epi32(x);
+                  *(__m128i*)(xi + cnt) = _mm_cvttps_epi32(x);
+                  //printf("%d/%d/%d/%d\n", xi[cnt],xi[cnt+1],xi[cnt+2],xi[cnt+3]);
+              }
+              for (cnt = 0; cnt < end; cnt++)
+              {
+                  if (xr[cnt] < 0)
+                      xi[cnt] = -xi[cnt];
+              }
+              xi += cnt;
+              xr += BLOCK_LEN_SHORT;
+              continue;
           }
-          continue;
-      }
 #endif
 
-      for (cnt = start; cnt < end; cnt++)
-      {
-          double tmp = fabs(xr[cnt]);
+          for (cnt = 0; cnt < end; cnt++)
+          {
+              double tmp = fabs(xr[cnt]);
 
-          tmp *= sfacfix;
-          tmp = sqrt(tmp * sqrt(tmp));
+              tmp *= sfacfix;
+              tmp = sqrt(tmp * sqrt(tmp));
 
-          xi[cnt] = (int)(tmp + MAGIC_NUMBER);
+              xi[cnt] = (int)(tmp + MAGIC_NUMBER);
+              if (xr[cnt] < 0)
+                  xi[cnt] = -xi[cnt];
+          }
+          xi += cnt;
+          xr += BLOCK_LEN_SHORT;
       }
+      huffbook(coderInfo, xitab, gsize * end);
+      coderInfo->sf[coderInfo->bandcnt++] = SF_OFFSET - sfac;
     }
 }
 
-int BlocQuant(CoderInfo *coderInfo, double *xr, int *xi, AACQuantCfg *aacquantCfg)
+int BlocQuant(CoderInfo *coder, double *xr, AACQuantCfg *aacquantCfg)
 {
     double bandlvl[MAX_SCFAC_BANDS];
     int cnt;
     int nonzero = 0;
+    double *gxr;
 
-    coderInfo->sfcnt = 0;
+    coder->global_gain = 0;
+    for (cnt = 0; cnt < coder->sfbn; cnt++)
+        coder->sf[cnt] = 0;
 
+    coder->bandcnt = 0;
+    coder->datacnt = 0;
+
     for (cnt = 0; cnt < FRAME_LEN; cnt++)
         nonzero += (fabs(xr[cnt]) > 1E-20);
 
-    SetMemory(xi, 0, FRAME_LEN*sizeof(xi[0]));
     if (nonzero)
     {
-        bmask(coderInfo, xr, bandlvl, aacquantCfg);
-        qlevel(coderInfo, xr, xi, bandlvl, aacquantCfg->pow43);
+        int lastis;
+        int lastsf;
+
+        gxr = xr;
+        for (cnt = 0; cnt < coder->groups.n; cnt++)
+        {
+            bmask(coder, gxr, bandlvl, cnt,
+                  (double)aacquantCfg->quality/DEFQUAL);
+            qlevel(coder, gxr, bandlvl, cnt);
+            gxr += coder->groups.len[cnt] * BLOCK_LEN_SHORT;
+        }
+
+        coder->global_gain = 0;
+        for (cnt = 0; cnt < coder->bandcnt; cnt++)
+        {
+            int book = coder->book[cnt];
+            if (!book)
+                continue;
+            if ((book != INTENSITY_HCB) && (book != INTENSITY_HCB2))
+            {
+                coder->global_gain = coder->sf[cnt];
+                break;
+            }
+        }
+
+        lastsf = coder->global_gain;
+        lastis = 0;
+        // fixme: move SF range check to quantizer
+        for (cnt = 0; cnt < coder->bandcnt; cnt++)
+        {
+            int book = coder->book[cnt];
+            if ((book == INTENSITY_HCB) || (book == INTENSITY_HCB2))
+            {
+                int diff = coder->sf[cnt] - lastis;
+
+                if (diff < -60)
+                    diff = -60;
+                if (diff > 60)
+                    diff = 60;
+
+                lastis += diff;
+                coder->sf[cnt] = lastis;
+            }
+            else if (book)
+            {
+                int diff = coder->sf[cnt] - lastsf;
+
+                if (diff < -60)
+                    diff = -60;
+                if (diff > 60)
+                    diff = 60;
+
+                lastsf += diff;
+                coder->sf[cnt] = lastsf;
+            }
+        }
         return 1;
     }
-
     return 0;
 }
 
@@ -232,4 +352,99 @@
     aacquantCfg->max_cbl = cnt;
 
     *bw = (double)l * rate / (BLOCK_LEN_LONG << 1);
+}
+
+enum {MINSFB = 2};
+
+static void calce(double *xr, int *bands, double e[NSFB_SHORT], int maxsfb)
+{
+    int sfb;
+    for (sfb = MINSFB; sfb < maxsfb; sfb++)
+    {
+        int l;
+
+        e[sfb] = 0;
+        for (l = bands[sfb]; l < bands[sfb + 1]; l++)
+            e[sfb] += xr[l] * xr[l];
+    }
+}
+
+static void resete(double min[NSFB_SHORT], double max[NSFB_SHORT],
+                   double e[NSFB_SHORT], int maxsfb)
+{
+    int sfb;
+    for (sfb = MINSFB; sfb < maxsfb; sfb++)
+        min[sfb] = max[sfb] = e[sfb];
+}
+
+#define PRINTSTAT 1
+#if PRINTSTAT
+static int groups = 0;
+static int frames = 0;
+#endif
+void BlocGroup(double *xr, CoderInfo *coderInfo, int maxsfb)
+{
+    int win, sfb;
+    double e[NSFB_SHORT];
+    double min[NSFB_SHORT];
+    double max[NSFB_SHORT];
+    const double thr = 3.0;
+    int win0;
+    int fastmin;
+
+    if (coderInfo->block_type != ONLY_SHORT_WINDOW)
+    {
+        coderInfo->groups.n = 1;
+        coderInfo->groups.len[0] = 1;
+        return;
+    }
+
+    fastmin = ((maxsfb - MINSFB) * 3) >> 2;
+
+#if 0
+    coderInfo->groups.n = 1;
+    coderInfo->groups.len[0] = 8;
+    return;
+#endif
+
+#if PRINTSTAT
+    frames++;
+#endif
+    calce(xr, coderInfo->sfb_offset, e, maxsfb);
+    resete(min, max, e, maxsfb);
+    win0 = 0;
+    coderInfo->groups.n = 0;
+    for (win = 1; win < MAX_SHORT_WINDOWS; win++)
+    {
+        int fast = 0;
+
+        calce(xr + win * BLOCK_LEN_SHORT, coderInfo->sfb_offset, e, maxsfb);
+        for (sfb = MINSFB; sfb < maxsfb; sfb++)
+        {
+            if (min[sfb] > e[sfb])
+                min[sfb] = e[sfb];
+            if (max[sfb] < e[sfb])
+                max[sfb] = e[sfb];
+
+            if (max[sfb] > thr * min[sfb])
+                fast++;
+        }
+        if (fast > fastmin)
+        {
+            coderInfo->groups.len[coderInfo->groups.n++] = win - win0;
+            win0 = win;
+            resete(min, max, e, maxsfb);
+        }
+    }
+    coderInfo->groups.len[coderInfo->groups.n++] = win - win0;
+#if PRINTSTAT
+    groups += coderInfo->groups.n;
+#endif
+}
+
+void BlocStat(void)
+{
+#if PRINTSTAT
+    printf("frames:%d; groups:%d; g/f:%f\n", frames, groups, (double)groups/frames);
+#endif
 }
--- a/libfaac/quantize.h
+++ b/libfaac/quantize.h
@@ -21,10 +21,29 @@
 #ifndef QUANTIZE_H
 #define QUANTIZE_H
 
-#include "aacquant.h"
 #include "coder.h"
 
-int BlocQuant(CoderInfo *coderInfo, double *xr, int *xi, AACQuantCfg *aacquantCfg);
+typedef struct
+{
+    //double *pow43;
+    double quality;
+    int max_cbl;
+    int max_cbs;
+} AACQuantCfg;
+
+#include "quantize.h"
+
+enum {
+    DEFQUAL = 100,
+    MAXQUAL = 5000,
+    MAXQUALADTS = MAXQUAL,
+    MINQUAL = 10,
+    SF_OFFSET = 100,
+};
+
+int BlocQuant(CoderInfo *coderInfo, double *xr, AACQuantCfg *aacquantCfg);
 void BandLimit(unsigned *bw, int rate, SR_INFO *sr, AACQuantCfg *aacquantCfg);
+void BlocGroup(double *xr, CoderInfo *coderInfo, int maxsfb);
+void BlocStat(void);
 
 #endif