1 Star 0 Fork 2

maimos/libfaac

forked from Fred/libfaac 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
stereo.c 9.84 KB
一键复制 编辑 原始数据 按行查看 历史
Fred 提交于 2019-11-26 14:55 . new repo
/****************************************************************************
Intensity Stereo
Copyright (C) 2017 Krzysztof Nikiel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <math.h>
#include "stereo.h"
#include "huff2.h"
static void stereo(CoderInfo *cl, CoderInfo *cr,
double *sl0, double *sr0, int *sfcnt,
int wstart, int wend, double phthr
)
{
int sfb;
int win;
int sfmin;
if (!phthr)
return;
phthr = 1.0 / phthr;
if (cl->block_type == ONLY_SHORT_WINDOW)
sfmin = 1;
else
sfmin = 8;
(*sfcnt) += sfmin;
for (sfb = sfmin; sfb < cl->sfbn; sfb++)
{
int l, start, end;
double sum, diff;
double enrgs, enrgd, enrgl, enrgr;
int hcb = HCB_NONE;
const double step = 10/1.50515;
double ethr;
double vfix, efix;
start = cl->sfb_offset[sfb];
end = cl->sfb_offset[sfb + 1];
enrgs = enrgd = enrgl = enrgr = 0.0;
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++)
{
double lx = sl[l];
double rx = sr[l];
sum = lx + rx;
diff = lx - rx;
enrgs += sum * sum;
enrgd += diff * diff;
enrgl += lx * lx;
enrgr += rx * rx;
}
}
ethr = sqrt(enrgl) + sqrt(enrgr);
ethr *= ethr;
ethr *= phthr;
efix = enrgl + enrgr;
if (enrgs >= ethr)
{
hcb = HCB_INTENSITY;
vfix = sqrt(efix / enrgs);
}
else if (enrgd >= ethr)
{
hcb = HCB_INTENSITY2;
vfix = sqrt(efix / enrgd);
}
if (hcb != HCB_NONE)
{
int sf = lrint(log10(enrgl / efix) * step);
int pan = lrint(log10(enrgr/efix) * step) - sf;
if (pan > 30)
{
cl->book[*sfcnt] = HCB_ZERO;
(*sfcnt)++;
continue;
}
if (pan < -30)
{
cr->book[*sfcnt] = HCB_ZERO;
(*sfcnt)++;
continue;
}
cl->sf[*sfcnt] = sf;
cr->sf[*sfcnt] = -pan;
cr->book[*sfcnt] = hcb;
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 (hcb == HCB_INTENSITY)
sum = sl[l] + sr[l];
else
sum = sl[l] - sr[l];
sl[l] = sum * vfix;
}
}
}
(*sfcnt)++;
}
}
static void midside(CoderInfo *coder, ChannelInfo *channel,
double *sl0, double *sr0, int *sfcnt,
int wstart, int wend,
double thrmid, double thrside
)
{
int sfb;
int win;
int sfmin;
if (coder->block_type == ONLY_SHORT_WINDOW)
sfmin = 1;
else
sfmin = 8;
for (sfb = 0; sfb < sfmin; sfb++)
{
channel->msInfo.ms_used[*sfcnt] = 0;
(*sfcnt)++;
}
for (sfb = sfmin; sfb < coder->sfbn; sfb++)
{
int ms = 0;
int l, start, end;
double sum, diff;
double enrgs, enrgd, enrgl, enrgr;
start = coder->sfb_offset[sfb];
end = coder->sfb_offset[sfb + 1];
enrgs = enrgd = enrgl = enrgr = 0.0;
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++)
{
double lx = sl[l];
double rx = sr[l];
sum = 0.5 * (lx + rx);
diff = 0.5 * (lx - rx);
enrgs += sum * sum;
enrgd += diff * diff;
enrgl += lx * lx;
enrgr += rx * rx;
}
}
if ((min(enrgl, enrgr) * thrmid) >= max(enrgs, enrgd))
{
enum {PH_NONE, PH_IN, PH_OUT};
int phase = PH_NONE;
if ((enrgs * thrmid * 2.0) >= (enrgl + enrgr))
{
ms = 1;
phase = PH_IN;
}
else if ((enrgd * thrmid * 2.0) >= (enrgl + enrgr))
{
ms = 1;
phase = PH_OUT;
}
if (ms)
{
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 (phase == PH_IN)
{
sum = sl[l] + sr[l];
diff = 0;
}
else
{
sum = 0;
diff = sl[l] - sr[l];
}
sl[l] = 0.5 * sum;
sr[l] = 0.5 * diff;
}
}
}
}
if (min(enrgl, enrgr) <= (thrside * 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;
}
}
}
channel->msInfo.ms_used[*sfcnt] = ms;
(*sfcnt)++;
}
}
void AACstereo(CoderInfo *coder,
ChannelInfo *channel,
double *s[MAX_CHANNELS],
int maxchan,
double quality,
int mode
)
{
int chn;
static const double thr075 = 1.09 /* ~0.75dB */ - 1.0;
static const double thrmax = 1.25 /* ~2dB */ - 1.0;
static const double sidemin = 0.1; /* -20dB */
static const double sidemax = 0.3; /* ~-10.5dB */
static const double isthrmax = M_SQRT2 - 1.0;
double thrmid, thrside;
double isthr;
thrmid = 1.0;
thrside = 0.0;
isthr = 1.0;
switch (mode)
{
case JOINT_MS:
thrmid = thr075 / quality;
if (thrmid > thrmax)
thrmid = thrmax;
thrside = sidemin / quality;
if (thrside > sidemax)
thrside = sidemax;
thrmid += 1.0;
break;
case JOINT_IS:
isthr = 0.18 / (quality * quality);
if (isthr > isthrmax)
isthr = isthrmax;
isthr += 1.0;
break;
}
// convert into energy
thrmid *= thrmid;
thrside *= thrside;
isthr *= isthr;
for (chn = 0; chn < maxchan; chn++)
{
int group;
int bookcnt = 0;
CoderInfo *cp = coder + chn;
if (!channel[chn].present)
continue;
for (group = 0; group < cp->groups.n; group++)
{
int band;
for (band = 0; band < cp->sfbn; band++)
{
cp->book[bookcnt] = HCB_NONE;
cp->sf[bookcnt] = 0;
bookcnt++;
}
}
}
for (chn = 0; chn < maxchan; chn++)
{
int rch;
int cnt;
int group;
int sfcnt = 0;
int start = 0;
if (!channel[chn].present)
continue;
if (!((channel[chn].cpe) && (channel[chn].ch_is_left)))
continue;
rch = channel[chn].paired_ch;
channel[chn].common_window = 0;
channel[chn].msInfo.is_present = 0;
channel[rch].msInfo.is_present = 0;
if (coder[chn].block_type != coder[rch].block_type)
continue;
if (coder[chn].groups.n != coder[rch].groups.n)
continue;
channel[chn].common_window = 1;
for (cnt = 0; cnt < coder[chn].groups.n; cnt++)
if (coder[chn].groups.len[cnt] != coder[rch].groups.len[cnt])
{
channel[chn].common_window = 0;
goto skip;
}
if (mode == JOINT_MS)
{
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];
switch(mode) {
case JOINT_MS:
midside(coder + chn, channel + chn, s[chn], s[rch], &sfcnt,
start, end, thrmid, thrside);
break;
case JOINT_IS:
stereo(coder + chn, coder + rch, s[chn], s[rch], &sfcnt, start, end, isthr);
break;
}
start = end;
}
skip:;
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/maimos/libfaac.git
git@gitee.com:maimos/libfaac.git
maimos
libfaac
libfaac
master

搜索帮助