shithub: aacenc

Download patch

ref: 29fe1278dc4e8f4700282ca67bf1c6e4237e4a94
parent: 31a27a38271fdff180f07c621fde650cb31977bd
author: Krzysztof Nikiel <knik@users.sourceforge.net>
date: Fri Oct 20 08:37:01 EDT 2017

rewritten mid/side coding

--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+	* rewritten mid/side coding
+	* fixed bug in blockswitch
 1.29.8
 	* changed default mode to ABR 64kbps/channel
 	* implemented short windows grouping
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -157,7 +157,7 @@
 
     if (config->bitRate && !config->bandWidth)
     {
-        config->bandWidth = (double)config->bitRate * hEncoder->sampleRate * g_bw.fac / 60000.0;
+        config->bandWidth = (double)config->bitRate * hEncoder->sampleRate * g_bw.fac / 50000.0;
         if (config->bandWidth > g_bw.freq)
             config->bandWidth = g_bw.freq;
 
@@ -520,8 +520,6 @@
         if (coderInfo[channel].block_type == ONLY_SHORT_WINDOW) {
             coderInfo[channel].sfbn = hEncoder->aacquantCfg.max_cbs;
 
-            BlocGroup(hEncoder->freqBuff[channel], coderInfo + channel, hEncoder->aacquantCfg.max_cbs);
-
             offset = 0;
             for (sb = 0; sb < coderInfo[channel].sfbn; sb++) {
                 coderInfo[channel].sfb_offset[sb] = offset;
@@ -528,6 +526,7 @@
                 offset += hEncoder->srInfo->cb_width_short[sb];
             }
             coderInfo[channel].sfb_offset[sb] = offset;
+            BlocGroup(hEncoder->freqBuff[channel], coderInfo + channel, hEncoder->aacquantCfg.max_cbs);
         } else {
             coderInfo[channel].sfbn = hEncoder->aacquantCfg.max_cbl;
 
@@ -565,7 +564,12 @@
 		}
 	}
 
-    MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels, allowMidside);
+    if (allowMidside)
+        MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels,
+                 (double)hEncoder->aacquantCfg.quality/DEFQUAL);
+    else
+        MSEncode(coderInfo, channelInfo, hEncoder->freqBuff, numChannels,
+                 0.0);
 
 #ifdef DRM
     /* loop the quantization until the desired bit-rate is reached */
--- a/libfaac/midside.c
+++ b/libfaac/midside.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: midside.c,v 1.1 2003/06/26 19:39:54 knik Exp $
  */
 
 #include <math.h>
@@ -24,99 +23,162 @@
 #include "util.h"
 
 
-void MSEncode(CoderInfo *coderInfo,
-	      ChannelInfo *channelInfo,
-	      double *spectrum[MAX_CHANNELS],
-	      int maxchan,
-	      int allowms)
+static void midside(CoderInfo *coder, ChannelInfo *channel,
+                    double *sl0, double *sr0, int *mscnt,
+                    int wstart, int wend,
+                    double mutethr
+                   )
 {
-  int chn;
+    int sfb;
+    int win;
 
-  // doesn't work with the new windows grouping code
-  return;
-
-  for (chn = 0; chn < maxchan; chn++)
-  {
-    if (channelInfo[chn].present)
+    for (sfb = 0; sfb < coder->sfbn; sfb++)
     {
-      if ((channelInfo[chn].cpe) && (channelInfo[chn].ch_is_left))
-      {
-	int rch = channelInfo[chn].paired_ch;
+        int ms = 0;
+        int l, start, end;
+        double sum, diff;
+        double enrgs, enrgd, enrgl, enrgr;
+        double maxs, maxd, maxl, maxr;
 
-	channelInfo[chn].msInfo.is_present = 0;
-	channelInfo[rch].msInfo.is_present = 0;
+        start = coder->sfb_offset[sfb];
+        end = coder->sfb_offset[sfb + 1];
 
-	/* Perform MS if block_types are the same */
-	if ((coderInfo[chn].block_type == coderInfo[rch].block_type)
-	    && allowms)
-	{
-            int nsfb = coderInfo[chn].sfbn;
-	  MSInfo *msInfoL = &(channelInfo[chn].msInfo);
-	  MSInfo *msInfoR = &(channelInfo[rch].msInfo);
-	  int sfb;
+        enrgs = enrgd = enrgl = enrgr = 0.0;
+        maxs = maxd = maxl = maxr = 0.0;
+        for (win = wstart; win < wend; win++)
+        {
+            double *sl = sl0 + win * BLOCK_LEN_SHORT;
+            double *sr = sr0 + win * BLOCK_LEN_SHORT;
 
-	  channelInfo[chn].common_window = 1;  /* Use common window */
-	  channelInfo[chn].msInfo.is_present = 1;
-	  channelInfo[rch].msInfo.is_present = 1;
+            for (l = start; l < end; l++)
+            {
+                double lx = sl[l];
+                double rx = sr[l];
 
-	  for (sfb = 0; sfb < nsfb; sfb++)
-	  {
-            int ms = 0;
-	    int l, start, end;
-	    double sum, diff;
-            double enrgs, enrgd, enrgl, enrgr;
-	    double maxs, maxd, maxl, maxr;
+                sum = 0.5 * (lx + rx);
+                diff = 0.5 * (lx - rx);
 
-	    start = coderInfo[chn].sfb_offset[sfb];
-            end = coderInfo[chn].sfb_offset[sfb + 1];
+                enrgs += sum * sum;
+                maxs = max(maxs, fabs(sum));
 
-            enrgs = enrgd = enrgl = enrgr = 0.0;
-	    maxs = maxd = maxl = maxr = 0.0;
-	    for (l = start; l < end; l++)
-	    {
-              double lx = spectrum[chn][l];
-	      double rx = spectrum[rch][l];
+                enrgd += diff * diff;
+                maxd = max(maxd, fabs(diff));
 
-	      sum = 0.5 * (lx + rx);
-	      diff = 0.5 * (lx - rx);
+                enrgl += lx * lx;
+                enrgr += rx * rx;
 
-	      enrgs += sum * sum;
-	      maxs = max(maxs, fabs(sum));
+                maxl = max(maxl, fabs(lx));
+                maxr = max(maxr, fabs(rx));
+            }
+        }
 
-	      enrgd += diff * diff;
-	      maxd = max(maxd, fabs(diff));
+        if (min(enrgs, enrgd) < mutethr * max(enrgs, enrgd))
+        {
+            ms = 1;
+            for (win = wstart; win < wend; win++)
+            {
+                double *sl = sl0 + win * BLOCK_LEN_SHORT;
+                double *sr = sr0 + win * BLOCK_LEN_SHORT;
+                for (l = start; l < end; l++)
+                {
+                    sum = sl[l] + sr[l];
+                    diff = sl[l] - sr[l];
+                    if (enrgs < enrgd)
+                        sum = 0.0;
+                    else
+                        diff = 0.0;
+                    sl[l] = 0.5 * sum;
+                    sr[l] = 0.5 * diff;
+                }
+            }
+        }
+        if (min(enrgl, enrgr) < mutethr * max(enrgl, enrgr))
+        {
+            for (win = wstart; win < wend; win++)
+            {
+                double *sl = sl0 + win * BLOCK_LEN_SHORT;
+                double *sr = sr0 + win * BLOCK_LEN_SHORT;
+                for (l = start; l < end; l++)
+                {
+                    if (enrgl < enrgr)
+                        sl[l] = 0.0;
+                    else
+                        sr[l] = 0.0;
+                }
+            }
+        }
 
-	      enrgl += lx * lx;
-	      enrgr += rx * rx;
+        channel->msInfo.ms_used[*mscnt] = ms;
+        (*mscnt)++;
+    }
+}
 
-              maxl = max(maxl, fabs(lx));
-              maxr = max(maxr, fabs(rx));
-	    }
 
-#if 1
-	    if ((min(enrgs, enrgd) < min(enrgl, enrgr))
-		&& (min(maxs, maxd) < min(maxl, maxr)))
-	      ms = 1;
-#else
-	    if (min(enrgs, enrgd) < min(enrgl, enrgr))
-	      ms = 1;
-#endif
+void MSEncode(CoderInfo *coder,
+              ChannelInfo *channel,
+              double *s[MAX_CHANNELS],
+              int maxchan,
+              double quality)
+{
+    int chn;
+    int usems;
+    double mutethr;
+    static const double thr075 = 0.09; /* ~0.75dB */
+    static const double thrmax = 0.25; /* ~2dB */
 
-	    //printf("%d:%d\n", sfb, ms);
+    if (quality > 0.01)
+    {
+        usems = 1;
+        mutethr = thr075 / quality;
+        if (mutethr > thrmax)
+            mutethr = thrmax;
+    }
+    else
+    {
+        usems = 0;
+        mutethr = 0.0;
+    }
 
-	    msInfoR->ms_used[sfb] = msInfoL->ms_used[sfb] = ms;
+    for (chn = 0; chn < maxchan; chn++)
+    {
+        int rch;
+        int cnt;
+        int group;
+        int mscnt = 0;
+        int start = 0;
 
-	    if (ms)
-	      for (l = start; l < end; l++)
-	      {
-		sum = spectrum[chn][l] + spectrum[rch][l];
-		diff = spectrum[chn][l] - spectrum[rch][l];
-		spectrum[chn][l] = 0.5 * sum;
-		spectrum[rch][l] = 0.5 * diff;
-	      }
-	  }
-	}
-      }
+        if (!channel[chn].present)
+            continue;
+        if (!((channel[chn].cpe) && (channel[chn].ch_is_left)))
+            continue;
+
+        rch = channel[chn].paired_ch;
+
+        channel[chn].msInfo.is_present = 0;
+        channel[rch].msInfo.is_present = 0;
+
+        if (!usems)
+            continue;
+
+        if (coder[chn].block_type != coder[rch].block_type)
+            continue;
+        if (coder[chn].groups.n != coder[rch].groups.n)
+            continue;
+        for (cnt = 0; cnt < coder[chn].groups.n; cnt++)
+            if (coder[chn].groups.len[cnt] != coder[rch].groups.len[cnt])
+                goto skip;
+
+        channel[chn].common_window = 1;
+        channel[chn].msInfo.is_present = 1;
+        channel[rch].msInfo.is_present = 1;
+
+        for (group = 0; group < coder->groups.n; group++)
+        {
+            int end = start + coder->groups.len[group];
+            midside(coder + chn, channel + chn, s[chn], s[rch], &mscnt,
+                    start, end, mutethr);
+            start = end;
+        }
+        skip:;
     }
-  }
 }
--- a/libfaac/midside.h
+++ b/libfaac/midside.h
@@ -30,7 +30,7 @@
 
 
 void MSEncode(CoderInfo *coderInfo, ChannelInfo *channelInfo, double *spectrum[MAX_CHANNELS],
-              unsigned int numberOfChannels, unsigned int msenable);
+              unsigned int numberOfChannels, double quality);
 
 #ifdef __cplusplus
 }