Two bugfixes (float) not (float *) and an optimization to
[platform/upstream/libvorbis.git] / lib / psy.c
index c02bab9..35df7e7 100644 (file)
--- a/lib/psy.c
+++ b/lib/psy.c
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: psychoacoustics not including preecho
- last mod: $Id: psy.c,v 1.35 2001/01/22 01:38:25 xiphmont Exp $
+ last mod: $Id: psy.c,v 1.40 2001/02/02 02:52:34 xiphmont Exp $
 
  ********************************************************************/
 
@@ -207,8 +207,8 @@ void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate){
     p->octave[i]=toOC((i*.5f+.25f)*rate/n)*(1<<(p->shiftoc+1))+.5f;
 
   p->tonecurves=_ogg_malloc(P_BANDS*sizeof(float **));
-  p->noisemedian=_ogg_malloc(n*sizeof(float *));
-  p->noiseoffset=_ogg_malloc(n*sizeof(float *));
+  p->noisemedian=_ogg_malloc(n*sizeof(float));
+  p->noiseoffset=_ogg_malloc(n*sizeof(float));
   p->peakatt=_ogg_malloc(P_BANDS*sizeof(float *));
   for(i=0;i<P_BANDS;i++){
     p->tonecurves[i]=_ogg_malloc(P_LEVELS*sizeof(float *));
@@ -323,6 +323,7 @@ void _vp_psy_clear(vorbis_look_psy *p){
       }
       _ogg_free(p->tonecurves);
       _ogg_free(p->noisemedian);
+      _ogg_free(p->noiseoffset);
       _ogg_free(p->peakatt);
     }
     memset(p,0,sizeof(vorbis_look_psy));
@@ -531,35 +532,50 @@ static void max_seeds(vorbis_look_psy *p,float *minseed,float *maxseed,
   
 }
 
-#define BIN(x) ((int)((x)*-4.))
-#define BINdB(x) ((x)*-.25)
+/* quarter-dB bins */
+#define BIN(x)   ((int)((x)*negFour))
+#define BINdB(x) ((x)*negQuarter)
+#define BINCOUNT (200*4)
+#define LASTBIN  (BINCOUNT-1)
+
 static void bark_noise_median(long n,float *b,float *f,float *noise,
                              float lowidth,float hiwidth,
                              int lomin,int himin,
                              float *thresh,float *off){
   long i=0,lo=0,hi=0;
-  long *radix=alloca(200*4*sizeof(long)); /* quarter-dB bins */
+  float bi,threshi;
+  long median=LASTBIN;
+  float negFour = -4.0f;
+  float negQuarter = -0.25f;
+
+   /* these are really integral values, but we store them in floats to
+      avoid excessive float/int conversions, which GCC and MSVC are
+      farily poor at optimizing. */
 
-  long countabove=0;
-  long median=200*4-1;
-  long countbelow=0;
+  float radix[BINCOUNT];
+  float countabove=0;
+  float countbelow=0;
 
-  memset(radix,0,200*4*sizeof(long));
+  memset(radix,0,sizeof(radix));
 
   for(i=0;i<n;i++){
     /* find new lo/hi */
-    for(;hi<n && (b[hi]<=b[i]+hiwidth || hi<i+himin);hi++){
+    bi=b[i]+hiwidth;
+    for(;hi<n && (hi<i+himin || b[hi]<=bi);hi++){
       int bin=BIN(f[hi]);
-      if(bin>=200*4)bin=200*4-1;
+      if(bin>LASTBIN)bin=LASTBIN;
+      if(bin<0)bin=0;
       radix[bin]++;
       if(bin<median)
        countabove++;
       else
        countbelow++;
     }
-    for(;lo<i && b[lo]+lowidth<=b[i] && lo+lomin<i;lo++){
+    bi=b[i]-lowidth;
+    for(;lo<i && lo+lomin<i && b[lo]<=bi;lo++){
       int bin=BIN(f[lo]);
-      if(bin>=200*4)bin=200*4-1;
+      if(bin>LASTBIN)bin=LASTBIN;
+      if(bin<0)bin=0;
       radix[bin]--;
       if(bin<median)
        countabove--;
@@ -569,15 +585,16 @@ static void bark_noise_median(long n,float *b,float *f,float *noise,
 
     /* move the median if needed */
     if(countabove+countbelow){
+      threshi = thresh[i]*(countabove+countbelow);
 
-      while(thresh[i]>countbelow/(float)(countabove+countbelow) && median>0){
+      while(threshi>countbelow && median>0){
        median--;
        countabove-=radix[median];
        countbelow+=radix[median];
       }
 
-      while(thresh[i]<(countbelow-radix[median])/
-           (float)(countabove+countbelow) && median+1<200*4){
+      while(threshi<(countbelow-radix[median]) &&
+           median<LASTBIN){
        countabove+=radix[median];
        countbelow-=radix[median];
        median++;
@@ -593,9 +610,9 @@ float _vp_compute_mask(vorbis_look_psy *p,
                      float *mdct, 
                      float *flr, 
                      float *decay,
-                     float prev_maxamp){
+                     float specmax){
   int i,n=p->n;
-  float specmax=NEGINF;
+  float localmax=NEGINF;
   static int seq=0;
 
   float *minseed=alloca(sizeof(float)*p->total_octave_lines);
@@ -605,9 +622,9 @@ float _vp_compute_mask(vorbis_look_psy *p,
   /* go to dB scale. Also find the highest peak so we know the limits */
   for(i=0;i<n;i++){
     fft[i]=todB(fft[i]);
-    if(fft[i]>specmax)specmax=fft[i];
+    if(fft[i]>localmax)localmax=fft[i];
   }
-  if(specmax<prev_maxamp)specmax=prev_maxamp;
+  if(specmax<localmax)specmax=localmax;
 
 
   for(i=0;i<n;i++){
@@ -635,9 +652,10 @@ float _vp_compute_mask(vorbis_look_psy *p,
     for(i=0;i<n;i++)flr[i]=NEGINF;
   }
 
-  /* set the ATH (floating below specmax by a specified att) */
+  /* set the ATH (floating below localmax, not global max by a
+     specified att) */
   if(p->vi->athp){
-    float att=specmax+p->vi->ath_adjatt;
+    float att=localmax+p->vi->ath_adjatt;
     if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
 
     for(i=0;i<n;i++){