📄 psych.c
字号:
epartM = psyInfoL->energyMS[low];
npartM = nb_tmpM[low];
epartS = psyInfoR->energyMS[low];
npartS = nb_tmpS[low];
for (w = low+1; w < high; w++)
{
epartM += psyInfoL->energyMS[w];
epartS += psyInfoR->energyMS[w];
if (nb_tmpM[w] < npartM)
npartM = nb_tmpM[w];
if (nb_tmpS[w] < npartS)
npartS = nb_tmpS[w];
}
npartM *= cb_width_long[b];
npartS *= cb_width_long[b];
psyInfoL->maskThrMS[b] = psyInfoL->maskThrNextMS[b];
psyInfoR->maskThrMS[b] = psyInfoR->maskThrNextMS[b];
psyInfoL->maskEnMS[b] = psyInfoL->maskEnNextMS[b];
psyInfoR->maskEnMS[b] = psyInfoR->maskEnNextMS[b];
psyInfoL->maskThrNextMS[b] = npartM;
psyInfoR->maskThrNextMS[b] = npartS;
psyInfoL->maskEnNextMS[b] = epartM;
psyInfoR->maskEnNextMS[b] = epartS;
{
double thmL = psyInfoL->maskThr[b];
double thmR = psyInfoR->maskThr[b];
double thmM = psyInfoL->maskThrMS[b];
double thmS = psyInfoR->maskThrMS[b];
double msfix = 3.5;
if (thmL*msfix < (thmM+thmS)/2) {
double f = thmL*msfix / ((thmM+thmS)/2);
thmM *= f;
thmS *= f;
}
if (thmR*msfix < (thmM+thmS)/2) {
double f = thmR*msfix / ((thmM+thmS)/2);
thmM *= f;
thmS *= f;
}
psyInfoL->maskThrMS[b] = min(thmM,psyInfoL->maskThrMS[b]);
psyInfoR->maskThrMS[b] = min(thmS,psyInfoR->maskThrMS[b]);
if (psyInfoL->maskThr[b] * psyInfoR->maskThr[b] < psyInfoL->maskThrMS[b] * psyInfoR->maskThrMS[b])
channelInfoL->msInfo.ms_used[b] = 0;
else
channelInfoL->msInfo.ms_used[b] = 1;
}
}
#ifdef _DEBUG
printf("MSL:%3d ", ms_used);
#endif
/* Short windows */
for (j = 0; j < 8; j++)
{
/* Energy in each partition and weighted unpredictability */
high = 0;
for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
double ebM, ebS;
low = high;
high += gpsyInfo->psyPartS->width[b];
ebM = psyInfoL->energySMS[j][low];
ebS = psyInfoR->energySMS[j][low];
for (w = low+1; w < high; w++)
{
ebM += psyInfoL->energySMS[j][w];
ebS += psyInfoR->energySMS[j][w];
}
eM[b] = ebM;
eS[b] = ebS;
}
/* Convolve the partitioned energy and unpredictability
with the spreading function */
for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
/* Mid channel */
/* Get power ratio */
ecb = 0;
for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
{
ecb += gpsyInfo->spreadingS[b][bb] * eM[bb];
}
/* Actual energy threshold */
nbM[b] = max(1e-6, ecb);
/*
nbM[b] = max(nbM[b], gpsyInfo->athS[b]);
*/
/* Side channel */
/* Get power ratio */
ecb = 0;
for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
{
ecb += gpsyInfo->spreadingS[b][bb] * eS[bb];
}
/* Actual energy threshold */
nbS[b] = max(1e-6, ecb);
/*
nbS[b] = max(nbS[b], gpsyInfo->athS[b]);
*/
if (psyInfoL->nbS[j][b] <= 1.58*psyInfoR->nbS[j][b]
&& psyInfoR->nbS[j][b] <= 1.58*psyInfoL->nbS[j][b]) {
mld = gpsyInfo->mldS[b]*eM[b];
tmp1 = max(nbM[b], min(nbS[b],mld));
mld = gpsyInfo->mldS[b]*eS[b];
tmp2 = max(nbS[b], min(nbM[b],mld));
nbM[b] = tmp1;
nbS[b] = tmp2;
}
}
high = 0;
for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
low = high;
high += gpsyInfo->psyPartS->width[b];
for (w = low; w < high; w++)
{
nb_tmpM[w] = nbM[b] / gpsyInfo->psyPartS->width[b];
nb_tmpS[w] = nbS[b] / gpsyInfo->psyPartS->width[b];
}
}
high = 0;
for (b = 0; b < num_cb_short; b++)
{
low = high;
high += cb_width_short[b];
epartM = psyInfoL->energySMS[j][low];
epartS = psyInfoR->energySMS[j][low];
npartM = nb_tmpM[low];
npartS = nb_tmpS[low];
for (w = low+1; w < high; w++)
{
epartM += psyInfoL->energySMS[j][w];
epartS += psyInfoR->energySMS[j][w];
if (nb_tmpM[w] < npartM)
npartM = nb_tmpM[w];
if (nb_tmpS[w] < npartS)
npartS = nb_tmpS[w];
}
npartM *= cb_width_short[b];
npartS *= cb_width_short[b];
psyInfoL->maskThrSMS[j][b] = psyInfoL->maskThrNextSMS[j][b];
psyInfoR->maskThrSMS[j][b] = psyInfoR->maskThrNextSMS[j][b];
psyInfoL->maskEnSMS[j][b] = psyInfoL->maskEnNextSMS[j][b];
psyInfoR->maskEnSMS[j][b] = psyInfoR->maskEnNextSMS[j][b];
psyInfoL->maskThrNextSMS[j][b] = npartM;
psyInfoR->maskThrNextSMS[j][b] = npartS;
psyInfoL->maskEnNextSMS[j][b] = epartM;
psyInfoR->maskEnNextSMS[j][b] = epartS;
{
double thmL = psyInfoL->maskThrS[j][b];
double thmR = psyInfoR->maskThrS[j][b];
double thmM = psyInfoL->maskThrSMS[j][b];
double thmS = psyInfoR->maskThrSMS[j][b];
double msfix = 3.5;
if (thmL*msfix < (thmM+thmS)/2) {
double f = thmL*msfix / ((thmM+thmS)/2);
thmM *= f;
thmS *= f;
}
if (thmR*msfix < (thmM+thmS)/2) {
double f = thmR*msfix / ((thmM+thmS)/2);
thmM *= f;
thmS *= f;
}
psyInfoL->maskThrSMS[j][b] = min(thmM,psyInfoL->maskThrSMS[j][b]);
psyInfoR->maskThrSMS[j][b] = min(thmS,psyInfoR->maskThrSMS[j][b]);
if (psyInfoL->maskThrS[j][b] * psyInfoR->maskThrS[j][b] <
psyInfoL->maskThrSMS[j][b] * psyInfoR->maskThrSMS[j][b])
channelInfoL->msInfo.ms_usedS[j][b] = 0;
else
channelInfoL->msInfo.ms_usedS[j][b] = 1;
}
}
}
#ifdef _DEBUG
printf("MSS:%3d ", ms_usedS);
#endif
}
void BlockSwitch(CoderInfo *coderInfo, PsyInfo *psyInfo, unsigned int numChannels)
{
unsigned int channel;
int desire = ONLY_LONG_WINDOW;
/* Use the same block type for all channels
If there is 1 channel that wants a short block,
use a short block on all channels.
*/
for (channel = 0; channel < numChannels; channel++)
{
if (psyInfo[channel].block_type == ONLY_SHORT_WINDOW)
desire = ONLY_SHORT_WINDOW;
}
for (channel = 0; channel < numChannels; channel++)
{
if ((coderInfo[channel].block_type == ONLY_SHORT_WINDOW) ||
(coderInfo[channel].block_type == LONG_SHORT_WINDOW) ) {
if ((coderInfo[channel].desired_block_type==ONLY_LONG_WINDOW) &&
(desire == ONLY_LONG_WINDOW) ) {
coderInfo[channel].block_type = SHORT_LONG_WINDOW;
} else {
coderInfo[channel].block_type = ONLY_SHORT_WINDOW;
}
} else if (desire == ONLY_SHORT_WINDOW) {
coderInfo[channel].block_type = LONG_SHORT_WINDOW;
} else {
coderInfo[channel].block_type = ONLY_LONG_WINDOW;
}
coderInfo[channel].desired_block_type = desire;
}
#ifdef _DEBUG
printf("%s ", (coderInfo[0].block_type == ONLY_SHORT_WINDOW) ? "SHORT" : "LONG ");
#endif
}
static double freq2bark(double freq)
{
double bark;
if(freq > 200.0)
bark = 26.81 / (1 + (1960 / freq)) - 0.53;
else
bark = freq / 102.9;
return (bark);
}
static double ATHformula(double f)
{
double ath;
f /= 1000; /* convert to khz */
f = max(0.01, f);
f = min(18.0,f);
/* from Painter & Spanias, 1997 */
/* modified by Gabriel Bouvigne to better fit to the reality */
ath = 3.640 * pow(f,-0.8)
- 6.800 * exp(-0.6*pow(f-3.4,2.0))
+ 6.000 * exp(-0.15*pow(f-8.7,2.0))
+ 0.6* 0.001 * pow(f,4.0);
return ath;
}
static PsyPartTable psyPartTableLong[12+1] =
{
{ 96000, 71,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,10,10,11,12,13,14,15,16,
18,19,21,24,26,30,34,39,45,53,64,78,98,127,113
}
},
{ 88200, 72,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,4,4,4,4,5,5,5,6,6,7,7,8,8,9,10,10,11,12,13,14,15,
16,18,19,21,23,26,29,32,37,42,49,58,69,85,106,137,35
}
},
{ 64000, 67,
{ /* width */
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,
4,4,4,4,5,5,5,6,6,7,7,8,8,9,10,10,11,12,13,14,15,16,17,
18,20,21,23,25,28,30,34,37,42,47,54,63,73,87,105,57
}
},
{ 48000, 69,
{ /* width */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 12,
13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 28, 31, 34, 37, 40, 45, 50,
56, 63, 72, 84, 86
}
},
{ 44100, 70,
{ /* width */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 28, 30, 33, 36, 39,
43, 47, 53, 59, 67, 76, 88, 27
}
},
{ 32000, 66,
{ /* width */
3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,4,4,4,
4,4,4,4,5,5,5,5,6,6,6,
7,7,8,8,9,10,10,11,12,13,14,
15,16,17,19,20,22,23,25,27,29,31,
33,35,38,41,45,48,53,58,64,71,62
}
},
{ 24000, 66,
{ /* width */
3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,6,6,6,6,7,7,
7,8,8,9,9,10,11,12,12,13,14,
15,17,18,19,21,22,24,26,28,30,32,
34,37,39,42,45,49,53,57,62,67,34
}
},
{ 22050, 63,
{ /* width */
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17,
19, 20, 22, 23, 25, 27, 29, 31, 33, 36, 38, 41, 44, 47, 51, 55, 59,
64, 61
}
},
{ 16000, 60,
{ /* width */
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,6,6,6,6,6,
6,6,7,7,7,7,8,8,8,9,
9,10,10,11,11,12,13,14,15,16,
17,18,19,21,22,24,26,28,30,33,
35,38,41,44,47,50,54,58,62,58
}
},
{ 12000, 57,
{ /* width */
6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,
8,8,8,8,8,9,9,9,10,10,11,11,12,12,13,13,
14,15,16,17,18,19,20,22,23,25,27,29,31,
34,36,39,42,45,49,53,57,61,58
}
},
{ 11025, 56,
{ /* width */
7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,
9,9,9,9,10,10,10,11,11,12,12,13,13,14,15,16,17,18,19,20,
21,23,24,26,28,30,33,35,38,41,44,48,51,55,59,64,9
}
},
{ 8000, 52,
{ /* width */
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11,
12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 23, 24,
26, 27, 29, 31, 33, 36, 38, 41, 44, 48, 52, 56, 60, 14
}
},
{ -1 }
};
static PsyPartTable psyPartTableShort[12+1] =
{
{ 96000, 36,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,4,4,5,5,
6,7,9,11,14,18,7
}
},
{ 88200, 37,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,4,4,
5,5,6,7,8,10,12,16,1
}
},
{ 64000, 39,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,4,4,4,
5,5,6,7,8,9,11,13,10
}
},
{ 48000, 42,
{ /* width */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 12, 1
}
},
{ 44100, 42,
{ /* width */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 12
}
},
{ 32000, 44,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,6,6,7,8,8,9,8
}
},
{ 24000, 46,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,1
}
},
{ 22050, 46,
{ /* width */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 7
}
},
{ 16000, 47,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,7
}
},
{ 12000, 48,
{ /* width */
1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,2,2,2,2,2,
2,2,2,2,2,2,3,3,3,3,3,4,
4,4,5,5,5,6,6,7,7,8,8,3
}
},
{ 11025, 47,
{ /* width */
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,2,2,
2,2,2,2,2,2,2,2,2,3,
3,3,3,3,4,4,4,4,5,5,
5,6,6,7,7,8,8
}
},
{ 8000, 40,
{ /* width */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 3
}
},
{ -1 }
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -