170 lines
4.3 KiB
C
170 lines
4.3 KiB
C
/*
|
|
* 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|