/* * 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 #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; } } } } } } } }