ref: f3ce26d5f169d441b0a3a120c8bd8d70e0261b33
parent: 9a15358ad54891c89ed352b024b55cf0bb437084
author: menno <menno>
date: Wed Jan 31 18:40:05 EST 2001
Completely new psychoacoustic model
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: frame.c,v 1.3 2001/01/23 13:46:18 menno Exp $
+ * $Id: frame.c,v 1.4 2001/01/31 23:40:05 menno Exp $
*/
/*
@@ -97,9 +97,7 @@
/* Initialize coder functions */
PsyInit(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels,
- hEncoder->sampleRate, hEncoder->srInfo->cb_width_long,
- hEncoder->srInfo->num_cb_long, hEncoder->srInfo->cb_width_short,
- hEncoder->srInfo->num_cb_short);
+ hEncoder->sampleRate, hEncoder->sampleRateIdx);
FilterBankInit(hEncoder);
@@ -158,7 +156,7 @@
/* After 4 flush frames all samples have been encoded,
return 0 bytes written */
- if (hEncoder->flushFrame == 4)
+ if (hEncoder->flushFrame == 2)
return 0;
/* Determine the channel configuration */
@@ -169,31 +167,29 @@
if (hEncoder->sampleBuff[channel])
free(hEncoder->sampleBuff[channel]);
hEncoder->sampleBuff[channel] = hEncoder->nextSampleBuff[channel];
- hEncoder->nextSampleBuff[channel] = hEncoder->next2SampleBuff[channel];
- hEncoder->next2SampleBuff[channel] = hEncoder->next3SampleBuff[channel];
- hEncoder->next3SampleBuff[channel] = (double*)malloc(FRAME_LEN*sizeof(double));
+ hEncoder->nextSampleBuff[channel] = (double*)malloc(FRAME_LEN*sizeof(double));
if (samplesInput == 0) { /* start flushing*/
for (i = 0; i < FRAME_LEN; i++)
- hEncoder->next3SampleBuff[channel][i] = 0.0;
+ hEncoder->nextSampleBuff[channel][i] = 0.0;
} else {
for (i = 0; i < (int)(samplesInput/numChannels); i++)
- hEncoder->next3SampleBuff[channel][i] =
+ hEncoder->nextSampleBuff[channel][i] =
(double)inputBuffer[(i*numChannels)+channel];
for (i = (int)(samplesInput/numChannels); i < FRAME_LEN; i++)
- hEncoder->next3SampleBuff[channel][i] = 0.0;
+ hEncoder->nextSampleBuff[channel][i] = 0.0;
}
/* Psychoacoustics */
/* Update buffers and run FFT on new samples */
PsyBufferUpdate(&hEncoder->gpsyInfo, &hEncoder->psyInfo[channel],
- hEncoder->next3SampleBuff[channel]);
+ hEncoder->nextSampleBuff[channel]);
}
- if (hEncoder->frameNum <= 3) /* Still filling up the buffers */
+ if (hEncoder->frameNum <= 1) /* Still filling up the buffers */
return 0;
- /* Excitation pattern based psychoacoustic model */
+ /* Psychoacoustics */
PsyCalculate(channelInfo, &hEncoder->gpsyInfo, hEncoder->psyInfo,
hEncoder->srInfo->cb_width_long, hEncoder->srInfo->num_cb_long,
hEncoder->srInfo->cb_width_short,
@@ -287,7 +283,7 @@
frameBytes = CloseBitStream(bitStream);
#ifdef _DEBUG
- printf("%d\t%d\n", hEncoder->frameNum-3, frameBytes);
+ printf("%4d %4d\n", hEncoder->frameNum-1, frameBytes);
#endif
return frameBytes;
--- a/libfaac/libfaac.dsp
+++ b/libfaac/libfaac.dsp
@@ -41,7 +41,7 @@
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX- /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x413 /d "NDEBUG"
# ADD RSC /l 0x413 /d "NDEBUG"
BSC32=bscmake.exe
@@ -63,8 +63,8 @@
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x413 /d "_DEBUG"
# ADD RSC /l 0x413 /d "_DEBUG"
BSC32=bscmake.exe
--- a/libfaac/psych.c
+++ b/libfaac/psych.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: psych.c,v 1.2 2001/01/19 14:58:41 menno Exp $
+ * $Id: psych.c,v 1.3 2001/01/31 23:40:05 menno Exp $
*/
#include <stdlib.h>
@@ -27,29 +27,29 @@
#include "coder.h"
#include "fft.h"
+#define NS_INTERP(x,y,r) (pow((x),(r))*pow((y),1-(r)))
+#define SQRT2 1.41421356237309504880
void PsyInit(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, unsigned int numChannels,
- unsigned int sampleRate, int *cb_width_long, int num_cb_long,
- int *cb_width_short, int num_cb_short)
+ unsigned int sampleRate, unsigned int sampleRateIdx)
{
unsigned int channel;
int i, j, b, bb, high, low, size;
- double tmpx,tmpy,tmp,x,b1,b2;
- double bval[MAX_SCFAC_BANDS];
+ double tmpx,tmpy,tmp,x;
+ double bval[MAX_NPART], SNR;
- gpsyInfo->ath = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
+ gpsyInfo->ath = (double*)malloc(NPART_LONG*sizeof(double));
gpsyInfo->athS = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
- gpsyInfo->rnorm = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
- gpsyInfo->rnormS = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
- gpsyInfo->mld = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
+ gpsyInfo->mld = (double*)malloc(NPART_LONG*sizeof(double));
gpsyInfo->mldS = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
- gpsyInfo->hannWindow = (double*)malloc(2*BLOCK_LEN_LONG*sizeof(double));
- gpsyInfo->hannWindowS = (double*)malloc(2*BLOCK_LEN_SHORT*sizeof(double));
+ gpsyInfo->window = (double*)malloc(2*BLOCK_LEN_LONG*sizeof(double));
+ gpsyInfo->windowS = (double*)malloc(2*BLOCK_LEN_SHORT*sizeof(double));
for(i = 0; i < BLOCK_LEN_LONG*2; i++)
- gpsyInfo->hannWindow[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_LONG*2)));
+ gpsyInfo->window[i] = 0.42-0.5*cos(2*M_PI*(i+.5)/(BLOCK_LEN_LONG*2))+
+ 0.08*cos(4*M_PI*(i+.5)/(BLOCK_LEN_LONG*2));
for(i = 0; i < BLOCK_LEN_SHORT*2; i++)
- gpsyInfo->hannWindowS[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_SHORT*2)));
+ gpsyInfo->windowS[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_SHORT*2)));
gpsyInfo->sampleRate = (double)sampleRate;
size = BLOCK_LEN_LONG;
@@ -59,7 +59,8 @@
psyInfo[channel].lastPe = 0.0;
psyInfo[channel].lastEnr = 0.0;
psyInfo[channel].threeInARow = 0;
- psyInfo[channel].cw = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].tonality = (double*)malloc(NPART_LONG*sizeof(double));
+ psyInfo[channel].nb = (double*)malloc(NPART_LONG*sizeof(double));
psyInfo[channel].maskThr = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
psyInfo[channel].maskEn = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
psyInfo[channel].maskThrNext = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
@@ -71,25 +72,21 @@
psyInfo[channel].prevSamples = (double*)malloc(size*sizeof(double));
memset(psyInfo[channel].prevSamples, 0, size*sizeof(double));
- psyInfo[channel].lastNb = (double*)malloc(size*sizeof(double));
- psyInfo[channel].lastNbMS = (double*)malloc(size*sizeof(double));
- for (j = 0; j < size; j++) {
+ psyInfo[channel].lastNb = (double*)malloc(NPART_LONG*sizeof(double));
+ psyInfo[channel].lastNbMS = (double*)malloc(NPART_LONG*sizeof(double));
+ for (j = 0; j < NPART_LONG; j++) {
psyInfo[channel].lastNb[j] = 2.;
psyInfo[channel].lastNbMS[j] = 2.;
}
- psyInfo[channel].fftMagPlus2 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagPlus1 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMag = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagMin1 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagMin2 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhPlus2 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhPlus1 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPh = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhMin1 = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhMin2 = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].energy = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].energyMS = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].transBuff = (double*)malloc(2*size*sizeof(double));
}
+ gpsyInfo->psyPart = &psyPartTableLong[sampleRateIdx];
+ gpsyInfo->psyPartS = &psyPartTableShort[sampleRateIdx];
+
size = BLOCK_LEN_SHORT;
for (channel = 0; channel < numChannels; channel++) {
psyInfo[channel].sizeS = size;
@@ -98,7 +95,7 @@
memset(psyInfo[channel].prevSamplesS, 0, size*sizeof(double));
for (j = 0; j < 8; j++) {
- psyInfo[channel].cwS[j] = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].nbS[j] = (double*)malloc(NPART_SHORT*sizeof(double));
psyInfo[channel].maskThrS[j] = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
psyInfo[channel].maskEnS[j] = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
psyInfo[channel].maskThrNextS[j] = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
@@ -108,66 +105,72 @@
psyInfo[channel].maskThrNextSMS[j] = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
psyInfo[channel].maskEnNextSMS[j] = (double*)malloc(MAX_SCFAC_BANDS*sizeof(double));
- psyInfo[channel].fftMagPlus2S[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagPlus1S[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagS[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftMagMin1S[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhPlus2S[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhPlus1S[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhS[j] = (double*)malloc(size*sizeof(double));
- psyInfo[channel].fftPhMin1S[j] = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].energyS[j] = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].energySMS[j] = (double*)malloc(size*sizeof(double));
+ psyInfo[channel].transBuffS[j] = (double*)malloc(2*size*sizeof(double));
}
}
size = BLOCK_LEN_LONG;
high = 0;
- for(b = 0; b < num_cb_long; b++) {
+ for(b = 0; b < gpsyInfo->psyPart->len; b++) {
low = high;
- high += cb_width_long[b];
+ high += gpsyInfo->psyPart->width[b];
bval[b] = 0.5 * (freq2bark(gpsyInfo->sampleRate*low/(2*size)) +
freq2bark(gpsyInfo->sampleRate*(high-1)/(2*size)));
}
- for(b = 0; b < num_cb_long; b++) {
- b2 = bval[b];
- for(bb = 0; bb < num_cb_long; bb++) {
- b1 = bval[bb];
+ for(b = 0; b < gpsyInfo->psyPart->len; b++) {
+ for(bb = 0; bb < gpsyInfo->psyPart->len; bb++) {
+ if (bval[b] >= bval[bb]) tmpx = (bval[b] - bval[bb])*3.0;
+ else tmpx = (bval[b] - bval[bb])*1.5;
- if (b>=bb) tmpx = (b2 - b1)*3.0;
- else tmpx = (b2 - b1)*1.5;
-
- if(tmpx>=0.5 && tmpx<=2.5)
+ if(tmpx >= 0.5 && tmpx <= 2.5)
{
tmp = tmpx - 0.5;
x = 8.0 * (tmp*tmp - 2.0 * tmp);
- }
- else x = 0.0;
+ } else
+ x = 0.0;
+
tmpx += 0.474;
tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx);
- if (tmpy <= -100.0) gpsyInfo->spreading[b][bb] = 0.0;
+ if (tmpy < -100.0) gpsyInfo->spreading[b][bb] = 0.0;
else gpsyInfo->spreading[b][bb] = exp((x + tmpy)*0.2302585093);
}
}
+ for(b = 0; b < gpsyInfo->psyPart->len; b++) {
+ for(bb = 0; bb < gpsyInfo->psyPart->len; bb++) {
+ if (gpsyInfo->spreading[b][bb] != 0.0)
+ break;
+ }
+ gpsyInfo->sprInd[b][0] = bb;
+ for(bb = gpsyInfo->psyPart->len-1; bb > 0; bb--) {
+ if (gpsyInfo->spreading[b][bb] != 0.0)
+ break;
+ }
+ gpsyInfo->sprInd[b][1] = bb;
+ }
- for( b = 0; b < num_cb_long; b++){
+ for( b = 0; b < gpsyInfo->psyPart->len; b++){
tmp = 0.0;
- for( bb = 0; bb < num_cb_long; bb++)
- tmp += gpsyInfo->spreading[bb][b];
- gpsyInfo->rnorm[b] = 1.0/tmp;
+ for( bb = gpsyInfo->sprInd[b][0]; bb < gpsyInfo->sprInd[b][1]; bb++)
+ tmp += gpsyInfo->spreading[b][bb];
+ for( bb = gpsyInfo->sprInd[b][0]; bb < gpsyInfo->sprInd[b][1]; bb++)
+ gpsyInfo->spreading[b][bb] /= tmp;
}
j = 0;
- for( b = 0; b < num_cb_long; b++){
+ for( b = 0; b < gpsyInfo->psyPart->len; b++){
gpsyInfo->ath[b] = 1.e37;
- for (bb = 0; bb < cb_width_long[b]; bb++, j++) {
+ for (bb = 0; bb < gpsyInfo->psyPart->width[b]; bb++, j++) {
double freq = gpsyInfo->sampleRate*j/(1000.0*2*size);
double level;
level = ATHformula(freq*1000) - 20;
level = pow(10., 0.1*level);
- level *= cb_width_long[b];
+ level *= gpsyInfo->psyPart->width[b];
if (level < gpsyInfo->ath[b])
gpsyInfo->ath[b] = level;
}
@@ -174,76 +177,94 @@
}
low = 0;
- for (b = 0; b < num_cb_long; b++) {
+ for (b = 0; b < gpsyInfo->psyPart->len; b++) {
tmp = freq2bark(gpsyInfo->sampleRate*low/(2*size));
tmp = (min(tmp, 15.5)/15.5);
gpsyInfo->mld[b] = pow(10.0, 1.25*(1-cos(M_PI*tmp))-2.5);
- low += cb_width_long[b];
+ low += gpsyInfo->psyPart->width[b];
}
size = BLOCK_LEN_SHORT;
high = 0;
- for(b = 0; b < num_cb_short; b++) {
+ for(b = 0; b < gpsyInfo->psyPartS->len; b++) {
low = high;
- high += cb_width_short[b];
+ high += gpsyInfo->psyPartS->width[b];
bval[b] = 0.5 * (freq2bark(gpsyInfo->sampleRate*low/(2*size)) +
freq2bark(gpsyInfo->sampleRate*(high-1)/(2*size)));
}
- for(b = 0; b < num_cb_short; b++) {
- b2 = bval[b];
- for(bb = 0; bb < num_cb_short; bb++) {
- b1 = bval[bb];
+ for(b = 0; b < gpsyInfo->psyPartS->len; b++) {
+ for(bb = 0; bb < gpsyInfo->psyPartS->len; bb++) {
+ if (bval[b] >= bval[bb]) tmpx = (bval[b] - bval[bb])*3.0;
+ else tmpx = (bval[b] - bval[bb])*1.5;
- if (b>=bb) tmpx = (b2 - b1)*3.0;
- else tmpx = (b2 - b1)*1.5;
-
- if(tmpx>=0.5 && tmpx<=2.5)
+ if(tmpx >= 0.5 && tmpx <= 2.5)
{
tmp = tmpx - 0.5;
x = 8.0 * (tmp*tmp - 2.0 * tmp);
- }
- else x = 0.0;
+ } else
+ x = 0.0;
+
tmpx += 0.474;
tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx);
- if (tmpy <= -100.0) gpsyInfo->spreadingS[b][bb] = 0.0;
+ if (tmpy < -100.0) gpsyInfo->spreadingS[b][bb] = 0.0;
else gpsyInfo->spreadingS[b][bb] = exp((x + tmpy)*0.2302585093);
}
}
+ for(b = 0; b < gpsyInfo->psyPartS->len; b++) {
+ for(bb = 0; bb < gpsyInfo->psyPartS->len; bb++) {
+ if (gpsyInfo->spreadingS[b][bb] != 0.0)
+ break;
+ }
+ gpsyInfo->sprIndS[b][0] = bb;
+ for(bb = gpsyInfo->psyPartS->len-1; bb > 0; bb--) {
+ if (gpsyInfo->spreadingS[b][bb] != 0.0)
+ break;
+ }
+ gpsyInfo->sprIndS[b][1] = bb;
+ }
j = 0;
- for( b = 0; b < num_cb_short; b++){
+ for( b = 0; b < gpsyInfo->psyPartS->len; b++){
gpsyInfo->athS[b] = 1.e37;
- for (bb = 0; bb < cb_width_short[b]; bb++, j++) {
+ for (bb = 0; bb < gpsyInfo->psyPartS->width[b]; bb++, j++) {
double freq = gpsyInfo->sampleRate*j/(1000.0*2*size);
double level;
level = ATHformula(freq*1000) - 20;
level = pow(10., 0.1*level);
- level *= cb_width_short[b];
+ level *= gpsyInfo->psyPartS->width[b];
if (level < gpsyInfo->athS[b])
gpsyInfo->athS[b] = level;
}
}
- for( b = 0; b < num_cb_short; b++){
+ for( b = 0; b < gpsyInfo->psyPartS->len; b++){
tmp = 0.0;
- for( bb = 0; bb < num_cb_short; bb++)
- tmp += gpsyInfo->spreadingS[bb][b];
- gpsyInfo->rnormS[b] = 1.0/tmp;
+ for( bb = gpsyInfo->sprIndS[b][0]; bb < gpsyInfo->sprIndS[b][1]; bb++)
+ tmp += gpsyInfo->spreadingS[b][bb];
+
+ /* SNR formula */
+ if (bval[b] < 13) SNR = -8.25;
+ else SNR = -4.5 * (bval[b]-13)/(24.0-13.0) +
+ -8.25*(bval[b]-24)/(13.0-24.0);
+ SNR = pow(10.0, SNR/10.0);
+
+ for( bb = gpsyInfo->sprIndS[b][0]; bb < gpsyInfo->sprIndS[b][1]; bb++)
+ gpsyInfo->spreadingS[b][bb] *= SNR / tmp;
}
low = 0;
- for (b = 0; b < num_cb_short; b++) {
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++) {
tmp = freq2bark(gpsyInfo->sampleRate*low/(2*size));
tmp = (min(tmp, 15.5)/15.5);
gpsyInfo->mldS[b] = pow(10.0, 1.25*(1-cos(M_PI*tmp))-2.5);
- low += cb_width_short[b];
+ low += gpsyInfo->psyPartS->width[b];
}
}
@@ -254,16 +275,14 @@
if (gpsyInfo->ath) free(gpsyInfo->ath);
if (gpsyInfo->athS) free(gpsyInfo->athS);
- if (gpsyInfo->rnorm) free(gpsyInfo->rnorm);
- if (gpsyInfo->rnormS) free(gpsyInfo->rnormS);
if (gpsyInfo->mld) free(gpsyInfo->mld);
if (gpsyInfo->mldS) free(gpsyInfo->mldS);
- if (gpsyInfo->hannWindow) free(gpsyInfo->hannWindow);
- if (gpsyInfo->hannWindowS) free(gpsyInfo->hannWindowS);
+ if (gpsyInfo->window) free(gpsyInfo->window);
+ if (gpsyInfo->windowS) free(gpsyInfo->windowS);
for (channel = 0; channel < numChannels; channel++) {
+ if (psyInfo[channel].tonality) free(psyInfo[channel].tonality);
if (psyInfo[channel].prevSamples) free(psyInfo[channel].prevSamples);
- if (psyInfo[channel].cw) free(psyInfo[channel].cw);
if (psyInfo[channel].maskThr) free(psyInfo[channel].maskThr);
if (psyInfo[channel].maskEn) free(psyInfo[channel].maskEn);
if (psyInfo[channel].maskThrNext) free(psyInfo[channel].maskThrNext);
@@ -276,22 +295,14 @@
if (psyInfo[channel].lastNb) free(psyInfo[channel].lastNb);
if (psyInfo[channel].lastNbMS) free(psyInfo[channel].lastNbMS);
- if (psyInfo[channel].fftMagPlus2) free(psyInfo[channel].fftMagPlus2);
- if (psyInfo[channel].fftMagPlus1) free(psyInfo[channel].fftMagPlus1);
- if (psyInfo[channel].fftMag) free(psyInfo[channel].fftMag);
- if (psyInfo[channel].fftMagMin1) free(psyInfo[channel].fftMagMin1);
- if (psyInfo[channel].fftMagMin2) free(psyInfo[channel].fftMagMin2);
- if (psyInfo[channel].fftPhPlus2) free(psyInfo[channel].fftPhPlus2);
- if (psyInfo[channel].fftPhPlus1) free(psyInfo[channel].fftPhPlus1);
- if (psyInfo[channel].fftPh) free(psyInfo[channel].fftPh);
- if (psyInfo[channel].fftPhMin1) free(psyInfo[channel].fftPhMin1);
- if (psyInfo[channel].fftPhMin2) free(psyInfo[channel].fftPhMin2);
+ if (psyInfo[channel].energy) free(psyInfo[channel].energy);
+ if (psyInfo[channel].energyMS) free(psyInfo[channel].energyMS);
+ if (psyInfo[channel].transBuff) free(psyInfo[channel].transBuff);
}
for (channel = 0; channel < numChannels; channel++) {
if(psyInfo[channel].prevSamplesS) free(psyInfo[channel].prevSamplesS);
for (j = 0; j < 8; j++) {
- if (psyInfo[channel].cwS[j]) free(psyInfo[channel].cwS[j]);
if (psyInfo[channel].maskThrS[j]) free(psyInfo[channel].maskThrS[j]);
if (psyInfo[channel].maskEnS[j]) free(psyInfo[channel].maskEnS[j]);
if (psyInfo[channel].maskThrNextS[j]) free(psyInfo[channel].maskThrNextS[j]);
@@ -301,14 +312,9 @@
if (psyInfo[channel].maskThrNextSMS[j]) free(psyInfo[channel].maskThrNextSMS[j]);
if (psyInfo[channel].maskEnNextSMS[j]) free(psyInfo[channel].maskEnNextSMS[j]);
- if (psyInfo[channel].fftMagPlus2S[j]) free(psyInfo[channel].fftMagPlus2S[j]);
- if (psyInfo[channel].fftMagPlus1S[j]) free(psyInfo[channel].fftMagPlus1S[j]);
- if (psyInfo[channel].fftMagS[j]) free(psyInfo[channel].fftMagS[j]);
- if (psyInfo[channel].fftMagMin1S[j]) free(psyInfo[channel].fftMagMin1S[j]);
- if (psyInfo[channel].fftPhPlus2S[j]) free(psyInfo[channel].fftPhPlus2S[j]);
- if (psyInfo[channel].fftPhPlus1S[j]) free(psyInfo[channel].fftPhPlus1S[j]);
- if (psyInfo[channel].fftPhS[j]) free(psyInfo[channel].fftPhS[j]);
- if (psyInfo[channel].fftPhMin1S[j]) free(psyInfo[channel].fftPhMin1S[j]);
+ if (psyInfo[channel].energyS[j]) free(psyInfo[channel].energyS[j]);
+ if (psyInfo[channel].energySMS[j]) free(psyInfo[channel].energySMS[j]);
+ if (psyInfo[channel].transBuffS[j]) free(psyInfo[channel].transBuffS[j]);
}
}
}
@@ -329,9 +335,7 @@
int leftChan = channel;
int rightChan = channelInfo[channel].paired_ch;
- /* Calculate the unpredictability */
- PsyUnpredictability(&psyInfo[leftChan]);
- PsyUnpredictability(&psyInfo[rightChan]);
+ PsyBufferUpdateMS(gpsyInfo, &psyInfo[leftChan], &psyInfo[rightChan]);
/* Calculate the threshold */
PsyThreshold(gpsyInfo, &psyInfo[leftChan], cb_width_long, num_cb_long,
@@ -351,9 +355,6 @@
} else if (!channelInfo[channel].cpe) { /* SCE */
- /* Calculate the unpredictability */
- PsyUnpredictability(&psyInfo[channel]);
-
/* Calculate the threshold */
PsyThreshold(gpsyInfo, &psyInfo[channel], cb_width_long, num_cb_long,
cb_width_short, num_cb_short);
@@ -369,10 +370,10 @@
/* Applying Hann window */
if (size == BLOCK_LEN_LONG*2) {
for(i = 0; i < size; i++)
- inSamples[i] *= gpsyInfo->hannWindow[i];
+ inSamples[i] *= gpsyInfo->window[i];
} else {
for(i = 0; i < size; i++)
- inSamples[i] *= gpsyInfo->hannWindowS[i];
+ inSamples[i] *= gpsyInfo->windowS[i];
}
}
@@ -380,303 +381,141 @@
{
int i, j;
double a, b;
- double *transBuff, *transBuffS, *tmp;
+ double temp[2048];
- transBuff = (double*)malloc(2*psyInfo->size*sizeof(double));
+ memcpy(psyInfo->transBuff, psyInfo->prevSamples, psyInfo->size*sizeof(double));
+ memcpy(psyInfo->transBuff + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
- memcpy(transBuff, psyInfo->prevSamples, psyInfo->size*sizeof(double));
- memcpy(transBuff + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
+ Hann(gpsyInfo, psyInfo->transBuff, 2*psyInfo->size);
+ rsfft(psyInfo->transBuff, 11);
- /* In 2 frames this will be the frequencies where
- the psychoacoustics are calculated for */
- Hann(gpsyInfo, transBuff, 2*psyInfo->size);
- rsfft(transBuff, 11);
-
-
- /* shift all buffers 1 frame ahead */
- tmp = psyInfo->fftMagMin2;
- psyInfo->fftMagMin2 = psyInfo->fftMagMin1;
- psyInfo->fftMagMin1 = psyInfo->fftMag;
- psyInfo->fftMag = psyInfo->fftMagPlus1;
- psyInfo->fftMagPlus1 = psyInfo->fftMagPlus2;
- psyInfo->fftMagPlus2 = tmp;
-
- tmp = psyInfo->fftPhMin2;
- psyInfo->fftPhMin2 = psyInfo->fftPhMin1;
- psyInfo->fftPhMin1 = psyInfo->fftPh;
- psyInfo->fftPh = psyInfo->fftPhPlus1;
- psyInfo->fftPhPlus1 = psyInfo->fftPhPlus2;
- psyInfo->fftPhPlus2 = tmp;
-
-
- /* Calculate magnitude and phase of new data */
+ /* Calculate magnitude of new data */
for (i = 0; i < psyInfo->size; i++) {
- a = transBuff[i];
- b = transBuff[i + psyInfo->size];
- psyInfo->fftMagPlus2[i] = sqrt(a*a + b*b);
-
- if(a > 0.0){
- if(b >= 0.0)
- psyInfo->fftPhPlus2[i] = atan2(b, a);
- else
- psyInfo->fftPhPlus2[i] = atan2(b, a) + M_PI * 2.0;
- } else if(a < 0.0) {
- psyInfo->fftPhPlus2[i] = atan2(b, a) + M_PI;
- } else {
- if(b > 0.0)
- psyInfo->fftPhPlus2[i] = M_PI * 0.5;
- else if( b < 0.0 )
- psyInfo->fftPhPlus2[i] = M_PI * 1.5;
- else
- psyInfo->fftPhPlus2[i] = 0.0;
- }
+ a = psyInfo->transBuff[i];
+ b = psyInfo->transBuff[i+psyInfo->size];
+ psyInfo->energy[i] = 0.5 * (a*a + b*b);
}
- transBuffS = (double*)malloc(2*psyInfo->sizeS*sizeof(double));
+ memcpy(temp, psyInfo->prevSamples, psyInfo->size*sizeof(double));
+ memcpy(temp + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
- memcpy(transBuff, psyInfo->prevSamples, psyInfo->size*sizeof(double));
- memcpy(transBuff + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
-
for (j = 0; j < 8; j++) {
- memcpy(transBuffS, transBuff+(j*128)+(1024-128), 2*psyInfo->sizeS*sizeof(double));
+ memcpy(psyInfo->transBuffS[j], temp+(j*128)+(1024-128), 2*psyInfo->sizeS*sizeof(double));
- /* In 2 frames this will be the frequencies where
- the psychoacoustics are calculated for */
- Hann(gpsyInfo, transBuffS, 2*psyInfo->sizeS);
- rsfft(transBuff, 8);
+ Hann(gpsyInfo, psyInfo->transBuffS[j], 2*psyInfo->sizeS);
+ rsfft(psyInfo->transBuffS[j], 8);
-
- /* shift all buffers 1 frame ahead */
- tmp = psyInfo->fftMagMin1S[j];
- psyInfo->fftMagMin1S[j] = psyInfo->fftMagS[j];
- psyInfo->fftMagS[j] = psyInfo->fftMagPlus1S[j];
- psyInfo->fftMagPlus1S[j] = psyInfo->fftMagPlus2S[j];
- psyInfo->fftMagPlus2S[j] = tmp;
-
- tmp = psyInfo->fftPhMin1S[j];
- psyInfo->fftPhMin1S[j] = psyInfo->fftPhS[j];
- psyInfo->fftPhS[j] = psyInfo->fftPhPlus1S[j];
- psyInfo->fftPhPlus1S[j] = psyInfo->fftPhPlus2S[j];
- psyInfo->fftPhPlus2S[j] = tmp;
-
-
- /* Calculate magnitude and phase of new data */
- for (i = 0; i < psyInfo->sizeS; i++) {
- a = transBuffS[i];
- b = transBuffS[i + psyInfo->sizeS];
- psyInfo->fftMagPlus2S[j][i] = sqrt(a*a + b*b);
-
- if(a > 0.0){
- if(b >= 0.0)
- psyInfo->fftPhPlus2S[j][i] = atan2(b, a);
- else
- psyInfo->fftPhPlus2S[j][i] = atan2(b, a) + M_PI * 2.0;
- } else if(a < 0.0) {
- psyInfo->fftPhPlus2S[j][i] = atan2(b, a) + M_PI;
- } else {
- if(b > 0.0)
- psyInfo->fftPhPlus2S[j][i] = M_PI * 0.5;
- else if( b < 0.0 )
- psyInfo->fftPhPlus2S[j][i] = M_PI * 1.5;
- else
- psyInfo->fftPhPlus2S[j][i] = 0.0;
- }
+ /* Calculate magnitude of new data */
+ for(i = 0; i < psyInfo->sizeS; i++){
+ a = psyInfo->transBuffS[j][i];
+ b = psyInfo->transBuffS[j][i+psyInfo->sizeS];
+ psyInfo->energyS[j][i] = 0.5 * (a*a + b*b);
}
}
memcpy(psyInfo->prevSamples, newSamples, psyInfo->size*sizeof(double));
-
- if (transBuff) free(transBuff);
- if (transBuffS) free(transBuffS);
}
-static void PsyUnpredictability(PsyInfo *psyInfo)
+void PsyBufferUpdateMS(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfoL, PsyInfo *psyInfoR)
{
int i, j;
- double predMagMin, predMagPlus, predMag, mag;
- double predPhMin, predPhPlus, predPh, ph;
+ double a, b;
+ double dataL[2048], dataR[2048];
- for (i = 0; i < psyInfo->size; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagMin1[i] - psyInfo->fftMagMin2[i];
- predMagPlus = 2.0 * psyInfo->fftMagPlus1[i] - psyInfo->fftMagPlus2[i];
- predPhMin = 2.0 * psyInfo->fftPhMin1[i] - psyInfo->fftPhMin2[i];
- predPhPlus = 2.0 * psyInfo->fftPhPlus1[i] - psyInfo->fftPhPlus2[i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMag[i] - predMagMin) < (psyInfo->fftMag[i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
- }
+ for (i = 0; i < psyInfoL->size*2; i++) {
+ a = psyInfoL->transBuff[i];
+ b = psyInfoR->transBuff[i];
+ dataL[i] = (a+b)*SQRT2*0.5;
+ dataR[i] = (a-b)*SQRT2*0.5;
+ }
- mag = psyInfo->fftMag[i];
- ph = psyInfo->fftPh[i];
+ /* Calculate magnitude of new data */
+ for (i = 0; i < psyInfoL->size; i++) {
+ a = dataL[i];
+ b = dataL[i+psyInfoL->size];
+ psyInfoL->energyMS[i] = 0.5 * (a*a + b*b);
- /* unpredictability */
- psyInfo->cw[i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
+ a = dataR[i];
+ b = dataR[i+psyInfoL->size];
+ psyInfoR->energyMS[i] = 0.5 * (a*a + b*b);
}
- for (i = 0; i < psyInfo->sizeS; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagMin1S[7][i] - psyInfo->fftMagMin1S[6][i];
- predMagPlus = 2.0 * psyInfo->fftMagS[1][i] - psyInfo->fftMagS[2][i];
- predPhMin = 2.0 * psyInfo->fftPhMin1S[7][i] - psyInfo->fftPhMin1S[6][i];
- predPhPlus = 2.0 * psyInfo->fftPhS[1][i] - psyInfo->fftPhS[2][i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMagS[0][i] - predMagMin) < (psyInfo->fftMagS[0][i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
+ for (j = 0; j < 8; j++) {
+
+ for (i = 0; i < psyInfoL->sizeS*2; i++) {
+ a = psyInfoL->transBuffS[j][i];
+ b = psyInfoR->transBuffS[j][i];
+ dataL[i] = (a+b)*SQRT2*0.5;
+ dataR[i] = (a-b)*SQRT2*0.5;
}
- mag = psyInfo->fftMagS[0][i];
- ph = psyInfo->fftPhS[0][i];
+ /* Calculate magnitude of new data */
+ for (i = 0; i < psyInfoL->sizeS; i++) {
+ a = dataL[i];
+ b = dataL[i+psyInfoL->sizeS];
+ psyInfoL->energySMS[j][i] = 0.5 * (a*a + b*b);
- /* unpredictability */
- psyInfo->cwS[0][i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
- }
- for (i = 0; i < psyInfo->sizeS; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagS[0][i] - psyInfo->fftMagMin1S[7][i];
- predMagPlus = 2.0 * psyInfo->fftMagS[2][i] - psyInfo->fftMagS[3][i];
- predPhMin = 2.0 * psyInfo->fftPhS[0][i] - psyInfo->fftPhMin1S[7][i];
- predPhPlus = 2.0 * psyInfo->fftPhS[2][i] - psyInfo->fftPhS[3][i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMagS[1][i] - predMagMin) < (psyInfo->fftMagS[1][i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
+ a = dataR[i];
+ b = dataR[i+psyInfoL->sizeS];
+ psyInfoR->energySMS[j][i] = 0.5 * (a*a + b*b);
}
+ }
+}
- mag = psyInfo->fftMagS[1][i];
- ph = psyInfo->fftPhS[1][i];
+/* addition of simultaneous masking */
+__inline double mask_add(double m1, double m2, int k, int b, double *ath)
+{
+ static const double table1[] = {
+ 3.3246 *3.3246 ,3.23837*3.23837,3.15437*3.15437,3.00412*3.00412,2.86103*2.86103,2.65407*2.65407,2.46209*2.46209,2.284 *2.284 ,
+ 2.11879*2.11879,1.96552*1.96552,1.82335*1.82335,1.69146*1.69146,1.56911*1.56911,1.46658*1.46658,1.37074*1.37074,1.31036*1.31036,
+ 1.25264*1.25264,1.20648*1.20648,1.16203*1.16203,1.12765*1.12765,1.09428*1.09428,1.0659 *1.0659 ,1.03826*1.03826,1.01895*1.01895,
+ 1
+ };
- /* unpredictability */
- psyInfo->cwS[1][i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
- }
+ static const double table2[] = {
+ 1.33352*1.33352,1.35879*1.35879,1.38454*1.38454,1.39497*1.39497,1.40548*1.40548,1.3537 *1.3537 ,1.30382*1.30382,1.22321*1.22321,
+ 1.14758*1.14758
+ };
- for (j = 2; j < 6; j++) {
- for (i = 0; i < psyInfo->sizeS; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagS[j-1][i] - psyInfo->fftMagS[j-2][i];
- predMagPlus = 2.0 * psyInfo->fftMagS[j+1][i] - psyInfo->fftMagS[j+2][i];
- predPhMin = 2.0 * psyInfo->fftPhS[j-1][i] - psyInfo->fftPhS[j-2][i];
- predPhPlus = 2.0 * psyInfo->fftPhS[j+1][i] - psyInfo->fftPhS[j+2][i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMagS[j][i] - predMagMin) < (psyInfo->fftMagS[j][i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
- }
+ static const double table3[] = {
+ 2.35364*2.35364,2.29259*2.29259,2.23313*2.23313,2.12675*2.12675,2.02545*2.02545,1.87894*1.87894,1.74303*1.74303,1.61695*1.61695,
+ 1.49999*1.49999,1.39148*1.39148,1.29083*1.29083,1.19746*1.19746,1.11084*1.11084,1.03826*1.03826
+ };
- mag = psyInfo->fftMagS[j][i];
- ph = psyInfo->fftPhS[j][i];
- /* unpredictability */
- psyInfo->cwS[j][i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
- }
- }
+ int i;
+ double m;
- for (i = 0; i < psyInfo->sizeS; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagS[5][i] - psyInfo->fftMagS[4][i];
- predMagPlus = 2.0 * psyInfo->fftMagS[7][i] - psyInfo->fftMagPlus1S[0][i];
- predPhMin = 2.0 * psyInfo->fftPhS[5][i] - psyInfo->fftPhS[4][i];
- predPhPlus = 2.0 * psyInfo->fftPhS[7][i] - psyInfo->fftPhPlus1S[0][i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMagS[6][i] - predMagMin) < (psyInfo->fftMagS[6][i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
- }
+ if (m1 == 0) return m2;
- mag = psyInfo->fftMagS[6][i];
- ph = psyInfo->fftPhS[6][i];
+ if (b < 0) b = -b;
- /* unpredictability */
- psyInfo->cwS[6][i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
- }
- for (i = 0; i < psyInfo->sizeS; i++)
- {
- predMagMin = 2.0 * psyInfo->fftMagS[6][i] - psyInfo->fftMagMin1S[5][i];
- predMagPlus = 2.0 * psyInfo->fftMagPlus1S[0][i] - psyInfo->fftMagPlus1S[1][i];
- predPhMin = 2.0 * psyInfo->fftPhS[6][i] - psyInfo->fftPhS[5][i];
- predPhPlus = 2.0 * psyInfo->fftPhPlus1S[0][i] - psyInfo->fftPhPlus1S[1][i];
- if ((predMagMin != 0.0) && (predMagPlus != 0.0)) {
- if ((psyInfo->fftMagS[7][i] - predMagMin) < (psyInfo->fftMagS[7][i] - predMagPlus)) {
- predMag = predMagMin;
- predPh = predPhMin;
- } else {
- predMag = predMagPlus;
- predPh = predPhPlus;
- }
- } else if (predMagMin == 0.0) {
- predMag = predMagPlus;
- predPh = predPhPlus;
- } else { /* predMagPlus == 0.0 */
- predMag = predMagMin;
- predPh = predPhMin;
- }
+ i = (int)(10*log10(m2 / m1)/10*16);
+ m = 10*log10((m1+m2)/ath[k]);
- mag = psyInfo->fftMagS[7][i];
- ph = psyInfo->fftPhS[7][i];
+ if (i < 0) i = -i;
- /* unpredictability */
- psyInfo->cwS[7][i] =
- sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
+ if (b <= 3) { /* approximately, 1 bark = 3 partitions */
+ if (i > 8) return m1+m2;
+ return (m1+m2)*table2[i];
}
+
+ if (m<15) {
+ if (m > 0) {
+ double f=1.0,r;
+ if (i > 24) return m1+m2;
+ if (i > 13) f = 1; else f = table3[i];
+ r = (m-0)/15;
+ return (m1+m2)*(table1[i]*r+f*(1-r));
+ }
+ if (i > 13) return m1+m2;
+ return (m1+m2)*table3[i];
+ }
+
+ if (i > 24) return m1+m2;
+ return (m1+m2)*table1[i];
}
static void PsyThreshold(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, int *cb_width_long,
@@ -683,77 +522,131 @@
int num_cb_long, int *cb_width_short, int num_cb_short)
{
int b, bb, w, low, high, j;
- double tmp, ct, ecb, cb;
- double tb, snr, bc, en, nb;
+ double tmp, ecb;
- double e[MAX_SCFAC_BANDS];
- double c[MAX_SCFAC_BANDS];
+ double e[MAX_NPART];
+ double c[MAX_NPART];
+ double maxi[MAX_NPART];
+ double avg[MAX_NPART];
+ double eb;
+ double nb_tmp[1024], epart, npart;
+
double tot, mx, estot[8];
double pe = 0.0;
/* Energy in each partition and weighted unpredictability */
high = 0;
- for (b = 0; b < num_cb_long; b++)
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
{
+ double m, a;
low = high;
- high += cb_width_long[b];
+ high += gpsyInfo->psyPart->width[b];
- e[b] = 0.0;
- c[b] = 0.0;
+ eb = psyInfo->energy[low];
+ m = a = eb;
- for (w = low; w < high; w++)
+ for (w = low+1; w < high; w++)
{
- tmp = psyInfo->fftMag[w];
- tmp *= tmp;
- e[b] += tmp;
- c[b] += tmp * psyInfo->cw[w];
+ double el = psyInfo->energy[w];
+ eb += el;
+ a += el;
+ m = m < el ? el : m;
}
+ e[b] = eb;
+ maxi[b] = m;
+ avg[b] = a / gpsyInfo->psyPart->width[b];
}
- /* Convolve the partitioned energy and unpredictability
- with the spreading function */
- for (b = 0; b < num_cb_long; b++)
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
{
- ecb = 0.0;
- ct = 0.0;
+ static double tab[20] = {
+ 1,0.79433,0.63096,0.63096,0.63096,0.63096,0.63096,0.25119,0.11749,0.11749,
+ 0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749
+ };
+ int c1,c2,t;
+ double m, a, tonality;
- for (bb = 0; bb < num_cb_long; bb++)
+ c1 = c2 = 0;
+ m = a = 0;
+ for(w = b-1; w <= b+1; w++)
{
- ecb += e[bb] * gpsyInfo->spreading[bb][b];
- ct += c[bb] * gpsyInfo->spreading[bb][b];
+ if (w >= 0 && w < gpsyInfo->psyPart->len) {
+ c1++;
+ c2 += gpsyInfo->psyPart->width[w];
+ a += avg[w];
+ m = m < maxi[w] ? maxi[w] : m;
+ }
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- en = ecb * gpsyInfo->rnorm[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
+ a /= c1;
+ tonality = (a == 0) ? 0 : (m / a - 1)/(c2-1);
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
+ t = (int)(20*tonality);
+ if (t > 19) t = 19;
+ psyInfo->tonality[b] = tab[t];
+ c[b] = e[b] * tab[t];
+ }
+ /* Convolve the partitioned energy and unpredictability
+ with the spreading function */
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
+ {
+ ecb = 0;
+ for (bb = gpsyInfo->sprInd[b][0]; bb < gpsyInfo->sprInd[b][1]; bb++)
+ {
+ ecb = mask_add(ecb, gpsyInfo->spreading[b][bb] * c[bb], bb, bb-b, gpsyInfo->ath);
+ }
+ ecb *= 0.158489319246111;
+
/* Actual energy threshold */
- nb = en * bc;
- nb = max(min(nb, psyInfo->lastNb[b]*2), gpsyInfo->ath[b]);
- psyInfo->lastNb[b] = en * bc;
+ psyInfo->nb[b] = NS_INTERP(min(ecb, 2*psyInfo->lastNb[b]), ecb, 1/*pcfact*/);
+// psyInfo->nb[b] = max(psyInfo->nb[b], gpsyInfo->ath[b]);
+ psyInfo->lastNb[b] = ecb;
/* Perceptual entropy */
- tmp = cb_width_long[b]
- * log((nb + 0.0000000001)
+ tmp = gpsyInfo->psyPart->width[b]
+ * log((psyInfo->nb[b] + 0.0000000001)
/ (e[b] + 0.0000000001));
tmp = min(0,tmp);
pe -= tmp;
+ }
+ high = 0;
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
+ {
+ low = high;
+ high += gpsyInfo->psyPart->width[b];
+
+ for (w = low; w < high; w++)
+ {
+ nb_tmp[w] = psyInfo->nb[b] / gpsyInfo->psyPart->width[b];
+ }
+ }
+
+ high = 0;
+ for (b = 0; b < num_cb_long; b++)
+ {
+ low = high;
+ high += cb_width_long[b];
+
+ epart = psyInfo->energy[low];
+ npart = nb_tmp[low];
+ for (w = low+1; w < high; w++)
+ {
+ epart += psyInfo->energy[w];
+
+ if (nb_tmp[w] < npart)
+ npart = nb_tmp[w];
+ }
+ npart *= cb_width_long[b];
+
psyInfo->maskThr[b] = psyInfo->maskThrNext[b];
psyInfo->maskEn[b] = psyInfo->maskEnNext[b];
- psyInfo->maskThrNext[b] = nb;
- psyInfo->maskEnNext[b] = en;
+ tmp = npart / epart;
+ psyInfo->maskThrNext[b] = npart;
+ psyInfo->maskEnNext[b] = epart;
}
/* Short windows */
@@ -761,21 +654,19 @@
{
/* Energy in each partition and weighted unpredictability */
high = 0;
- for (b = 0; b < num_cb_short; b++)
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
low = high;
- high += cb_width_short[b];
+ high += gpsyInfo->psyPartS->width[b];
- e[b] = 0.0;
- c[b] = 0.0;
+ eb = psyInfo->energyS[j][low];
- for (w = low; w < high; w++)
+ for (w = low+1; w < high; w++)
{
- tmp = psyInfo->fftMagS[j][w];
- tmp *= tmp;
- e[b] += tmp;
- c[b] += tmp * psyInfo->cwS[j][w];
+ double el = psyInfo->energyS[j][w];
+ eb += el;
}
+ e[b] = eb;
}
estot[j] = 0.0;
@@ -782,44 +673,58 @@
/* Convolve the partitioned energy and unpredictability
with the spreading function */
- for (b = 0; b < num_cb_short; b++)
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
- ecb = 0.0;
- ct = 0.0;
-
- for (bb = 0; bb < num_cb_short; bb++)
+ ecb = 0;
+ for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
{
- ecb += e[bb] * gpsyInfo->spreadingS[bb][b];
- ct += c[bb] * gpsyInfo->spreadingS[bb][b];
+ ecb += gpsyInfo->spreadingS[b][bb] * e[bb];
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- en = ecb * gpsyInfo->rnormS[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
-
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
-
/* Actual energy threshold */
- nb = en * bc;
- nb = max(nb, gpsyInfo->athS[b]);
+ psyInfo->nbS[j][b] = max(1e-6, ecb);
+// psyInfo->nbS[j][b] = max(psyInfo->nbS[j][b], gpsyInfo->athS[b]);
estot[j] += e[b];
+ }
+ if (estot[j] != 0.0)
+ estot[j] /= gpsyInfo->psyPartS->len;
+
+ high = 0;
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++)
+ {
+ low = high;
+ high += gpsyInfo->psyPartS->width[b];
+
+ for (w = low; w < high; w++)
+ {
+ nb_tmp[w] = psyInfo->nbS[j][b] / gpsyInfo->psyPartS->width[b];
+ }
+ }
+
+ high = 0;
+ for (b = 0; b < num_cb_short; b++)
+ {
+ low = high;
+ high += cb_width_short[b];
+
+ epart = psyInfo->energyS[j][low];
+ npart = nb_tmp[low];
+ for (w = low+1; w < high; w++)
+ {
+ epart += psyInfo->energyS[j][w];
+
+ if (nb_tmp[w] < npart)
+ npart = nb_tmp[w];
+ }
+ npart *= cb_width_short[b];
+
psyInfo->maskThrS[j][b] = psyInfo->maskThrNextS[j][b];
psyInfo->maskEnS[j][b] = psyInfo->maskEnNextS[j][b];
- psyInfo->maskThrNextS[j][b] = nb;
- psyInfo->maskEnNextS[j][b] = en;
+ psyInfo->maskThrNextS[j][b] = npart;
+ psyInfo->maskEnNextS[j][b] = epart;
}
-
- if (estot[j] != 0.0)
- estot[j] /= num_cb_short;
}
tot = mx = estot[0];
@@ -828,11 +733,15 @@
mx = max(mx, estot[j]);
}
+#ifdef _DEBUG
+ printf("%4f %2.2f ", pe, mx/tot);
+#endif
+
tot = max(tot, 1.e-12);
- if (((mx/tot) > 0.25) && (pe > 1100.0) || ((mx/tot) > 0.5)) {
+ if (((mx/tot) > 0.35) && (pe > 1800.0) || ((mx/tot) > 0.5) || (pe > 3000.0)) {
psyInfo->block_type = ONLY_SHORT_WINDOW;
psyInfo->threeInARow++;
- } else if ((psyInfo->lastEnr > 0.35) && (psyInfo->lastPe > 1000.0)) {
+ } else if ((psyInfo->lastEnr > 0.5) || (psyInfo->lastPe > 3000.0)) {
psyInfo->block_type = ONLY_SHORT_WINDOW;
psyInfo->threeInARow++;
} else if (psyInfo->threeInARow >= 3) {
@@ -851,14 +760,19 @@
int num_cb_short)
{
int b, bb, w, low, high, j;
- double tmp, ct, ecb, cb;
- double tb, snr, bc, enM, enS, nbM, nbS;
+ double ecb, tmp1, tmp2;
- double eM[MAX_SCFAC_BANDS];
- double eS[MAX_SCFAC_BANDS];
- double cM[MAX_SCFAC_BANDS];
- double cS[MAX_SCFAC_BANDS];
+ double nb_tmpM[1024];
+ double nb_tmpS[1024];
+ double epartM, epartS, npartM, npartS;
+ double nbM[MAX_NPART];
+ double nbS[MAX_NPART];
+ double eM[MAX_NPART];
+ double eS[MAX_NPART];
+ double cM[MAX_NPART];
+ double cS[MAX_NPART];
+
double x1, x2, db, mld;
#ifdef _DEBUG
@@ -868,119 +782,155 @@
/* Energy in each partition and weighted unpredictability */
high = 0;
- for (b = 0; b < num_cb_long; b++)
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
{
+ double mid, side, ebM, ebS;
low = high;
- high += cb_width_long[b];
+ high += gpsyInfo->psyPart->width[b];
- eM[b] = 0.0;
- cM[b] = 0.0;
- eS[b] = 0.0;
- cS[b] = 0.0;
+ mid = psyInfoL->energyMS[low];
+ side = psyInfoR->energyMS[low];
- for (w = low; w < high; w++)
+ ebM = mid;
+ ebS = side;
+
+ for (w = low+1; w < high; w++)
{
- tmp = (psyInfoL->fftMag[w] + psyInfoR->fftMag[w]) * 0.5;
- tmp *= tmp;
- eM[b] += tmp;
- cM[b] += tmp * min(psyInfoL->cw[w], psyInfoR->cw[w]);
+ mid = psyInfoL->energyMS[w];
+ side = psyInfoR->energyMS[w];
- tmp = (psyInfoL->fftMag[w] - psyInfoR->fftMag[w]) * 0.5;
- tmp *= tmp;
- eS[b] += tmp;
- cS[b] += tmp * min(psyInfoL->cw[w], psyInfoR->cw[w]);
+ ebM += mid;
+ ebS += side;
}
+ eM[b] = ebM;
+ eS[b] = ebS;
+ cM[b] = ebM * min(psyInfoL->tonality[b], psyInfoR->tonality[b]);
+ cS[b] = ebS * min(psyInfoL->tonality[b], psyInfoR->tonality[b]);
}
/* Convolve the partitioned energy and unpredictability
with the spreading function */
- for (b = 0; b < num_cb_long; b++)
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
{
/* Mid channel */
- ecb = 0.0;
- ct = 0.0;
- for (bb = 0; bb < num_cb_long; bb++)
+ ecb = 0;
+ for (bb = gpsyInfo->sprInd[b][0]; bb <= gpsyInfo->sprInd[b][1]; bb++)
{
- ecb += eM[bb] * gpsyInfo->spreading[bb][b];
- ct += cM[bb] * gpsyInfo->spreading[bb][b];
+ ecb = mask_add(ecb, gpsyInfo->spreading[bb][b] * cM[bb], bb, bb-b, gpsyInfo->ath);
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- enM = ecb * gpsyInfo->rnorm[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
+ ecb *= 0.158489319246111;
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
+ /* Actual energy threshold */
+ nbM[b] = NS_INTERP(min(ecb, 2*psyInfoL->lastNbMS[b]), ecb, 1/*pcfact*/);
+// nbM[b] = max(nbM[b], gpsyInfo->ath[b]);
+ psyInfoL->lastNbMS[b] = ecb;
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
+ /* Side channel */
+
+ ecb = 0;
+ for (bb = gpsyInfo->sprInd[b][0]; bb <= gpsyInfo->sprInd[b][1]; bb++)
+ {
+ ecb = mask_add(ecb, gpsyInfo->spreading[bb][b] * cS[bb], bb, bb-b, gpsyInfo->ath);
+ }
+ ecb *= 0.158489319246111;
+
/* Actual energy threshold */
- nbM = enM * bc;
- nbM = max(min(nbM, psyInfoL->lastNbMS[b]*2), gpsyInfo->ath[b]);
- psyInfoL->lastNbMS[b] = enM * bc;
+ nbS[b] = NS_INTERP(min(ecb, 2*psyInfoR->lastNbMS[b]), ecb, 1/*pcfact*/);
+// nbS[b] = max(nbS[b], gpsyInfo->ath[b]);
+ psyInfoR->lastNbMS[b] = ecb;
+ if (psyInfoL->nb[b] <= 1.58*psyInfoR->nb[b]
+ && psyInfoR->nb[b] <= 1.58*psyInfoL->nb[b]) {
- /* Side channel */
- ecb = 0.0;
- ct = 0.0;
+ mld = gpsyInfo->mld[b]*eM[b];
+ tmp1 = max(nbM[b], min(nbS[b],mld));
- for (bb = 0; bb < num_cb_long; bb++)
+ mld = gpsyInfo->mld[b]*eS[b];
+ tmp2 = max(nbS[b], min(nbM[b],mld));
+
+ nbM[b] = tmp1;
+ nbS[b] = tmp2;
+ }
+ }
+
+ high = 0;
+ for (b = 0; b < gpsyInfo->psyPart->len; b++)
+ {
+ low = high;
+ high += gpsyInfo->psyPart->width[b];
+
+ for (w = low; w < high; w++)
{
- ecb += eS[bb] * gpsyInfo->spreading[bb][b];
- ct += cS[bb] * gpsyInfo->spreading[bb][b];
+ nb_tmpM[w] = nbM[b] / gpsyInfo->psyPart->width[b];
+ nb_tmpS[w] = nbS[b] / gpsyInfo->psyPart->width[b];
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- enS = ecb * gpsyInfo->rnorm[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
+ }
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
+ high = 0;
+ for (b = 0; b < num_cb_long; b++)
+ {
+ low = high;
+ high += cb_width_long[b];
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
+ epartM = psyInfoL->energyMS[low];
+ npartM = nb_tmpM[low];
+ epartS = psyInfoR->energyMS[low];
+ npartS = nb_tmpS[low];
- /* Actual energy threshold */
- nbS = enS * bc;
- nbS = max(min(nbS, psyInfoR->lastNbMS[b]*2), gpsyInfo->ath[b]);
- psyInfoR->lastNbMS[b] = enS * bc;
+ 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] = nbM;
- psyInfoR->maskThrNextMS[b] = nbS;
- psyInfoL->maskEnNextMS[b] = enM;
- psyInfoR->maskEnNextMS[b] = enS;
+ psyInfoL->maskThrNextMS[b] = npartM;
+ psyInfoR->maskThrNextMS[b] = npartS;
+ psyInfoL->maskEnNextMS[b] = epartM;
+ psyInfoR->maskEnNextMS[b] = epartS;
- if (psyInfoL->maskThr[b] <= 1.58*psyInfoR->maskThr[b]
- && psyInfoR->maskThr[b] <= 1.58*psyInfoL->maskThr[b]) {
+ {
+ double thmL = psyInfoL->maskThr[b];
+ double thmR = psyInfoR->maskThr[b];
+ double thmM = psyInfoL->maskThrMS[b];
+ double thmS = psyInfoR->maskThrMS[b];
+ double msfix = 3.5;
- mld = gpsyInfo->mld[b]*enM;
- psyInfoL->maskThrMS[b] = max(psyInfoL->maskThrMS[b],
- min(psyInfoR->maskThrMS[b],mld));
+ 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;
+ }
- mld = gpsyInfo->mld[b]*enS;
- psyInfoR->maskThrMS[b] = max(psyInfoR->maskThrMS[b],
- min(psyInfoL->maskThrMS[b],mld));
+ psyInfoL->maskThrMS[b] = min(thmM,psyInfoL->maskThrMS[b]);
+ psyInfoR->maskThrMS[b] = min(thmS,psyInfoR->maskThrMS[b]);
+ channelInfoL->msInfo.ms_used[b] = 1;
}
- x1 = min(psyInfoL->maskThr[b], psyInfoR->maskThr[b]);
- x2 = max(psyInfoL->maskThr[b], psyInfoR->maskThr[b]);
+#if 0
+ x1 = min(npartM, npartS);
+ x2 = max(npartM, npartS);
/* thresholds difference in db */
if (x2 >= 1000*x1) db=3;
else db = log10(x2/x1);
- if (db < 0.25) {
+ if (db < 0.05) {
#ifdef _DEBUG
ms_used++;
#endif
@@ -988,10 +938,12 @@
} else {
channelInfoL->msInfo.ms_used[b] = 0;
}
+#endif
}
+
#ifdef _DEBUG
- printf("%d\t", ms_used);
+ printf("MSL:%3d ", ms_used);
#endif
/* Short windows */
@@ -999,118 +951,145 @@
{
/* Energy in each partition and weighted unpredictability */
high = 0;
- for (b = 0; b < num_cb_short; b++)
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
+ double ebM, ebS;
low = high;
- high += cb_width_short[b];
+ high += gpsyInfo->psyPartS->width[b];
- eM[b] = 0.0;
- eS[b] = 0.0;
- cM[b] = 0.0;
- cS[b] = 0.0;
+ ebM = psyInfoL->energySMS[j][low];
+ ebS = psyInfoR->energySMS[j][low];
- for (w = low; w < high; w++)
+ for (w = low+1; w < high; w++)
{
- tmp = (psyInfoL->fftMagS[j][w] + psyInfoR->fftMagS[j][w]) * 0.5;
- tmp *= tmp;
- eM[b] += tmp;
- cM[b] += tmp * min(psyInfoL->cwS[j][w], psyInfoR->cwS[j][w]);
-
- tmp = (psyInfoL->fftMagS[j][w] - psyInfoR->fftMagS[j][w]) * 0.5;
- tmp *= tmp;
- eS[b] += tmp;
- cS[b] += tmp * min(psyInfoL->cwS[j][w], psyInfoR->cwS[j][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 < num_cb_short; b++)
+ for (b = 0; b < gpsyInfo->psyPartS->len; b++)
{
/* Mid channel */
- ecb = 0.0;
- ct = 0.0;
- for (bb = 0; bb < num_cb_short; bb++)
+ /* Get power ratio */
+ ecb = 0;
+ for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
{
- ecb += eM[bb] * gpsyInfo->spreadingS[bb][b];
- ct += cM[bb] * gpsyInfo->spreadingS[bb][b];
+ ecb += gpsyInfo->spreadingS[b][bb] * eM[bb];
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- enM = ecb * gpsyInfo->rnormS[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
+ /* Actual energy threshold */
+ nbM[b] = max(1e-6, ecb);
+// nbM[b] = max(nbM[b], gpsyInfo->athS[b]);
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
+ /* 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 */
- nbM = enM * bc;
- nbM = max(nbM, gpsyInfo->athS[b]);
+ 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]) {
- /* Side channel */
- ecb = 0.0;
- ct = 0.0;
+ mld = gpsyInfo->mldS[b]*eM[b];
+ tmp1 = max(nbM[b], min(nbS[b],mld));
- for (bb = 0; bb < num_cb_short; bb++)
+ 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++)
{
- ecb += eS[bb] * gpsyInfo->spreadingS[bb][b];
- ct += cS[bb] * gpsyInfo->spreadingS[bb][b];
+ nb_tmpM[w] = nbM[b] / gpsyInfo->psyPartS->width[b];
+ nb_tmpS[w] = nbS[b] / gpsyInfo->psyPartS->width[b];
}
- if (ecb != 0.0) cb = ct / ecb;
- else cb = 0.0;
- enS = ecb * gpsyInfo->rnormS[b];
-
- /* Get the tonality index */
- tb = -0.299 - 0.43*log(cb);
- tb = max(min(tb,1),0);
+ }
- /* Calculate the required SNR in each partition */
- snr = tb * 18.0 + (1-tb) * 6.0;
+ high = 0;
+ for (b = 0; b < num_cb_short; b++)
+ {
+ low = high;
+ high += cb_width_short[b];
- /* Power ratio */
- bc = pow(10.0, 0.1*(-snr));
+ epartM = psyInfoL->energySMS[j][low];
+ epartS = psyInfoR->energySMS[j][low];
+ npartM = nb_tmpM[low];
+ npartS = nb_tmpS[low];
- /* Actual energy threshold */
- nbS = enS * bc;
- nbS = max(nbS, gpsyInfo->athS[b]);
+ 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] = nbM;
- psyInfoR->maskThrNextSMS[j][b] = nbS;
- psyInfoL->maskEnNextSMS[j][b] = enM;
- psyInfoR->maskEnNextSMS[j][b] = enS;
+ psyInfoL->maskThrNextSMS[j][b] = npartM;
+ psyInfoR->maskThrNextSMS[j][b] = npartS;
+ psyInfoL->maskEnNextSMS[j][b] = epartM;
+ psyInfoR->maskEnNextSMS[j][b] = epartS;
- if (psyInfoL->maskThrS[j][b] <= 1.58*psyInfoR->maskThrS[j][b]
- && psyInfoR->maskThrS[j][b] <= 1.58*psyInfoL->maskThrS[j][b]) {
+ {
+ 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;
- mld = gpsyInfo->mldS[b]*enM;
- psyInfoL->maskThrSMS[j][b] = max(psyInfoL->maskThrSMS[j][b],
- min(psyInfoR->maskThrSMS[j][b],mld));
+ 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;
+ }
- mld = gpsyInfo->mldS[b]*enS;
- psyInfoR->maskThrSMS[j][b] = max(psyInfoR->maskThrSMS[j][b],
- min(psyInfoL->maskThrSMS[j][b],mld));
+ psyInfoL->maskThrSMS[j][b] = min(thmM,psyInfoL->maskThrSMS[j][b]);
+ psyInfoR->maskThrSMS[j][b] = min(thmS,psyInfoR->maskThrSMS[j][b]);
+ channelInfoL->msInfo.ms_usedS[j][b] = 1;
}
- x1 = min(psyInfoL->maskThrS[j][b], psyInfoR->maskThrS[j][b]);
- x2 = max(psyInfoL->maskThrS[j][b], psyInfoR->maskThrS[j][b]);
+#if 0
+ x1 = min(npartM, npartS);
+ x2 = max(npartM, npartS);
/* thresholds difference in db */
if (x2 >= 1000*x1) db = 3;
else db = log10(x2/x1);
- if (db < 0.25) {
+ if (db < 0.05) {
#ifdef _DEBUG
ms_usedS++;
#endif
@@ -1118,11 +1097,12 @@
} else {
channelInfoL->msInfo.ms_usedS[j][b] = 0;
}
+#endif
}
}
#ifdef _DEBUG
- printf("%d\t", ms_usedS);
+ printf("MSS:%3d ", ms_usedS);
#endif
}
@@ -1158,6 +1138,10 @@
}
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)
@@ -1175,14 +1159,199 @@
static double ATHformula(double f)
{
double ath;
- f /= 1000; // convert to khz
+ f /= 1000; /* convert to khz */
f = max(0.01, f);
f = min(18.0,f);
/* from Painter & Spanias, 1997 */
- /* minimum: (i=77) 3.3kHz = -5db */
+ /* modified by Gabriel Bouvigne to better fit to the reality */
ath = 3.640 * pow(f,-0.8)
- - 6.500 * exp(-0.6*pow(f-3.3,2.0))
- + 0.001 * pow(f,4.0);
+ - 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 }
+};
--- a/libfaac/psych.h
+++ b/libfaac/psych.h
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: psych.h,v 1.1 2001/01/17 11:21:40 menno Exp $
+ * $Id: psych.h,v 1.2 2001/01/31 23:40:05 menno Exp $
*/
#ifndef PSYCH_H
@@ -33,7 +33,20 @@
#include "coder.h"
#include "channels.h"
+#define NPART_LONG 72
+#define NPART_SHORT 48
+#define MAX_NPART NPART_LONG
+
typedef struct {
+ int sampling_rate;
+ int len;
+ unsigned char width[MAX_NPART];
+} PsyPartTable;
+
+static PsyPartTable psyPartTableLong[12+1];
+static PsyPartTable psyPartTableShort[12+1];
+
+typedef struct {
int size;
int sizeS;
@@ -44,33 +57,16 @@
/* FFT data */
/* Magnitude */
- double *fftMagPlus2;
- double *fftMagPlus1;
- double *fftMag;
- double *fftMagMin1;
- double *fftMagMin2;
+ double *energy;
+ double *energyS[8];
+ double *energyMS;
+ double *energySMS[8];
+ double *transBuff;
+ double *transBuffS[8];
- double *fftMagPlus2S[8];
- double *fftMagPlus1S[8];
- double *fftMagS[8];
- double *fftMagMin1S[8];
+ /* Tonality */
+ double *tonality;
- /* Phase */
- double *fftPhPlus2;
- double *fftPhPlus1;
- double *fftPh;
- double *fftPhMin1;
- double *fftPhMin2;
-
- double *fftPhPlus2S[8];
- double *fftPhPlus1S[8];
- double *fftPhS[8];
- double *fftPhMin1S[8];
-
- /* Unpredictability */
- double *cw;
- double *cwS[8];
-
double lastPe;
double lastEnr;
int threeInARow;
@@ -77,6 +73,8 @@
int block_type;
/* Final threshold values */
+ double *nb;
+ double *nbS[8];
double *maskThr;
double *maskEn;
double *maskThrS[8];
@@ -103,18 +101,21 @@
double sampleRate;
/* Hann window */
- double *hannWindow;
- double *hannWindowS;
+ double *window;
+ double *windowS;
/* Stereo demasking thresholds */
double *mld;
double *mldS;
+ PsyPartTable *psyPart;
+ PsyPartTable *psyPartS;
+
/* Spreading functions */
- double spreading[MAX_SCFAC_BANDS][MAX_SCFAC_BANDS];
- double spreadingS[MAX_SCFAC_BANDS][MAX_SCFAC_BANDS];
- double *rnorm;
- double *rnormS;
+ double spreading[NPART_LONG][NPART_LONG];
+ double spreadingS[NPART_SHORT][NPART_SHORT];
+ int sprInd[NPART_LONG][2];
+ int sprIndS[NPART_SHORT][2];
/* Absolute threshold of hearing */
double *ath;
@@ -122,17 +123,17 @@
} GlobalPsyInfo;
void PsyInit(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, unsigned int numChannels,
- unsigned int sampleRate, int *cb_width_long, int num_cb_long,
- int *cb_width_short, int num_cb_short);
+ unsigned int sampleRate, unsigned int sampleRateIdx);
void PsyEnd(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, unsigned int numChannels);
void PsyCalculate(ChannelInfo *channelInfo, GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo,
int *cb_width_long, int num_cb_long, int *cb_width_short,
int num_cb_short, unsigned int numChannels);
void PsyBufferUpdate(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, double *newSamples);
+void PsyBufferUpdateMS(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfoL, PsyInfo *psyInfoR);
void BlockSwitch(CoderInfo *coderInfo, PsyInfo *psyInfo, unsigned int numChannels);
static void Hann(GlobalPsyInfo *gpsyInfo, double *inSamples, int N);
-static void PsyUnpredictability(PsyInfo *psyInfo);
+__inline double mask_add(double m1, double m2, int k, int b, double *ath);
static void PsyThreshold(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, int *cb_width_long,
int num_cb_long, int *cb_width_short, int num_cb_short);
static void PsyThresholdMS(ChannelInfo *channelInfoL, GlobalPsyInfo *gpsyInfo,