shithub: aacenc

Download patch

ref: fa96363e8c8f9bf62e03d46101476c01afde38f2
parent: 41ce7b3b0b8f6939074eadfe90405d5f32e782eb
author: knik <knik>
date: Thu Jun 26 15:39:54 EDT 2003

new Mid/Side control

--- /dev/null
+++ b/libfaac/midside.c
@@ -1,0 +1,169 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * 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>
+#include "channels.h"
+#include "util.h"
+
+
+void MSEncode(CoderInfo *coderInfo,
+	      ChannelInfo *channelInfo,
+	      double *spectrum[MAX_CHANNELS],
+	      int maxchan,
+	      int allowms)
+{
+  int chn;
+
+  for (chn = 0; chn < maxchan; chn++)
+  {
+    if (channelInfo[chn].present)
+    {
+      if ((channelInfo[chn].cpe) && (channelInfo[chn].ch_is_left))
+      {
+	int rch = channelInfo[chn].paired_ch;
+
+	channelInfo[chn].msInfo.is_present = 0;
+	channelInfo[rch].msInfo.is_present = 0;
+
+	/* Perform MS if block_types are the same */
+	if ((coderInfo[chn].block_type == coderInfo[rch].block_type)
+	    && allowms)
+	{
+	  int nsfb = coderInfo[chn].nr_of_sfb;
+	  MSInfo *msInfoL = &(channelInfo[chn].msInfo);
+	  MSInfo *msInfoR = &(channelInfo[rch].msInfo);
+	  int sfb;
+
+	  channelInfo[chn].common_window = 1;  /* Use common window */
+	  channelInfo[chn].msInfo.is_present = 1;
+	  channelInfo[rch].msInfo.is_present = 1;
+
+          // make the same reference energy in both channels
+	  coderInfo[chn].avgenrg = coderInfo[rch].avgenrg =
+	    0.5 * (coderInfo[chn].avgenrg + coderInfo[rch].avgenrg);
+
+	  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;
+
+	    start = coderInfo[chn].sfb_offset[sfb];
+            end = coderInfo[chn].sfb_offset[sfb + 1];
+
+            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];
+
+	      sum = 0.5 * (lx + rx);
+	      diff = 0.5 * (lx - rx);
+
+	      enrgs += sum * sum;
+	      maxs = max(maxs, fabs(sum));
+
+	      enrgd += diff * diff;
+	      maxd = max(maxd, fabs(diff));
+
+	      enrgl += lx * lx;
+	      enrgr += rx * rx;
+
+              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
+
+	    //printf("%d:%d\n", sfb, ms);
+
+	    msInfoR->ms_used[sfb] = msInfoL->ms_used[sfb] = ms;
+
+	    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;
+	      }
+	  }
+	}
+      }
+    }
+  }
+}
+
+void MSReconstruct(CoderInfo *coderInfo,
+		   ChannelInfo *channelInfo,
+		   int maxchan)
+{
+  int chn;
+
+  for (chn = 0; chn < maxchan; chn++)
+  {
+    if (channelInfo[chn].present)
+    {
+      if (channelInfo[chn].cpe && channelInfo[chn].ch_is_left)
+      {
+	int rch = channelInfo[chn].paired_ch;
+
+	MSInfo *msInfoL = &(channelInfo[chn].msInfo);
+
+	if (msInfoL->is_present) {
+	  int nsfb = coderInfo[chn].nr_of_sfb;
+	  int sfb;
+
+	  for (sfb = 0; sfb < nsfb; sfb++)
+	  {
+	    int l, start, end;
+
+	    start = coderInfo[chn].sfb_offset[sfb];
+	    end = coderInfo[chn].sfb_offset[sfb + 1];
+
+	    if (msInfoL->ms_used[sfb])
+	    {
+	      for (l = start; l < end; l++)
+	      {
+		double sum, diff;
+
+		sum = coderInfo[chn].requantFreq[l];
+		diff = coderInfo[rch].requantFreq[l];
+		coderInfo[chn].requantFreq[l] = sum + diff;
+		coderInfo[rch].requantFreq[l] = sum - diff;
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+}