shithub: aacenc

Download patch

ref: 38ba4d951379a3a587aac95a50724cb2d1182413
parent: 6a0f3c931e3a04b11086258bb4e58e2c0358727b
author: menno <menno>
date: Sun Sep 9 12:03:16 EDT 2001

Stepped back to a MPEG type psychoacoustic model

--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,7 @@
  * 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: frame.c,v 1.24 2001/09/07 11:26:04 menno Exp $
+ * $Id: frame.c,v 1.25 2001/09/09 16:03:16 menno Exp $
  */
 
 /*
@@ -180,7 +180,9 @@
 
     /* Initialize coder functions */
     PsyInit(&hEncoder->gpsyInfo, hEncoder->psyInfo, hEncoder->numChannels,
-        hEncoder->sampleRate, hEncoder->sampleRateIdx);
+        hEncoder->sampleRate, hEncoder->srInfo->cb_width_long,
+        hEncoder->srInfo->num_cb_long, hEncoder->srInfo->cb_width_short,
+        hEncoder->srInfo->num_cb_short); 
 
     FilterBankInit(hEncoder);
 
@@ -259,9 +261,9 @@
     if (samplesInput == 0)
         hEncoder->flushFrame++;
 
-    /* After 2 flush frames all samples have been encoded,
+    /* After 4 flush frames all samples have been encoded,
        return 0 bytes written */
-    if (hEncoder->flushFrame == 2)
+    if (hEncoder->flushFrame == 4)
         return 0;
 
     /* Determine the channel configuration */
@@ -284,26 +286,28 @@
         if (hEncoder->sampleBuff[channel])
             FreeMemory(hEncoder->sampleBuff[channel]);
         hEncoder->sampleBuff[channel] = hEncoder->nextSampleBuff[channel];
-        hEncoder->nextSampleBuff[channel] = (double*)AllocMemory(FRAME_LEN*sizeof(double));
+        hEncoder->nextSampleBuff[channel] = hEncoder->next2SampleBuff[channel];
+        hEncoder->next2SampleBuff[channel] = hEncoder->next3SampleBuff[channel];
+        hEncoder->next3SampleBuff[channel] = (double*)AllocMemory(FRAME_LEN*sizeof(double));
 
         if (samplesInput == 0) { /* start flushing*/
             for (i = 0; i < FRAME_LEN; i++)
-                hEncoder->nextSampleBuff[channel][i] = 0.0;
+                hEncoder->next3SampleBuff[channel][i] = 0.0;
         } else {
             for (i = 0; i < (int)(samplesInput/numChannels); i++)
-                hEncoder->nextSampleBuff[channel][i] =
+                hEncoder->next3SampleBuff[channel][i] =
                     (double)inputBuffer[(i*numChannels)+channel];
             for (i = (int)(samplesInput/numChannels); i < FRAME_LEN; i++)
-                hEncoder->nextSampleBuff[channel][i] = 0.0;
+                hEncoder->next3SampleBuff[channel][i] = 0.0;
         }
 
         /* Psychoacoustics */
         /* Update buffers and run FFT on new samples */
         PsyBufferUpdate(&hEncoder->gpsyInfo, &hEncoder->psyInfo[channel],
-            hEncoder->nextSampleBuff[channel]);
+            hEncoder->next3SampleBuff[channel]);
     }
 
-    if (hEncoder->frameNum <= 1) /* Still filling up the buffers */
+    if (hEncoder->frameNum <= 3) /* Still filling up the buffers */
         return 0;
 
     /* Psychoacoustics */
@@ -496,7 +500,7 @@
     frameBytes = CloseBitStream(bitStream);
 
 #ifdef _DEBUG
-    printf("%4d %4d\n", hEncoder->frameNum-1, frameBytes);
+    printf("%4d %4d\n", hEncoder->frameNum-3, frameBytes);
 #endif
 
     return frameBytes;
--- a/libfaac/frame.h
+++ b/libfaac/frame.h
@@ -16,7 +16,7 @@
  * 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: frame.h,v 1.13 2001/09/07 11:26:04 menno Exp $
+ * $Id: frame.h,v 1.14 2001/09/09 16:03:16 menno Exp $
  */
 
 #ifndef FRAME_H
@@ -90,6 +90,7 @@
     double *sampleBuff[MAX_CHANNELS];
     double *nextSampleBuff[MAX_CHANNELS];
     double *next2SampleBuff[MAX_CHANNELS];
+    double *next3SampleBuff[MAX_CHANNELS];
     double *ltpTimeBuff[MAX_CHANNELS];
 
     /* Filterbank buffers */
--- a/libfaac/psych.c
+++ b/libfaac/psych.c
@@ -16,13 +16,12 @@
  * 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.11 2001/06/08 18:01:09 menno Exp $
+ * $Id: psych.c,v 1.12 2001/09/09 16:03:16 menno Exp $
  */
 
+#include <stdlib.h>
+#include <memory.h>
 #include <math.h>
-#ifdef _DEBUG
-#include <stdio.h>
-#endif
 
 #include "psych.h"
 #include "coder.h"
@@ -29,1111 +28,1137 @@
 #include "fft.h"
 #include "util.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, unsigned int sampleRateIdx)
+			 unsigned int sampleRate, int *cb_width_long, int num_cb_long,
+			 int *cb_width_short, int num_cb_short)
 {
-    unsigned int channel;
-    int i, j, b, bb, high, low, size;
-    double tmpx,tmpy,tmp,x;
-    double bval[MAX_NPART], SNR;
+	unsigned int channel;
+	int i, j, b, bb, high, low, size;
+	double tmpx,tmpy,tmp,x,b1,b2;
+	double bval[MAX_SCFAC_BANDS];
 
-    gpsyInfo->ath = (double*)AllocMemory(NPART_LONG*sizeof(double));
-    gpsyInfo->athS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-    gpsyInfo->mld = (double*)AllocMemory(NPART_LONG*sizeof(double));
-    gpsyInfo->mldS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-    gpsyInfo->window = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double));
-    gpsyInfo->windowS = (double*)AllocMemory(2*BLOCK_LEN_SHORT*sizeof(double));
+	gpsyInfo->ath = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->athS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->rnorm = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->rnormS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->mld = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->mldS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+	gpsyInfo->hannWindow = (double*)AllocMemory(2*BLOCK_LEN_LONG*sizeof(double));
+	gpsyInfo->hannWindowS = (double*)AllocMemory(2*BLOCK_LEN_SHORT*sizeof(double));
 
-    for(i = 0; i < BLOCK_LEN_LONG*2; i++)
-        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->windowS[i] = 0.5 * (1-cos(2.0*M_PI*(i+0.5)/(BLOCK_LEN_SHORT*2)));
-    gpsyInfo->sampleRate = (double)sampleRate;
+	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)));
+	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->sampleRate = (double)sampleRate;
 
-    size = BLOCK_LEN_LONG;
-    for (channel = 0; channel < numChannels; channel++) {
-        psyInfo[channel].size = size;
+	size = BLOCK_LEN_LONG;
+	for (channel = 0; channel < numChannels; channel++) {
+		psyInfo[channel].size = size;
 
-        psyInfo[channel].lastPe = 0.0;
-        psyInfo[channel].lastEnr = 0.0;
-        psyInfo[channel].threeInARow = 0;
-        psyInfo[channel].tonality = (double*)AllocMemory(NPART_LONG*sizeof(double));
-        psyInfo[channel].nb = (double*)AllocMemory(NPART_LONG*sizeof(double));
-        psyInfo[channel].maskThr = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskEn = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskThrNext = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskEnNext = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskThrMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskEnMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskThrNextMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].maskEnNextMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-        psyInfo[channel].prevSamples = (double*)AllocMemory(size*sizeof(double));
-        SetMemory(psyInfo[channel].prevSamples, 0, size*sizeof(double));
+		psyInfo[channel].lastPe = 0.0;
+		psyInfo[channel].lastEnr = 0.0;
+		psyInfo[channel].threeInARow = 0;
+		psyInfo[channel].cw = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].maskThr = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskEn = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskThrNext = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskEnNext = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskThrMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskEnMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskThrNextMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].maskEnNextMS = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+		psyInfo[channel].prevSamples = (double*)AllocMemory(size*sizeof(double));
+		memset(psyInfo[channel].prevSamples, 0, size*sizeof(double));
 
-        psyInfo[channel].lastNb = (double*)AllocMemory(NPART_LONG*sizeof(double));
-        psyInfo[channel].lastNbMS = (double*)AllocMemory(NPART_LONG*sizeof(double));
-        for (j = 0; j < NPART_LONG; j++) {
-            psyInfo[channel].lastNb[j] = 2.;
-            psyInfo[channel].lastNbMS[j] = 2.;
-        }
+		psyInfo[channel].lastNb = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].lastNbMS = (double*)AllocMemory(size*sizeof(double));
+		for (j = 0; j < size; j++) {
+			psyInfo[channel].lastNb[j] = 2.;
+			psyInfo[channel].lastNbMS[j] = 2.;
+		}
 
-        psyInfo[channel].energy = (double*)AllocMemory(size*sizeof(double));
-        psyInfo[channel].energyMS = (double*)AllocMemory(size*sizeof(double));
-        psyInfo[channel].transBuff = (double*)AllocMemory(2*size*sizeof(double));
-    }
+		psyInfo[channel].fftMagPlus2 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftMagPlus1 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftMag = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftMagMin1 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftMagMin2 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftPhPlus2 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftPhPlus1 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftPh = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftPhMin1 = (double*)AllocMemory(size*sizeof(double));
+		psyInfo[channel].fftPhMin2 = (double*)AllocMemory(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;
 
-    size = BLOCK_LEN_SHORT;
-    for (channel = 0; channel < numChannels; channel++) {
-        psyInfo[channel].sizeS = size;
+		psyInfo[channel].prevSamplesS = (double*)AllocMemory(size*sizeof(double));
+		memset(psyInfo[channel].prevSamplesS, 0, size*sizeof(double));
 
-        psyInfo[channel].prevSamplesS = (double*)AllocMemory(size*sizeof(double));
-        SetMemory(psyInfo[channel].prevSamplesS, 0, size*sizeof(double));
+		for (j = 0; j < 8; j++) {
+			psyInfo[channel].cwS[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].maskThrS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskEnS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskThrNextS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskEnNextS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskThrSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskEnSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskThrNextSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].maskEnNextSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
 
-        for (j = 0; j < 8; j++) {
-            psyInfo[channel].nbS[j] = (double*)AllocMemory(NPART_SHORT*sizeof(double));
-            psyInfo[channel].maskThrS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskEnS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskThrNextS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskEnNextS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskThrSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskEnSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskThrNextSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
-            psyInfo[channel].maskEnNextSMS[j] = (double*)AllocMemory(MAX_SCFAC_BANDS*sizeof(double));
+			psyInfo[channel].fftMagPlus2S[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftMagPlus1S[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftMagS[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftMagMin1S[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftPhPlus2S[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftPhPlus1S[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftPhS[j] = (double*)AllocMemory(size*sizeof(double));
+			psyInfo[channel].fftPhMin1S[j] = (double*)AllocMemory(size*sizeof(double));
+		}
+	}
 
-            psyInfo[channel].energyS[j] = (double*)AllocMemory(size*sizeof(double));
-            psyInfo[channel].energySMS[j] = (double*)AllocMemory(size*sizeof(double));
-            psyInfo[channel].transBuffS[j] = (double*)AllocMemory(2*size*sizeof(double));
-        }
-    }
+	size = BLOCK_LEN_LONG;
+	high = 0;
+	for(b = 0; b < num_cb_long; b++) {
+		low = high;
+		high += cb_width_long[b];
 
-    size = BLOCK_LEN_LONG;
-    high = 0;
-    for(b = 0; b < gpsyInfo->psyPart->len; b++) {
-        low = high;
-        high += gpsyInfo->psyPart->width[b];
+		bval[b] = 0.5 * (freq2bark(gpsyInfo->sampleRate*low/(2*size)) + 
+			freq2bark(gpsyInfo->sampleRate*(high-1)/(2*size)));
+	}
 
-        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)
-            {
-                tmp = tmpx - 0.5;
-                x = 8.0 * (tmp*tmp - 2.0 * tmp);
-            } else
-                x = 0.0;
+			if(tmpx>=0.5 && tmpx<=2.5)
+			{
+				tmp = tmpx - 0.5;
+				x = 8.0 * (tmp*tmp - 2.0 * tmp);
+			}
+			else x = 0.0;
+			tmpx += 0.474;
+			tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx);
 
-            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;
+			else gpsyInfo->spreading[b][bb] = exp((x + tmpy)*0.2302585093);
+		}
+	}
 
-            if (tmpy < -100.0) gpsyInfo->spreading[b][bb] = 0.0;
-            else gpsyInfo->spreading[b][bb] = exp((x + tmpy)*0.2302585093);
-        }
+    for( b = 0; b < num_cb_long; b++){
+		tmp = 0.0;
+		for( bb = 0; bb < num_cb_long; bb++)
+			tmp += gpsyInfo->spreading[bb][b];
+		gpsyInfo->rnorm[b] = 1.0/tmp;
     }
-    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 < gpsyInfo->psyPart->len; b++){
-        tmp = 0.0;
-        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++){
+		gpsyInfo->ath[b] = 1.e37;
 
-    j = 0;
-    for( b = 0; b < gpsyInfo->psyPart->len; b++){
-        gpsyInfo->ath[b] = 1.e37;
-
-        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.0) - 20.0;
-            level = pow(10., 0.1*level);
-            level *= gpsyInfo->psyPart->width[b];
-            if (level < gpsyInfo->ath[b])
-                gpsyInfo->ath[b] = level;
-        }
+		for (bb = 0; bb < cb_width_long[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];
+			if (level < gpsyInfo->ath[b])
+				gpsyInfo->ath[b] = level;
+		}
     }
 
-    low = 0;
-    for (b = 0; b < gpsyInfo->psyPart->len; b++) {
-        tmp = freq2bark(gpsyInfo->sampleRate*low/(2*size));
-        tmp = (min(tmp, 15.5)/15.5);
+	low = 0;
+	for (b = 0; b < num_cb_long; 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 += gpsyInfo->psyPart->width[b];
-    }
+		gpsyInfo->mld[b] = pow(10.0, 1.25*(1-cos(M_PI*tmp))-2.5);
+		low += cb_width_long[b];
+	}
 
 
-    size = BLOCK_LEN_SHORT;
-    high = 0;
-    for(b = 0; b < gpsyInfo->psyPartS->len; b++) {
-        low = high;
-        high += gpsyInfo->psyPartS->width[b];
+	size = BLOCK_LEN_SHORT;
+	high = 0;
+	for(b = 0; b < num_cb_short; b++) {
+		low = high;
+		high += cb_width_short[b];
 
-        bval[b] = 0.5 * (freq2bark(gpsyInfo->sampleRate*low/(2*size)) +
-            freq2bark(gpsyInfo->sampleRate*(high-1)/(2*size)));
-    }
+		bval[b] = 0.5 * (freq2bark(gpsyInfo->sampleRate*low/(2*size)) + 
+			freq2bark(gpsyInfo->sampleRate*(high-1)/(2*size)));
+	}
 
-    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;
+	for(b = 0; b < num_cb_short; b++) {
+		b2 = bval[b];
+		for(bb = 0; bb < num_cb_short; bb++) {
+			b1 = bval[bb];
 
-            if(tmpx >= 0.5 && tmpx <= 2.5)
-            {
-                tmp = tmpx - 0.5;
-                x = 8.0 * (tmp*tmp - 2.0 * tmp);
-            } else
-                x = 0.0;
+			if (b>=bb) tmpx = (b2 - b1)*3.0;
+			else tmpx = (b2 - b1)*1.5;
 
-            tmpx += 0.474;
-            tmpy = 15.811389 + 7.5*tmpx - 17.5*sqrt(1.0+tmpx*tmpx);
+			if(tmpx>=0.5 && tmpx<=2.5)
+			{
+				tmp = tmpx - 0.5;
+				x = 8.0 * (tmp*tmp - 2.0 * tmp);
+			}
+			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;
-            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;
-    }
+			if (tmpy <= -100.0) gpsyInfo->spreadingS[b][bb] = 0.0;
+			else gpsyInfo->spreadingS[b][bb] = exp((x + tmpy)*0.2302585093);
+		}
+	}
 
-    j = 0;
-    for( b = 0; b < gpsyInfo->psyPartS->len; b++){
-        gpsyInfo->athS[b] = 1.e37;
+	j = 0;
+    for( b = 0; b < num_cb_short; b++){
+		gpsyInfo->athS[b] = 1.e37;
 
-        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.0) - 20.0;
-            level = pow(10., 0.1*level);
-            level *= gpsyInfo->psyPartS->width[b];
-            if (level < gpsyInfo->athS[b])
-                gpsyInfo->athS[b] = level;
-        }
+		for (bb = 0; bb < cb_width_short[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];
+			if (level < gpsyInfo->athS[b])
+				gpsyInfo->athS[b] = level;
+		}
     }
 
-    for( b = 0; b < gpsyInfo->psyPartS->len; b++){
-        tmp = 0.0;
-        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;
+    for( b = 0; b < num_cb_short; b++){
+		tmp = 0.0;
+		for( bb = 0; bb < num_cb_short; bb++)
+			tmp += gpsyInfo->spreadingS[bb][b];
+		gpsyInfo->rnormS[b] = 1.0/tmp;
     }
 
-    low = 0;
-    for (b = 0; b < gpsyInfo->psyPartS->len; b++) {
-        tmp = freq2bark(gpsyInfo->sampleRate*low/(2*size));
-        tmp = (min(tmp, 15.5)/15.5);
+	low = 0;
+	for (b = 0; b < num_cb_short; 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 += gpsyInfo->psyPartS->width[b];
-    }
+		gpsyInfo->mldS[b] = pow(10.0, 1.25*(1-cos(M_PI*tmp))-2.5);
+		low += cb_width_short[b];
+	}
 }
 
 void PsyEnd(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, unsigned int numChannels)
 {
-    unsigned int channel;
-    int j;
+	unsigned int channel;
+	int j;
 
-    if (gpsyInfo->ath) FreeMemory(gpsyInfo->ath);
-    if (gpsyInfo->athS) FreeMemory(gpsyInfo->athS);
-    if (gpsyInfo->mld) FreeMemory(gpsyInfo->mld);
-    if (gpsyInfo->mldS) FreeMemory(gpsyInfo->mldS);
-    if (gpsyInfo->window) FreeMemory(gpsyInfo->window);
-    if (gpsyInfo->windowS) FreeMemory(gpsyInfo->windowS);
+	if (gpsyInfo->ath) FreeMemory(gpsyInfo->ath);
+	if (gpsyInfo->athS) FreeMemory(gpsyInfo->athS);
+	if (gpsyInfo->rnorm) FreeMemory(gpsyInfo->rnorm);
+	if (gpsyInfo->rnormS) FreeMemory(gpsyInfo->rnormS);
+	if (gpsyInfo->mld) FreeMemory(gpsyInfo->mld);
+	if (gpsyInfo->mldS) FreeMemory(gpsyInfo->mldS);
+	if (gpsyInfo->hannWindow) FreeMemory(gpsyInfo->hannWindow);
+	if (gpsyInfo->hannWindowS) FreeMemory(gpsyInfo->hannWindowS);
 
-    for (channel = 0; channel < numChannels; channel++) {
-        if (psyInfo[channel].nb) FreeMemory(psyInfo[channel].nb);
-        if (psyInfo[channel].tonality) FreeMemory(psyInfo[channel].tonality);
-        if (psyInfo[channel].prevSamples) FreeMemory(psyInfo[channel].prevSamples);
-        if (psyInfo[channel].maskThr) FreeMemory(psyInfo[channel].maskThr);
-        if (psyInfo[channel].maskEn) FreeMemory(psyInfo[channel].maskEn);
-        if (psyInfo[channel].maskThrNext) FreeMemory(psyInfo[channel].maskThrNext);
-        if (psyInfo[channel].maskEnNext) FreeMemory(psyInfo[channel].maskEnNext);
-        if (psyInfo[channel].maskThrMS) FreeMemory(psyInfo[channel].maskThrMS);
-        if (psyInfo[channel].maskEnMS) FreeMemory(psyInfo[channel].maskEnMS);
-        if (psyInfo[channel].maskThrNextMS) FreeMemory(psyInfo[channel].maskThrNextMS);
-        if (psyInfo[channel].maskEnNextMS) FreeMemory(psyInfo[channel].maskEnNextMS);
+	for (channel = 0; channel < numChannels; channel++) {
+		if (psyInfo[channel].prevSamples) FreeMemory(psyInfo[channel].prevSamples);
+		if (psyInfo[channel].cw) FreeMemory(psyInfo[channel].cw);
+		if (psyInfo[channel].maskThr) FreeMemory(psyInfo[channel].maskThr);
+		if (psyInfo[channel].maskEn) FreeMemory(psyInfo[channel].maskEn);
+		if (psyInfo[channel].maskThrNext) FreeMemory(psyInfo[channel].maskThrNext);
+		if (psyInfo[channel].maskEnNext) FreeMemory(psyInfo[channel].maskEnNext);
+		if (psyInfo[channel].maskThrMS) FreeMemory(psyInfo[channel].maskThrMS);
+		if (psyInfo[channel].maskEnMS) FreeMemory(psyInfo[channel].maskEnMS);
+		if (psyInfo[channel].maskThrNextMS) FreeMemory(psyInfo[channel].maskThrNextMS);
+		if (psyInfo[channel].maskEnNextMS) FreeMemory(psyInfo[channel].maskEnNextMS);
+		
+		if (psyInfo[channel].lastNb) FreeMemory(psyInfo[channel].lastNb);
+		if (psyInfo[channel].lastNbMS) FreeMemory(psyInfo[channel].lastNbMS);
 
-        if (psyInfo[channel].lastNb) FreeMemory(psyInfo[channel].lastNb);
-        if (psyInfo[channel].lastNbMS) FreeMemory(psyInfo[channel].lastNbMS);
+		if (psyInfo[channel].fftMagPlus2) FreeMemory(psyInfo[channel].fftMagPlus2);
+		if (psyInfo[channel].fftMagPlus1) FreeMemory(psyInfo[channel].fftMagPlus1);
+		if (psyInfo[channel].fftMag) FreeMemory(psyInfo[channel].fftMag);
+		if (psyInfo[channel].fftMagMin1) FreeMemory(psyInfo[channel].fftMagMin1);
+		if (psyInfo[channel].fftMagMin2) FreeMemory(psyInfo[channel].fftMagMin2);
+		if (psyInfo[channel].fftPhPlus2) FreeMemory(psyInfo[channel].fftPhPlus2);
+		if (psyInfo[channel].fftPhPlus1) FreeMemory(psyInfo[channel].fftPhPlus1);
+		if (psyInfo[channel].fftPh) FreeMemory(psyInfo[channel].fftPh);
+		if (psyInfo[channel].fftPhMin1) FreeMemory(psyInfo[channel].fftPhMin1);
+		if (psyInfo[channel].fftPhMin2) FreeMemory(psyInfo[channel].fftPhMin2);
+	}
 
-        if (psyInfo[channel].energy) FreeMemory(psyInfo[channel].energy);
-        if (psyInfo[channel].energyMS) FreeMemory(psyInfo[channel].energyMS);
-        if (psyInfo[channel].transBuff) FreeMemory(psyInfo[channel].transBuff);
-    }
+	for (channel = 0; channel < numChannels; channel++) {
+		if(psyInfo[channel].prevSamplesS) FreeMemory(psyInfo[channel].prevSamplesS);
+		for (j = 0; j < 8; j++) {
+			if (psyInfo[channel].cwS[j]) FreeMemory(psyInfo[channel].cwS[j]);
+			if (psyInfo[channel].maskThrS[j]) FreeMemory(psyInfo[channel].maskThrS[j]);
+			if (psyInfo[channel].maskEnS[j]) FreeMemory(psyInfo[channel].maskEnS[j]);
+			if (psyInfo[channel].maskThrNextS[j]) FreeMemory(psyInfo[channel].maskThrNextS[j]);
+			if (psyInfo[channel].maskEnNextS[j]) FreeMemory(psyInfo[channel].maskEnNextS[j]);
+			if (psyInfo[channel].maskThrSMS[j]) FreeMemory(psyInfo[channel].maskThrSMS[j]);
+			if (psyInfo[channel].maskEnSMS[j]) FreeMemory(psyInfo[channel].maskEnSMS[j]);
+			if (psyInfo[channel].maskThrNextSMS[j]) FreeMemory(psyInfo[channel].maskThrNextSMS[j]);
+			if (psyInfo[channel].maskEnNextSMS[j]) FreeMemory(psyInfo[channel].maskEnNextSMS[j]);
 
-    for (channel = 0; channel < numChannels; channel++) {
-        if(psyInfo[channel].prevSamplesS) FreeMemory(psyInfo[channel].prevSamplesS);
-        for (j = 0; j < 8; j++) {
-            if (psyInfo[channel].nbS[j]) FreeMemory(psyInfo[channel].nbS[j]);
-            if (psyInfo[channel].maskThrS[j]) FreeMemory(psyInfo[channel].maskThrS[j]);
-            if (psyInfo[channel].maskEnS[j]) FreeMemory(psyInfo[channel].maskEnS[j]);
-            if (psyInfo[channel].maskThrNextS[j]) FreeMemory(psyInfo[channel].maskThrNextS[j]);
-            if (psyInfo[channel].maskEnNextS[j]) FreeMemory(psyInfo[channel].maskEnNextS[j]);
-            if (psyInfo[channel].maskThrSMS[j]) FreeMemory(psyInfo[channel].maskThrSMS[j]);
-            if (psyInfo[channel].maskEnSMS[j]) FreeMemory(psyInfo[channel].maskEnSMS[j]);
-            if (psyInfo[channel].maskThrNextSMS[j]) FreeMemory(psyInfo[channel].maskThrNextSMS[j]);
-            if (psyInfo[channel].maskEnNextSMS[j]) FreeMemory(psyInfo[channel].maskEnNextSMS[j]);
-
-            if (psyInfo[channel].energyS[j]) FreeMemory(psyInfo[channel].energyS[j]);
-            if (psyInfo[channel].energySMS[j]) FreeMemory(psyInfo[channel].energySMS[j]);
-            if (psyInfo[channel].transBuffS[j]) FreeMemory(psyInfo[channel].transBuffS[j]);
-        }
-    }
+			if (psyInfo[channel].fftMagPlus2S[j]) FreeMemory(psyInfo[channel].fftMagPlus2S[j]);
+			if (psyInfo[channel].fftMagPlus1S[j]) FreeMemory(psyInfo[channel].fftMagPlus1S[j]);
+			if (psyInfo[channel].fftMagS[j]) FreeMemory(psyInfo[channel].fftMagS[j]);
+			if (psyInfo[channel].fftMagMin1S[j]) FreeMemory(psyInfo[channel].fftMagMin1S[j]);
+			if (psyInfo[channel].fftPhPlus2S[j]) FreeMemory(psyInfo[channel].fftPhPlus2S[j]);
+			if (psyInfo[channel].fftPhPlus1S[j]) FreeMemory(psyInfo[channel].fftPhPlus1S[j]);
+			if (psyInfo[channel].fftPhS[j]) FreeMemory(psyInfo[channel].fftPhS[j]);
+			if (psyInfo[channel].fftPhMin1S[j]) FreeMemory(psyInfo[channel].fftPhMin1S[j]);
+		}
+	}
 }
 
 /* Do psychoacoustical analysis */
 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)
+				  int *cb_width_long, int num_cb_long, int *cb_width_short,
+				  int num_cb_short, unsigned int numChannels)
 {
-    unsigned int channel;
+	unsigned int channel;
 
-    for (channel = 0; channel < numChannels; channel++) {
-        if (channelInfo[channel].present) {
+	for (channel = 0; channel < numChannels; channel++) {
+		if (channelInfo[channel].present) {
 
-            if (channelInfo[channel].cpe &&
-                channelInfo[channel].ch_is_left) { /* CPE */
+			if (channelInfo[channel].cpe &&
+				channelInfo[channel].ch_is_left) { /* CPE */
 
-                int leftChan = channel;
-                int rightChan = channelInfo[channel].paired_ch;
+				int leftChan = channel;
+				int rightChan = channelInfo[channel].paired_ch;
 
-                PsyBufferUpdateMS(gpsyInfo, &psyInfo[leftChan], &psyInfo[rightChan]);
+				/* Calculate the unpredictability */
+				PsyUnpredictability(&psyInfo[leftChan]);
+				PsyUnpredictability(&psyInfo[rightChan]);
 
-                /* Calculate the threshold */
-                PsyThreshold(gpsyInfo, &psyInfo[leftChan], cb_width_long, num_cb_long,
-                    cb_width_short, num_cb_short);
-                PsyThreshold(gpsyInfo, &psyInfo[rightChan], cb_width_long, num_cb_long,
-                    cb_width_short, num_cb_short);
+				/* Calculate the threshold */
+				PsyThreshold(gpsyInfo, &psyInfo[leftChan], cb_width_long, num_cb_long,
+					cb_width_short, num_cb_short);
+				PsyThreshold(gpsyInfo, &psyInfo[rightChan], cb_width_long, num_cb_long,
+					cb_width_short, num_cb_short);
 
-                /* And for MS */
-                PsyThresholdMS(&channelInfo[leftChan], gpsyInfo, &psyInfo[leftChan],
-                    &psyInfo[rightChan], cb_width_long, num_cb_long, cb_width_short,
-                    num_cb_short);
+				/* And for MS */
+				PsyThresholdMS(&channelInfo[leftChan], gpsyInfo, &psyInfo[leftChan],
+					&psyInfo[rightChan], cb_width_long, num_cb_long, cb_width_short,
+					num_cb_short);
 
-            } else if (!channelInfo[channel].cpe &&
-                channelInfo[channel].lfe) { /* LFE */
+			} else if (!channelInfo[channel].cpe &&
+				channelInfo[channel].lfe) { /* LFE */
 
-                /* NOT FINISHED */
+				/* NOT FINISHED */
 
-            } else if (!channelInfo[channel].cpe) { /* SCE */
+			} else if (!channelInfo[channel].cpe) { /* SCE */
 
-                /* Calculate the threshold */
-                PsyThreshold(gpsyInfo, &psyInfo[channel], cb_width_long, num_cb_long,
-                    cb_width_short, num_cb_short);
-            }
-        }
-    }
+				/* 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);
+			}
+		}
+	}
 }
 
 static void Hann(GlobalPsyInfo *gpsyInfo, double *inSamples, int size)
 {
-    int i;
+	int i;
 
-    /* Applying Hann window */
-    if (size == BLOCK_LEN_LONG*2) {
-        for(i = 0; i < size; i++)
-            inSamples[i] *= gpsyInfo->window[i];
-    } else {
-        for(i = 0; i < size; i++)
-            inSamples[i] *= gpsyInfo->windowS[i];
-    }
+	/* Applying Hann window */
+	if (size == BLOCK_LEN_LONG*2) {
+		for(i = 0; i < size; i++)
+			inSamples[i] *= gpsyInfo->hannWindow[i];
+	} else {
+		for(i = 0; i < size; i++)
+			inSamples[i] *= gpsyInfo->hannWindowS[i];
+	}
 }
 
 void PsyBufferUpdate(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, double *newSamples)
 {
-    int i, j;
-    double a, b;
-    double temp[2048];
+	int i, j;
+	double a, b;
+	double *transBuff, *transBuffS, *tmp;
 
-    memcpy(psyInfo->transBuff, psyInfo->prevSamples, psyInfo->size*sizeof(double));
-    memcpy(psyInfo->transBuff + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
+	transBuff = (double*)AllocMemory(2*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);
 
-    /* Calculate magnitude of new data */
-    for (i = 0; i < psyInfo->size; i++) {
-        a = psyInfo->transBuff[i];
-        b = psyInfo->transBuff[i+psyInfo->size];
-        psyInfo->energy[i] = 0.5 * (a*a + b*b);
-    }
+	/* In 2 frames this will be the frequencies where
+	   the psychoacoustics are calculated for */
+	Hann(gpsyInfo, transBuff, 2*psyInfo->size);
+	rsfft(transBuff, 11);
 
-    memcpy(temp, psyInfo->prevSamples, psyInfo->size*sizeof(double));
-    memcpy(temp + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
 
-    for (j = 0; j < 8; j++) {
+	/* 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;
 
-        memcpy(psyInfo->transBuffS[j], temp+(j*128)+(1024-128), 2*psyInfo->sizeS*sizeof(double));
+	tmp = psyInfo->fftPhMin2;
+	psyInfo->fftPhMin2 = psyInfo->fftPhMin1;
+	psyInfo->fftPhMin1 = psyInfo->fftPh;
+	psyInfo->fftPh = psyInfo->fftPhPlus1;
+	psyInfo->fftPhPlus1 = psyInfo->fftPhPlus2;
+	psyInfo->fftPhPlus2 = tmp;
 
-        Hann(gpsyInfo, psyInfo->transBuffS[j], 2*psyInfo->sizeS);
-        rsfft(psyInfo->transBuffS[j], 8);
 
-        /* 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);
-        }
-    }
+	/* Calculate magnitude and phase 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);
 
-    memcpy(psyInfo->prevSamples, newSamples, psyInfo->size*sizeof(double));
-}
+		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;
+		}
+	}
 
-void PsyBufferUpdateMS(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfoL, PsyInfo *psyInfoR)
-{
-    int i, j;
-    double a, b;
-    double dataL[2048], dataR[2048];
+	transBuffS = (double*)AllocMemory(2*psyInfo->sizeS*sizeof(double));
 
-    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;
-    }
+	memcpy(transBuff, psyInfo->prevSamples, psyInfo->size*sizeof(double));
+	memcpy(transBuff + psyInfo->size, newSamples, psyInfo->size*sizeof(double));
 
-    /* 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);
+	for (j = 0; j < 8; j++) {
 
-        a = dataR[i];
-        b = dataR[i+psyInfoL->size];
-        psyInfoR->energyMS[i] = 0.5 * (a*a + b*b);
-    }
+		memcpy(transBuffS, transBuff+(j*128)+(1024-128), 2*psyInfo->sizeS*sizeof(double));
 
-    for (j = 0; j < 8; j++) {
+		/* In 2 frames this will be the frequencies where
+		   the psychoacoustics are calculated for */
+		Hann(gpsyInfo, transBuffS, 2*psyInfo->sizeS);
+		rsfft(transBuff, 8);
 
-        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;
-        }
 
-        /* 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);
+		/* 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;
 
-            a = dataR[i];
-            b = dataR[i+psyInfoL->sizeS];
-            psyInfoR->energySMS[j][i] = 0.5 * (a*a + b*b);
-        }
-    }
-}
+		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;
 
-/* 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
-    };
 
-    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
-    };
+		/* 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);
 
-    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
-    };
+			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;
+			}
+		}
+	}
 
+	memcpy(psyInfo->prevSamples, newSamples, psyInfo->size*sizeof(double));
 
-    int i;
-    double m;
+	if (transBuff) FreeMemory(transBuff);
+	if (transBuffS) FreeMemory(transBuffS);
+}
 
-    if (m1 == 0) return m2;
+static void PsyUnpredictability(PsyInfo *psyInfo)
+{
+	int i, j;
+	double predMagMin, predMagPlus, predMag, mag;
+	double predPhMin, predPhPlus, predPh, ph;
 
-    if (b < 0) b = -b;
+	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;
+		}
 
-    i = (int)(10*log10(m2 / m1)/10*16);
-    m = 10*log10((m1+m2)/ath[k]);
+		mag = psyInfo->fftMag[i];
+		ph = psyInfo->fftPh[i];
 
-    if (i < 0) i = -i;
+		/* unpredictability */
+		psyInfo->cw[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];
-    }
+	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;
+		}
 
-    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];
-    }
+		mag = psyInfo->fftMagS[0][i];
+		ph = psyInfo->fftPhS[0][i];
 
-    if (i > 24) return m1+m2;
-    return (m1+m2)*table1[i];
-}
+		/* 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;
+		}
 
-static void PsyThreshold(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, int *cb_width_long,
-                         int num_cb_long, int *cb_width_short, int num_cb_short)
-{
-    int b, bb, w, low, high, j;
-    double tmp, ecb;
+		mag = psyInfo->fftMagS[1][i];
+		ph = psyInfo->fftPhS[1][i];
 
-    double e[MAX_NPART];
-    double c[MAX_NPART];
-    double maxi[MAX_NPART];
-    double avg[MAX_NPART];
-    double eb;
+		/* unpredictability */
+		psyInfo->cwS[1][i] =
+			sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
+	}
 
-    double nb_tmp[1024], epart, npart;
+	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;
+			}
 
-    double tot, mx, estot[8];
-    double pe = 0.0;
+			mag = psyInfo->fftMagS[j][i];
+			ph = psyInfo->fftPhS[j][i];
 
-    /* Energy in each partition and weighted unpredictability */
-    high = 0;
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        double m, a;
-        low = high;
-        high += gpsyInfo->psyPart->width[b];
+			/* unpredictability */
+			psyInfo->cwS[j][i] =
+				sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
+		}
+	}
 
-        eb = psyInfo->energy[low];
-        m = a = eb;
+	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;
+		}
 
-        for (w = low+1; w < high; 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];
-    }
+		mag = psyInfo->fftMagS[6][i];
+		ph = psyInfo->fftPhS[6][i];
 
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        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;
+		/* 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;
+		}
 
-        c1 = c2 = 0;
-        m = a = 0;
-        for(w = b-1; w <= b+1; w++)
-        {
-            if (w >= 0 && w < gpsyInfo->psyPart->len) {
-                c1++;
-                c2 += gpsyInfo->psyPart->width[w];
-                a += avg[w];
-                m = m < maxi[w] ? maxi[w] : m;
-            }
-        }
+		mag = psyInfo->fftMagS[7][i];
+		ph = psyInfo->fftPhS[7][i];
 
-        a /= c1;
-        tonality = (a == 0) ? 0 : (m / a - 1)/(c2-1);
+		/* unpredictability */
+		psyInfo->cwS[7][i] =
+			sqrt(mag*mag+predMag*predMag-2*mag*predMag*cos(ph+predPh))/(mag+fabs(predMag));
+	}
+}
 
-        t = (int)(20*tonality);
-        if (t > 19) t = 19;
-        psyInfo->tonality[b] = tab[t];
-        c[b] = e[b] * tab[t];
-    }
+static void PsyThreshold(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, int *cb_width_long,
+						 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;
 
-    /* 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;
+	double e[MAX_SCFAC_BANDS];
+	double c[MAX_SCFAC_BANDS];
 
-        /* Actual energy threshold */
-        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;
+	double tot, mx, estot[8];
+	double pe = 0.0;
 
-        /* Perceptual entropy */
-        tmp = gpsyInfo->psyPart->width[b]
-            * log((psyInfo->nb[b] + 0.0000000001)
-            / (e[b] + 0.0000000001));
-        tmp = min(0,tmp);
+	/* Energy in each partition and weighted unpredictability */
+	high = 0;
+	for (b = 0; b < num_cb_long; b++)
+	{
+		low = high;
+		high += cb_width_long[b];
 
-        pe -= tmp;
-    }
+		e[b] = 0.0;
+		c[b] = 0.0;
 
-    high = 0;
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        low = high;
-        high += gpsyInfo->psyPart->width[b];
+		for (w = low; w < high; w++)
+		{
+			tmp = psyInfo->fftMag[w];
+			tmp *= tmp;
+			e[b] += tmp;
+			c[b] += tmp * psyInfo->cw[w];
+		}
+	}
 
-        for (w = low; w < high; w++)
-        {
-            nb_tmp[w] = psyInfo->nb[b] / gpsyInfo->psyPart->width[b];
-        }
-    }
+	/* Convolve the partitioned energy and unpredictability
+	   with the spreading function */
+	for (b = 0; b < num_cb_long; b++)
+	{
+		ecb = 0.0;
+		ct = 0.0;
 
-    high = 0;
-    for (b = 0; b < num_cb_long; b++)
-    {
-        low = high;
-        high += cb_width_long[b];
+		for (bb = 0; bb < num_cb_long; bb++)
+		{
+			ecb += e[bb] * gpsyInfo->spreading[bb][b];
+			ct += c[bb] * gpsyInfo->spreading[bb][b];
+		}
+		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);
 
-        epart = psyInfo->energy[low];
-        npart = nb_tmp[low];
-        for (w = low+1; w < high; w++)
-        {
-            epart += psyInfo->energy[w];
+		/* Calculate the required SNR in each partition */
+		snr = tb * 18.0 + (1-tb) * 6.0;
 
-            if (nb_tmp[w] < npart)
-                npart = nb_tmp[w];
-        }
-        npart *= cb_width_long[b];
+		/* Power ratio */
+		bc = pow(10.0, 0.1*(-snr));
 
-        psyInfo->maskThr[b] = psyInfo->maskThrNext[b];
-        psyInfo->maskEn[b] = psyInfo->maskEnNext[b];
-        tmp = npart / epart;
-        psyInfo->maskThrNext[b] = npart;
-        psyInfo->maskEnNext[b] = epart;
-    }
+		/* Actual energy threshold */
+		nb = en * bc;
+		nb = max(min(nb, psyInfo->lastNb[b]*2), gpsyInfo->ath[b]);
+		psyInfo->lastNb[b] = en * bc;
 
-    /* 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++)
-        {
-            low = high;
-            high += gpsyInfo->psyPartS->width[b];
+		/* Perceptual entropy */
+		tmp = cb_width_long[b]
+			* log((nb + 0.0000000001)
+			/ (e[b] + 0.0000000001));
+		tmp = min(0,tmp);
 
-            eb = psyInfo->energyS[j][low];
+		pe -= tmp;
 
-            for (w = low+1; w < high; w++)
-            {
-                double el = psyInfo->energyS[j][w];
-                eb += el;
-            }
-            e[b] = eb;
-        }
+		psyInfo->maskThr[b] = psyInfo->maskThrNext[b];
+		psyInfo->maskEn[b] = psyInfo->maskEnNext[b];
+		psyInfo->maskThrNext[b] = nb;
+		psyInfo->maskEnNext[b] = en;
+	}
 
-        estot[j] = 0.0;
+	/* Short windows */
+	for (j = 0; j < 8; j++)
+	{
+		/* Energy in each partition and weighted unpredictability */
+		high = 0;
+		for (b = 0; b < num_cb_short; b++)
+		{
+			low = high;
+			high += cb_width_short[b];
 
-        /* Convolve the partitioned energy and unpredictability
-        with the spreading function */
-        for (b = 0; b < gpsyInfo->psyPartS->len; b++)
-        {
-            ecb = 0;
-            for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
-            {
-                ecb += gpsyInfo->spreadingS[b][bb] * e[bb];
-            }
+			e[b] = 0.0;
+			c[b] = 0.0;
 
-            /* Actual energy threshold */
-            psyInfo->nbS[j][b] = max(1e-6, ecb);
-/*
-            psyInfo->nbS[j][b] = max(psyInfo->nbS[j][b], gpsyInfo->athS[b]);
-*/
+			for (w = low; w < high; w++)
+			{
+				tmp = psyInfo->fftMagS[j][w];
+				tmp *= tmp;
+				e[b] += tmp;
+				c[b] += tmp * psyInfo->cwS[j][w];
+			}
+		}
 
-            estot[j] += e[b];
-        }
+		estot[j] = 0.0;
 
-        if (estot[j] != 0.0)
-            estot[j] /= gpsyInfo->psyPartS->len;
+		/* Convolve the partitioned energy and unpredictability
+		with the spreading function */
+		for (b = 0; b < num_cb_short; b++)
+		{
+			ecb = 0.0;
+			ct = 0.0;
 
-        high = 0;
-        for (b = 0; b < gpsyInfo->psyPartS->len; b++)
-        {
-            low = high;
-            high += gpsyInfo->psyPartS->width[b];
+			for (bb = 0; bb < num_cb_short; bb++)
+			{
+				ecb += e[bb] * gpsyInfo->spreadingS[bb][b];
+				ct += c[bb] * gpsyInfo->spreadingS[bb][b];
+			}
+			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);
 
-            for (w = low; w < high; w++)
-            {
-                nb_tmp[w] = psyInfo->nbS[j][b] / gpsyInfo->psyPartS->width[b];
-            }
-        }
+			/* 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));
 
-            epart = psyInfo->energyS[j][low];
-            npart = nb_tmp[low];
-            for (w = low+1; w < high; w++)
-            {
-                epart += psyInfo->energyS[j][w];
+			/* Actual energy threshold */
+			nb = en * bc;
+			nb = max(nb, gpsyInfo->athS[b]);
 
-                if (nb_tmp[w] < npart)
-                    npart = nb_tmp[w];
-            }
-            npart *= cb_width_short[b];
+			estot[j] += e[b];
 
-            psyInfo->maskThrS[j][b] = psyInfo->maskThrNextS[j][b];
-            psyInfo->maskEnS[j][b] = psyInfo->maskEnNextS[j][b];
-            psyInfo->maskThrNextS[j][b] = npart;
-            psyInfo->maskEnNextS[j][b] = epart;
-        }
-    }
+			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;
+		}
 
-    tot = mx = estot[0];
-    for (j = 1; j < 8; j++) {
-        tot += estot[j];
-        mx = max(mx, estot[j]);
-    }
+		if (estot[j] != 0.0)
+			estot[j] /= num_cb_short;
+	}
 
-#ifdef _DEBUG
-    printf("%4f %2.2f ", pe, mx/tot);
-#endif
+	tot = mx = estot[0];
+	for (j = 1; j < 8; j++) {
+		tot += estot[j];
+		mx = max(mx, estot[j]);
+	}
 
-    tot = max(tot, 1.e-12);
-    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.5) || (psyInfo->lastPe > 3000.0)) {
-        psyInfo->block_type = ONLY_SHORT_WINDOW;
-        psyInfo->threeInARow++;
-    } else if (psyInfo->threeInARow >= 3) {
-        psyInfo->block_type = ONLY_SHORT_WINDOW;
-        psyInfo->threeInARow = 0;
-    } else {
-        psyInfo->block_type = ONLY_LONG_WINDOW;
-    }
+	tot = max(tot, 1.e-12);
+	if (((mx/tot) > 0.25) && (pe > 1100.0) || ((mx/tot) > 0.5)) {
+		psyInfo->block_type = ONLY_SHORT_WINDOW;
+		psyInfo->threeInARow++;
+	} else if ((psyInfo->lastEnr > 0.35) && (psyInfo->lastPe > 1000.0)) {
+		psyInfo->block_type = ONLY_SHORT_WINDOW;
+		psyInfo->threeInARow++;
+	} else if (psyInfo->threeInARow >= 3) {
+		psyInfo->block_type = ONLY_SHORT_WINDOW;
+		psyInfo->threeInARow = 0;
+	} else
+		psyInfo->block_type = ONLY_LONG_WINDOW;
 
-    psyInfo->lastEnr = mx/tot;
-    psyInfo->pe = psyInfo->lastPe;
-    psyInfo->lastPe = pe;
+ 	psyInfo->lastEnr = mx/tot;
+	psyInfo->lastPe = pe;
 }
 
 static void PsyThresholdMS(ChannelInfo *channelInfoL, GlobalPsyInfo *gpsyInfo,
-                           PsyInfo *psyInfoL, PsyInfo *psyInfoR,
-                           int *cb_width_long, int num_cb_long, int *cb_width_short,
-                           int num_cb_short)
+						   PsyInfo *psyInfoL, PsyInfo *psyInfoR,
+						   int *cb_width_long, int num_cb_long, int *cb_width_short,
+						   int num_cb_short)
 {
-    int b, bb, w, low, high, j;
-    double ecb, tmp1, tmp2;
+	int b, bb, w, low, high, j;
+	double tmp, ct, ecb, cb;
+	double tb, snr, bc, enM, enS, nbM, nbS;
 
-    double nb_tmpM[1024];
-    double nb_tmpS[1024];
-    double epartM, epartS, npartM, npartS;
+	double eM[MAX_SCFAC_BANDS];
+	double eS[MAX_SCFAC_BANDS];
+	double cM[MAX_SCFAC_BANDS];
+	double cS[MAX_SCFAC_BANDS];
 
-    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;
 
-    double mld;
-
 #ifdef _DEBUG
-    int ms_used = 0;
-    int ms_usedS = 0;
+	int ms_used = 0;
+	int ms_usedS = 0;
 #endif
 
-    /* Energy in each partition and weighted unpredictability */
-    high = 0;
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        double mid, side, ebM, ebS;
-        low = high;
-        high += gpsyInfo->psyPart->width[b];
-
-        mid  = psyInfoL->energyMS[low];
-        side = psyInfoR->energyMS[low];
-
-        ebM = mid;
-        ebS = side;
-
-        for (w = low+1; w < high; w++)
-        {
-            mid  = psyInfoL->energyMS[w];
-            side = psyInfoR->energyMS[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]);
-    }
+	/* Energy in each partition and weighted unpredictability */
+	high = 0;
+	for (b = 0; b < num_cb_long; b++)
+	{
+		low = high;
+		high += cb_width_long[b];
 
-    /* Convolve the partitioned energy and unpredictability
-       with the spreading function */
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        /* Mid channel */
+		eM[b] = 0.0;
+		cM[b] = 0.0;
+		eS[b] = 0.0;
+		cS[b] = 0.0;
 
-        ecb = 0;
-        for (bb = gpsyInfo->sprInd[b][0]; bb <= gpsyInfo->sprInd[b][1]; bb++)
-        {
-            ecb = mask_add(ecb, gpsyInfo->spreading[bb][b] * cM[bb], bb, bb-b, gpsyInfo->ath);
-        }
-        ecb *= 0.158489319246111;
+		for (w = low; 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]);
 
-        /* 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;
+			tmp = (psyInfoL->fftMag[w] - psyInfoR->fftMag[w]) * 0.5;
+			tmp *= tmp;
+			eS[b] += tmp;
+			cS[b] += tmp * min(psyInfoL->cw[w], psyInfoR->cw[w]);
+		}
+	}
 
+	/* Convolve the partitioned energy and unpredictability
+	   with the spreading function */
+	for (b = 0; b < num_cb_long; b++)
+	{
+		/* Mid channel */
+		ecb = 0.0;
+		ct = 0.0;
 
-        /* Side channel */
+		for (bb = 0; bb < num_cb_long; bb++)
+		{
+			ecb += eM[bb] * gpsyInfo->spreading[bb][b];
+			ct += cM[bb] * gpsyInfo->spreading[bb][b];
+		}
+		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;
-        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;
+		/* Calculate the required SNR in each partition */
+		snr = tb * 18.0 + (1-tb) * 6.0;
 
-        /* Actual energy threshold */
-        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;
+		/* Power ratio */
+		bc = pow(10.0, 0.1*(-snr));
 
-        if (psyInfoL->nb[b] <= 1.58*psyInfoR->nb[b]
-            && psyInfoR->nb[b] <= 1.58*psyInfoL->nb[b]) {
+		/* Actual energy threshold */
+		nbM = enM * bc;
+		nbM = max(min(nbM, psyInfoL->lastNbMS[b]*2), gpsyInfo->ath[b]);
+		psyInfoL->lastNbMS[b] = enM * bc;
 
-            mld = gpsyInfo->mld[b]*eM[b];
-            tmp1 = max(nbM[b], min(nbS[b],mld));
 
-            mld = gpsyInfo->mld[b]*eS[b];
-            tmp2 = max(nbS[b], min(nbM[b],mld));
+		/* Side channel */
+		ecb = 0.0;
+		ct = 0.0;
 
-            nbM[b] = tmp1;
-            nbS[b] = tmp2;
-        }
-    }
+		for (bb = 0; bb < num_cb_long; bb++)
+		{
+			ecb += eS[bb] * gpsyInfo->spreading[bb][b];
+			ct += cS[bb] * gpsyInfo->spreading[bb][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);
 
-    high = 0;
-    for (b = 0; b < gpsyInfo->psyPart->len; b++)
-    {
-        low = high;
-        high += gpsyInfo->psyPart->width[b];
+		/* Calculate the required SNR in each partition */
+		snr = tb * 18.0 + (1-tb) * 6.0;
 
-        for (w = low; w < high; w++)
-        {
-            nb_tmpM[w] = nbM[b] / gpsyInfo->psyPart->width[b];
-            nb_tmpS[w] = nbS[b] / gpsyInfo->psyPart->width[b];
-        }
-    }
+		/* Power ratio */
+		bc = pow(10.0, 0.1*(-snr));
 
-    high = 0;
-    for (b = 0; b < num_cb_long; b++)
-    {
-        low = high;
-        high += cb_width_long[b];
+		/* Actual energy threshold */
+		nbS = enS * bc;
+		nbS = max(min(nbS, psyInfoR->lastNbMS[b]*2), gpsyInfo->ath[b]);
+		psyInfoR->lastNbMS[b] = enS * bc;
 
-        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];
+		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;
 
-            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];
+		if (psyInfoL->maskThr[b] <= 1.58*psyInfoR->maskThr[b]
+			&& psyInfoR->maskThr[b] <= 1.58*psyInfoL->maskThr[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;
+			mld = gpsyInfo->mld[b]*enM;
+			psyInfoL->maskThrMS[b] = max(psyInfoL->maskThrMS[b],
+				min(psyInfoR->maskThrMS[b],mld));
 
-        {
-            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]*enS;
+			psyInfoR->maskThrMS[b] = max(psyInfoR->maskThrMS[b],
+				min(psyInfoL->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;
-            }
+		x1 = min(psyInfoL->maskThr[b], psyInfoR->maskThr[b]);
+		x2 = max(psyInfoL->maskThr[b], psyInfoR->maskThr[b]);
+		/* thresholds difference in db */
+		if (x2 >= 1000*x1) db=3;
+		else db = log10(x2/x1);  
+		if (db < 0.25) {
+#ifdef _DEBUG
+			ms_used++;
+#endif
+			channelInfoL->msInfo.ms_used[b] = 1;
+		} else {
+			channelInfoL->msInfo.ms_used[b] = 0;
+		}
+	}
 
-            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);
+	printf("%d\t", 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];
+	/* Short windows */
+	for (j = 0; j < 8; j++)
+	{
+		/* Energy in each partition and weighted unpredictability */
+		high = 0;
+		for (b = 0; b < num_cb_short; b++)
+		{
+			low = high;
+			high += cb_width_short[b];
 
-            ebM = psyInfoL->energySMS[j][low];
-            ebS = psyInfoR->energySMS[j][low];
+			eM[b] = 0.0;
+			eS[b] = 0.0;
+			cM[b] = 0.0;
+			cS[b] = 0.0;
 
-            for (w = low+1; w < high; w++)
-            {
-                ebM += psyInfoL->energySMS[j][w];
-                ebS += psyInfoR->energySMS[j][w];
-            }
-            eM[b] = ebM;
-            eS[b] = ebS;
-        }
+			for (w = low; 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]);
 
-        /* Convolve the partitioned energy and unpredictability
-        with the spreading function */
-        for (b = 0; b < gpsyInfo->psyPartS->len; b++)
-        {
-            /* Mid channel */
+				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]);
 
-            /* 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]);
-*/
+		/* Convolve the partitioned energy and unpredictability
+		with the spreading function */
+		for (b = 0; b < num_cb_short; b++)
+		{
+			/* Mid channel */
+			ecb = 0.0;
+			ct = 0.0;
 
-            /* Side channel */
+			for (bb = 0; bb < num_cb_short; bb++)
+			{
+				ecb += eM[bb] * gpsyInfo->spreadingS[bb][b];
+				ct += cM[bb] * gpsyInfo->spreadingS[bb][b];
+			}
+			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);
 
-            /* Get power ratio */
-            ecb = 0;
-            for (bb = gpsyInfo->sprIndS[b][0]; bb <= gpsyInfo->sprIndS[b][1]; bb++)
-            {
-                ecb += gpsyInfo->spreadingS[b][bb] * eS[bb];
-            }
+			/* Calculate the required SNR in each partition */
+			snr = tb * 18.0 + (1-tb) * 6.0;
 
-            /* Actual energy threshold */
-            nbS[b] = max(1e-6, ecb);
-/*
-            nbS[b] = max(nbS[b], gpsyInfo->athS[b]);
-*/
+			/* Power ratio */
+			bc = pow(10.0, 0.1*(-snr));
 
-            if (psyInfoL->nbS[j][b] <= 1.58*psyInfoR->nbS[j][b]
-                && psyInfoR->nbS[j][b] <= 1.58*psyInfoL->nbS[j][b]) {
+			/* Actual energy threshold */
+			nbM = enM * bc;
+			nbM = max(nbM, gpsyInfo->athS[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));
+			/* Side channel */
+			ecb = 0.0;
+			ct = 0.0;
 
-                nbM[b] = tmp1;
-                nbS[b] = tmp2;
-            }
-        }
+			for (bb = 0; bb < num_cb_short; bb++)
+			{
+				ecb += eS[bb] * gpsyInfo->spreadingS[bb][b];
+				ct += cS[bb] * gpsyInfo->spreadingS[bb][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);
 
-        high = 0;
-        for (b = 0; b < gpsyInfo->psyPartS->len; b++)
-        {
-            low = high;
-            high += gpsyInfo->psyPartS->width[b];
+			/* Calculate the required SNR in each partition */
+			snr = tb * 18.0 + (1-tb) * 6.0;
 
-            for (w = low; w < high; w++)
-            {
-                nb_tmpM[w] = nbM[b] / gpsyInfo->psyPartS->width[b];
-                nb_tmpS[w] = nbS[b] / gpsyInfo->psyPartS->width[b];
-            }
-        }
+			/* Power ratio */
+			bc = pow(10.0, 0.1*(-snr));
 
-        high = 0;
-        for (b = 0; b < num_cb_short; b++)
-        {
-            low = high;
-            high += cb_width_short[b];
+			/* Actual energy threshold */
+			nbS = enS * bc;
+			nbS = max(nbS, gpsyInfo->athS[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];
+			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;
 
-                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];
+			if (psyInfoL->maskThrS[j][b] <= 1.58*psyInfoR->maskThrS[j][b]
+				&& psyInfoR->maskThrS[j][b] <= 1.58*psyInfoL->maskThrS[j][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;
+				mld = gpsyInfo->mldS[b]*enM;
+				psyInfoL->maskThrSMS[j][b] = max(psyInfoL->maskThrSMS[j][b],
+					min(psyInfoR->maskThrSMS[j][b],mld));
 
-            {
-                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]*enS;
+				psyInfoR->maskThrSMS[j][b] = max(psyInfoR->maskThrSMS[j][b],
+					min(psyInfoL->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;
-                }
+			x1 = min(psyInfoL->maskThrS[j][b], psyInfoR->maskThrS[j][b]);
+			x2 = max(psyInfoL->maskThrS[j][b], psyInfoR->maskThrS[j][b]);
+			/* thresholds difference in db */
+			if (x2 >= 1000*x1) db = 3;
+			else db = log10(x2/x1);
+			if (db < 0.25) {
+#ifdef _DEBUG
+				ms_usedS++;
+#endif
+				channelInfoL->msInfo.ms_usedS[j][b] = 1;
+			} else {
+				channelInfoL->msInfo.ms_usedS[j][b] = 0;
+			}
+		}
+	}
 
-                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);
+	printf("%d\t", ms_usedS);
 #endif
 }
 
 void BlockSwitch(CoderInfo *coderInfo, PsyInfo *psyInfo, unsigned int numChannels)
 {
-    unsigned int channel;
-    int desire = ONLY_LONG_WINDOW;
+	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;
-    }
+	/* 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
+	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;
+	}
 }
 
 static double freq2bark(double freq)
@@ -1141,9 +1166,9 @@
     double bark;
 
     if(freq > 200.0)
-        bark = 26.81 / (1 + (1960 / freq)) - 0.53;
+		bark = 26.81 / (1 + (1960 / freq)) - 0.53; 
     else
-        bark = freq / 102.9;
+		bark = freq / 102.9;
 
     return (bark);
 }
@@ -1150,200 +1175,15 @@
 
 static double ATHformula(double f)
 {
-    double ath;
-    f /= 1000;  /* convert to khz */
-    f  = max(0.01, f);
-    f  = min(18.0,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;
+	/* from Painter & Spanias, 1997 */
+	/* minimum: (i=77) 3.3kHz = -5db */
+	ath =    3.640 * pow(f,-0.8)
+		- 6.500 * exp(-0.6*pow(f-3.3,2.0))
+		+ 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
@@ -2,21 +2,21 @@
  * FAAC - Freeware Advanced Audio Coder
  * Copyright (C) 2001 Menno Bakker
  *
- * 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 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 2 of the License, or
+ * (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * 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
- * 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
+ * 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, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: psych.h,v 1.8 2001/06/08 18:01:09 menno Exp $
+ * $Id: psych.h,v 1.9 2001/09/09 16:03:16 menno Exp $
  */
 
 #ifndef PSYCH_H
@@ -26,116 +26,118 @@
 extern "C" {
 #endif /* __cplusplus */
 
+#ifndef M_PI
+#define M_PI        3.14159265358979323846
+#endif
+
 #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;
+	int size;
+	int sizeS;
 
-static PsyPartTable psyPartTableLong[12+1];
-static PsyPartTable psyPartTableShort[12+1];
+	/* Previous input samples */
+	double *prevSamples;
+	double *prevSamplesS;
 
-typedef struct {
-    int size;
-    int sizeS;
+	/* FFT data */
 
-    /* Previous input samples */
-    double *prevSamples;
-    double *prevSamplesS;
+	/* Magnitude */
+	double *fftMagPlus2;
+	double *fftMagPlus1;
+	double *fftMag;
+	double *fftMagMin1;
+	double *fftMagMin2;
 
-    /* FFT data */
+	double *fftMagPlus2S[8];
+	double *fftMagPlus1S[8];
+	double *fftMagS[8];
+	double *fftMagMin1S[8];
 
-    /* Magnitude */
-    double *energy;
-    double *energyS[8];
-    double *energyMS;
-    double *energySMS[8];
-    double *transBuff;
-    double *transBuffS[8];
+	/* Phase */
+	double *fftPhPlus2;
+	double *fftPhPlus1;
+	double *fftPh;
+	double *fftPhMin1;
+	double *fftPhMin2;
 
-    /* Tonality */
-    double *tonality;
+	double *fftPhPlus2S[8];
+	double *fftPhPlus1S[8];
+	double *fftPhS[8];
+	double *fftPhMin1S[8];
 
-    double lastPe;
-    double lastEnr;
-    int threeInARow;
-    int block_type;
+	/* Unpredictability */
+	double *cw;
+	double *cwS[8];
 
-    /* Final threshold values */
-    double pe;
-    double *nb;
-    double *nbS[8];
-    double *maskThr;
-    double *maskEn;
-    double *maskThrS[8];
-    double *maskEnS[8];
-    double *maskThrNext;
-    double *maskEnNext;
-    double *maskThrNextS[8];
-    double *maskEnNextS[8];
+	double lastPe;
+	double lastEnr;
+	int threeInARow;
+	int block_type;
 
-    double *lastNb;
-    double *lastNbMS;
+	/* Final threshold values */
+	double *maskThr;
+	double *maskEn;
+	double *maskThrS[8];
+	double *maskEnS[8];
+	double *maskThrNext;
+	double *maskEnNext;
+	double *maskThrNextS[8];
+	double *maskEnNextS[8];
 
-    double *maskThrMS;
-    double *maskEnMS;
-    double *maskThrSMS[8];
-    double *maskEnSMS[8];
-    double *maskThrNextMS;
-    double *maskEnNextMS;
-    double *maskThrNextSMS[8];
-    double *maskEnNextSMS[8];
+	double *lastNb;
+	double *lastNbMS;
+
+	double *maskThrMS;
+	double *maskEnMS;
+	double *maskThrSMS[8];
+	double *maskEnSMS[8];
+	double *maskThrNextMS;
+	double *maskEnNextMS;
+	double *maskThrNextSMS[8];
+	double *maskEnNextSMS[8];
 } PsyInfo;
 
 typedef struct {
-    double sampleRate;
+	double sampleRate;
 
-    /* Hann window */
-    double *window;
-    double *windowS;
+	/* Hann window */
+	double *hannWindow;
+	double *hannWindowS;
 
-    /* Stereo demasking thresholds */
-    double *mld;
-    double *mldS;
+	/* 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;
 
-    /* Spreading functions */
-    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;
-    double *athS;
+	/* Absolute threshold of hearing */
+	double *ath;
+	double *athS;
 } GlobalPsyInfo;
 
 void PsyInit(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, unsigned int numChannels,
-             unsigned int sampleRate, unsigned int sampleRateIdx);
+			 unsigned int sampleRate, int *cb_width_long, int num_cb_long,
+			 int *cb_width_short, int num_cb_short);
 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);
+				  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);
-__inline double mask_add(double m1, double m2, int k, int b, double *ath);
+static void PsyUnpredictability(PsyInfo *psyInfo);
 static void PsyThreshold(GlobalPsyInfo *gpsyInfo, PsyInfo *psyInfo, int *cb_width_long,
-                         int num_cb_long, int *cb_width_short, int num_cb_short);
+						 int num_cb_long, int *cb_width_short, int num_cb_short);
 static void PsyThresholdMS(ChannelInfo *channelInfoL, GlobalPsyInfo *gpsyInfo,
-                           PsyInfo *psyInfoL, PsyInfo *psyInfoR, int *cb_width_long,
-                           int num_cb_long, int *cb_width_short, int num_cb_short);
+						   PsyInfo *psyInfoL, PsyInfo *psyInfoR, int *cb_width_long,
+						   int num_cb_long, int *cb_width_short, int num_cb_short);
 static double freq2bark(double freq);
 static double ATHformula(double f);
 
@@ -143,4 +145,4 @@
 }
 #endif /* __cplusplus */
 
-#endif /* PSYCH_H */
+#endif /* PSYCH_H */
\ No newline at end of file