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;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}