Blame lib/psy.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: psychoacoustics not including preecho
Packit 06404a
 last mod: $Id: psy.c 18077 2011-09-02 02:49:00Z giles $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include "vorbis/codec.h"
Packit 06404a
#include "codec_internal.h"
Packit 06404a
Packit 06404a
#include "masking.h"
Packit 06404a
#include "psy.h"
Packit 06404a
#include "os.h"
Packit 06404a
#include "lpc.h"
Packit 06404a
#include "smallft.h"
Packit 06404a
#include "scales.h"
Packit 06404a
#include "misc.h"
Packit 06404a
Packit 06404a
#define NEGINF -9999.f
Packit 06404a
static const double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10};
Packit 06404a
static const double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10};
Packit 06404a
Packit 06404a
vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy_global *gi=&ci->psy_g_param;
Packit 06404a
  vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look));
Packit 06404a
Packit 06404a
  look->channels=vi->channels;
Packit 06404a
Packit 06404a
  look->ampmax=-9999.;
Packit 06404a
  look->gi=gi;
Packit 06404a
  return(look);
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_global_free(vorbis_look_psy_global *look){
Packit 06404a
  if(look){
Packit 06404a
    memset(look,0,sizeof(*look));
Packit 06404a
    _ogg_free(look);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vi_gpsy_free(vorbis_info_psy_global *i){
Packit 06404a
  if(i){
Packit 06404a
    memset(i,0,sizeof(*i));
Packit 06404a
    _ogg_free(i);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vi_psy_free(vorbis_info_psy *i){
Packit 06404a
  if(i){
Packit 06404a
    memset(i,0,sizeof(*i));
Packit 06404a
    _ogg_free(i);
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void min_curve(float *c,
Packit 06404a
                       float *c2){
Packit 06404a
  int i;
Packit 06404a
  for(i=0;i
Packit 06404a
}
Packit 06404a
static void max_curve(float *c,
Packit 06404a
                       float *c2){
Packit 06404a
  int i;
Packit 06404a
  for(i=0;i<EHMER_MAX;i++)if(c2[i]>c[i])c[i]=c2[i];
Packit 06404a
}
Packit 06404a
Packit 06404a
static void attenuate_curve(float *c,float att){
Packit 06404a
  int i;
Packit 06404a
  for(i=0;i
Packit 06404a
    c[i]+=att;
Packit 06404a
}
Packit 06404a
Packit 06404a
static float ***setup_tone_curves(float curveatt_dB[P_BANDS],float binHz,int n,
Packit 06404a
                                  float center_boost, float center_decay_rate){
Packit 06404a
  int i,j,k,m;
Packit 06404a
  float ath[EHMER_MAX];
Packit 06404a
  float workc[P_BANDS][P_LEVELS][EHMER_MAX];
Packit 06404a
  float athc[P_LEVELS][EHMER_MAX];
Packit 06404a
  float *brute_buffer=alloca(n*sizeof(*brute_buffer));
Packit 06404a
Packit 06404a
  float ***ret=_ogg_malloc(sizeof(*ret)*P_BANDS);
Packit 06404a
Packit 06404a
  memset(workc,0,sizeof(workc));
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    /* we add back in the ATH to avoid low level curves falling off to
Packit 06404a
       -infinity and unnecessarily cutting off high level curves in the
Packit 06404a
       curve limiting (last step). */
Packit 06404a
Packit 06404a
    /* A half-band's settings must be valid over the whole band, and
Packit 06404a
       it's better to mask too little than too much */
Packit 06404a
    int ath_offset=i*4;
Packit 06404a
    for(j=0;j
Packit 06404a
      float min=999.;
Packit 06404a
      for(k=0;k<4;k++)
Packit 06404a
        if(j+k+ath_offset
Packit 06404a
          if(min>ATH[j+k+ath_offset])min=ATH[j+k+ath_offset];
Packit 06404a
        }else{
Packit 06404a
          if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1];
Packit 06404a
        }
Packit 06404a
      ath[j]=min;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* copy curves into working space, replicate the 50dB curve to 30
Packit 06404a
       and 40, replicate the 100dB curve to 110 */
Packit 06404a
    for(j=0;j<6;j++)
Packit 06404a
      memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j]));
Packit 06404a
    memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
Packit 06404a
    memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
Packit 06404a
Packit 06404a
    /* apply centered curve boost/decay */
Packit 06404a
    for(j=0;j
Packit 06404a
      for(k=0;k
Packit 06404a
        float adj=center_boost+abs(EHMER_OFFSET-k)*center_decay_rate;
Packit 06404a
        if(adj<0. && center_boost>0)adj=0.;
Packit 06404a
        if(adj>0. && center_boost<0)adj=0.;
Packit 06404a
        workc[i][j][k]+=adj;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* normalize curves so the driving amplitude is 0dB */
Packit 06404a
    /* make temp curves with the ATH overlayed */
Packit 06404a
    for(j=0;j
Packit 06404a
      attenuate_curve(workc[i][j],curveatt_dB[i]+100.-(j<2?2:j)*10.-P_LEVEL_0);
Packit 06404a
      memcpy(athc[j],ath,EHMER_MAX*sizeof(**athc));
Packit 06404a
      attenuate_curve(athc[j],+100.-j*10.f-P_LEVEL_0);
Packit 06404a
      max_curve(athc[j],workc[i][j]);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* Now limit the louder curves.
Packit 06404a
Packit 06404a
       the idea is this: We don't know what the playback attenuation
Packit 06404a
       will be; 0dB SL moves every time the user twiddles the volume
Packit 06404a
       knob. So that means we have to use a single 'most pessimal' curve
Packit 06404a
       for all masking amplitudes, right?  Wrong.  The *loudest* sound
Packit 06404a
       can be in (we assume) a range of ...+100dB] SL.  However, sounds
Packit 06404a
       20dB down will be in a range ...+80], 40dB down is from ...+60],
Packit 06404a
       etc... */
Packit 06404a
Packit 06404a
    for(j=1;j
Packit 06404a
      min_curve(athc[j],athc[j-1]);
Packit 06404a
      min_curve(workc[i][j],athc[j]);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    int hi_curve,lo_curve,bin;
Packit 06404a
    ret[i]=_ogg_malloc(sizeof(**ret)*P_LEVELS);
Packit 06404a
Packit 06404a
    /* low frequency curves are measured with greater resolution than
Packit 06404a
       the MDCT/FFT will actually give us; we want the curve applied
Packit 06404a
       to the tone data to be pessimistic and thus apply the minimum
Packit 06404a
       masking possible for a given bin.  That means that a single bin
Packit 06404a
       could span more than one octave and that the curve will be a
Packit 06404a
       composite of multiple octaves.  It also may mean that a single
Packit 06404a
       bin may span > an eighth of an octave and that the eighth
Packit 06404a
       octave values may also be composited. */
Packit 06404a
Packit 06404a
    /* which octave curves will we be compositing? */
Packit 06404a
    bin=floor(fromOC(i*.5)/binHz);
Packit 06404a
    lo_curve=  ceil(toOC(bin*binHz+1)*2);
Packit 06404a
    hi_curve=  floor(toOC((bin+1)*binHz)*2);
Packit 06404a
    if(lo_curve>i)lo_curve=i;
Packit 06404a
    if(lo_curve<0)lo_curve=0;
Packit 06404a
    if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1;
Packit 06404a
Packit 06404a
    for(m=0;m
Packit 06404a
      ret[i][m]=_ogg_malloc(sizeof(***ret)*(EHMER_MAX+2));
Packit 06404a
Packit 06404a
      for(j=0;j
Packit 06404a
Packit 06404a
      /* render the curve into bins, then pull values back into curve.
Packit 06404a
         The point is that any inherent subsampling aliasing results in
Packit 06404a
         a safe minimum */
Packit 06404a
      for(k=lo_curve;k<=hi_curve;k++){
Packit 06404a
        int l=0;
Packit 06404a
Packit 06404a
        for(j=0;j
Packit 06404a
          int lo_bin= fromOC(j*.125+k*.5-2.0625)/binHz;
Packit 06404a
          int hi_bin= fromOC(j*.125+k*.5-1.9375)/binHz+1;
Packit 06404a
Packit 06404a
          if(lo_bin<0)lo_bin=0;
Packit 06404a
          if(lo_bin>n)lo_bin=n;
Packit 06404a
          if(lo_bin
Packit 06404a
          if(hi_bin<0)hi_bin=0;
Packit 06404a
          if(hi_bin>n)hi_bin=n;
Packit 06404a
Packit 06404a
          for(;l
Packit 06404a
            if(brute_buffer[l]>workc[k][m][j])
Packit 06404a
              brute_buffer[l]=workc[k][m][j];
Packit 06404a
        }
Packit 06404a
Packit 06404a
        for(;l
Packit 06404a
          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
Packit 06404a
            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
Packit 06404a
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* be equally paranoid about being valid up to next half ocatve */
Packit 06404a
      if(i+1
Packit 06404a
        int l=0;
Packit 06404a
        k=i+1;
Packit 06404a
        for(j=0;j
Packit 06404a
          int lo_bin= fromOC(j*.125+i*.5-2.0625)/binHz;
Packit 06404a
          int hi_bin= fromOC(j*.125+i*.5-1.9375)/binHz+1;
Packit 06404a
Packit 06404a
          if(lo_bin<0)lo_bin=0;
Packit 06404a
          if(lo_bin>n)lo_bin=n;
Packit 06404a
          if(lo_bin
Packit 06404a
          if(hi_bin<0)hi_bin=0;
Packit 06404a
          if(hi_bin>n)hi_bin=n;
Packit 06404a
Packit 06404a
          for(;l
Packit 06404a
            if(brute_buffer[l]>workc[k][m][j])
Packit 06404a
              brute_buffer[l]=workc[k][m][j];
Packit 06404a
        }
Packit 06404a
Packit 06404a
        for(;l
Packit 06404a
          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
Packit 06404a
            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
Packit 06404a
Packit 06404a
      }
Packit 06404a
Packit 06404a
Packit 06404a
      for(j=0;j
Packit 06404a
        int bin=fromOC(j*.125+i*.5-2.)/binHz;
Packit 06404a
        if(bin<0){
Packit 06404a
          ret[i][m][j+2]=-999.;
Packit 06404a
        }else{
Packit 06404a
          if(bin>=n){
Packit 06404a
            ret[i][m][j+2]=-999.;
Packit 06404a
          }else{
Packit 06404a
            ret[i][m][j+2]=brute_buffer[bin];
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* add fenceposts */
Packit 06404a
      for(j=0;j
Packit 06404a
        if(ret[i][m][j+2]>-200.f)break;
Packit 06404a
      ret[i][m][0]=j;
Packit 06404a
Packit 06404a
      for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--)
Packit 06404a
        if(ret[i][m][j+2]>-200.f)
Packit 06404a
          break;
Packit 06404a
      ret[i][m][1]=j;
Packit 06404a
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(ret);
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
Packit 06404a
                  vorbis_info_psy_global *gi,int n,long rate){
Packit 06404a
  long i,j,lo=-99,hi=1;
Packit 06404a
  long maxoc;
Packit 06404a
  memset(p,0,sizeof(*p));
Packit 06404a
Packit 06404a
  p->eighth_octave_lines=gi->eighth_octave_lines;
Packit 06404a
  p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1;
Packit 06404a
Packit 06404a
  p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines;
Packit 06404a
  maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f;
Packit 06404a
  p->total_octave_lines=maxoc-p->firstoc+1;
Packit 06404a
  p->ath=_ogg_malloc(n*sizeof(*p->ath));
Packit 06404a
Packit 06404a
  p->octave=_ogg_malloc(n*sizeof(*p->octave));
Packit 06404a
  p->bark=_ogg_malloc(n*sizeof(*p->bark));
Packit 06404a
  p->vi=vi;
Packit 06404a
  p->n=n;
Packit 06404a
  p->rate=rate;
Packit 06404a
Packit 06404a
  /* AoTuV HF weighting */
Packit 06404a
  p->m_val = 1.;
Packit 06404a
  if(rate < 26000) p->m_val = 0;
Packit 06404a
  else if(rate < 38000) p->m_val = .94;   /* 32kHz */
Packit 06404a
  else if(rate > 46000) p->m_val = 1.275; /* 48kHz */
Packit 06404a
Packit 06404a
  /* set up the lookups for a given blocksize and sample rate */
Packit 06404a
Packit 06404a
  for(i=0,j=0;i
Packit 06404a
    int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate);
Packit 06404a
    float base=ATH[i];
Packit 06404a
    if(j
Packit 06404a
      float delta=(ATH[i+1]-base)/(endpos-j);
Packit 06404a
      for(;j
Packit 06404a
        p->ath[j]=base+100.;
Packit 06404a
        base+=delta;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(;j
Packit 06404a
    p->ath[j]=p->ath[j-1];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    float bark=toBARK(rate/(2*n)*i);
Packit 06404a
Packit 06404a
    for(;lo+vi->noisewindowlomin
Packit 06404a
          toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++);
Packit 06404a
Packit 06404a
    for(;hi<=n && (hi<i+vi->noisewindowhimin ||
Packit 06404a
          toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++);
Packit 06404a
Packit 06404a
    p->bark[i]=((lo-1)<<16)+(hi-1);
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f;
Packit 06404a
Packit 06404a
  p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n,
Packit 06404a
                                  vi->tone_centerboost,vi->tone_decay);
Packit 06404a
Packit 06404a
  /* set up rolling noise median */
Packit 06404a
  p->noiseoffset=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset));
Packit 06404a
  for(i=0;i
Packit 06404a
    p->noiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset));
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    float halfoc=toOC((i+.5)*rate/(2.*n))*2.;
Packit 06404a
    int inthalfoc;
Packit 06404a
    float del;
Packit 06404a
Packit 06404a
    if(halfoc<0)halfoc=0;
Packit 06404a
    if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1;
Packit 06404a
    inthalfoc=(int)halfoc;
Packit 06404a
    del=halfoc-inthalfoc;
Packit 06404a
Packit 06404a
    for(j=0;j
Packit 06404a
      p->noiseoffset[j][i]=
Packit 06404a
        p->vi->noiseoff[j][inthalfoc]*(1.-del) +
Packit 06404a
        p->vi->noiseoff[j][inthalfoc+1]*del;
Packit 06404a
Packit 06404a
  }
Packit 06404a
#if 0
Packit 06404a
  {
Packit 06404a
    static int ls=0;
Packit 06404a
    _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0);
Packit 06404a
    _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0);
Packit 06404a
    _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0);
Packit 06404a
  }
Packit 06404a
#endif
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_psy_clear(vorbis_look_psy *p){
Packit 06404a
  int i,j;
Packit 06404a
  if(p){
Packit 06404a
    if(p->ath)_ogg_free(p->ath);
Packit 06404a
    if(p->octave)_ogg_free(p->octave);
Packit 06404a
    if(p->bark)_ogg_free(p->bark);
Packit 06404a
    if(p->tonecurves){
Packit 06404a
      for(i=0;i
Packit 06404a
        for(j=0;j
Packit 06404a
          _ogg_free(p->tonecurves[i][j]);
Packit 06404a
        }
Packit 06404a
        _ogg_free(p->tonecurves[i]);
Packit 06404a
      }
Packit 06404a
      _ogg_free(p->tonecurves);
Packit 06404a
    }
Packit 06404a
    if(p->noiseoffset){
Packit 06404a
      for(i=0;i
Packit 06404a
        _ogg_free(p->noiseoffset[i]);
Packit 06404a
      }
Packit 06404a
      _ogg_free(p->noiseoffset);
Packit 06404a
    }
Packit 06404a
    memset(p,0,sizeof(*p));
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
/* octave/(8*eighth_octave_lines) x scale and dB y scale */
Packit 06404a
static void seed_curve(float *seed,
Packit 06404a
                       const float **curves,
Packit 06404a
                       float amp,
Packit 06404a
                       int oc, int n,
Packit 06404a
                       int linesper,float dBoffset){
Packit 06404a
  int i,post1;
Packit 06404a
  int seedptr;
Packit 06404a
  const float *posts,*curve;
Packit 06404a
Packit 06404a
  int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f);
Packit 06404a
  choice=max(choice,0);
Packit 06404a
  choice=min(choice,P_LEVELS-1);
Packit 06404a
  posts=curves[choice];
Packit 06404a
  curve=posts+2;
Packit 06404a
  post1=(int)posts[1];
Packit 06404a
  seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1);
Packit 06404a
Packit 06404a
  for(i=posts[0];i
Packit 06404a
    if(seedptr>0){
Packit 06404a
      float lin=amp+curve[i];
Packit 06404a
      if(seed[seedptr]
Packit 06404a
    }
Packit 06404a
    seedptr+=linesper;
Packit 06404a
    if(seedptr>=n)break;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void seed_loop(vorbis_look_psy *p,
Packit 06404a
                      const float ***curves,
Packit 06404a
                      const float *f,
Packit 06404a
                      const float *flr,
Packit 06404a
                      float *seed,
Packit 06404a
                      float specmax){
Packit 06404a
  vorbis_info_psy *vi=p->vi;
Packit 06404a
  long n=p->n,i;
Packit 06404a
  float dBoffset=vi->max_curve_dB-specmax;
Packit 06404a
Packit 06404a
  /* prime the working vector with peak values */
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    float max=f[i];
Packit 06404a
    long oc=p->octave[i];
Packit 06404a
    while(i+1<n && p->octave[i+1]==oc){
Packit 06404a
      i++;
Packit 06404a
      if(f[i]>max)max=f[i];
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(max+6.f>flr[i]){
Packit 06404a
      oc=oc>>p->shiftoc;
Packit 06404a
Packit 06404a
      if(oc>=P_BANDS)oc=P_BANDS-1;
Packit 06404a
      if(oc<0)oc=0;
Packit 06404a
Packit 06404a
      seed_curve(seed,
Packit 06404a
                 curves[oc],
Packit 06404a
                 max,
Packit 06404a
                 p->octave[i]-p->firstoc,
Packit 06404a
                 p->total_octave_lines,
Packit 06404a
                 p->eighth_octave_lines,
Packit 06404a
                 dBoffset);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
static void seed_chase(float *seeds, int linesper, long n){
Packit 06404a
  long  *posstack=alloca(n*sizeof(*posstack));
Packit 06404a
  float *ampstack=alloca(n*sizeof(*ampstack));
Packit 06404a
  long   stack=0;
Packit 06404a
  long   pos=0;
Packit 06404a
  long   i;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    if(stack<2){
Packit 06404a
      posstack[stack]=i;
Packit 06404a
      ampstack[stack++]=seeds[i];
Packit 06404a
    }else{
Packit 06404a
      while(1){
Packit 06404a
        if(seeds[i]
Packit 06404a
          posstack[stack]=i;
Packit 06404a
          ampstack[stack++]=seeds[i];
Packit 06404a
          break;
Packit 06404a
        }else{
Packit 06404a
          if(i
Packit 06404a
            if(stack>1 && ampstack[stack-1]<=ampstack[stack-2] &&
Packit 06404a
               i
Packit 06404a
              /* we completely overlap, making stack-1 irrelevant.  pop it */
Packit 06404a
              stack--;
Packit 06404a
              continue;
Packit 06404a
            }
Packit 06404a
          }
Packit 06404a
          posstack[stack]=i;
Packit 06404a
          ampstack[stack++]=seeds[i];
Packit 06404a
          break;
Packit 06404a
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* the stack now contains only the positions that are relevant. Scan
Packit 06404a
     'em straight through */
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    long endpos;
Packit 06404a
    if(i<stack-1 && ampstack[i+1]>ampstack[i]){
Packit 06404a
      endpos=posstack[i+1];
Packit 06404a
    }else{
Packit 06404a
      endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is
Packit 06404a
                                        discarded in short frames */
Packit 06404a
    }
Packit 06404a
    if(endpos>n)endpos=n;
Packit 06404a
    for(;pos
Packit 06404a
      seeds[pos]=ampstack[i];
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* there.  Linear time.  I now remember this was on a problem set I
Packit 06404a
     had in Grad Skool... I didn't solve it at the time ;-) */
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
/* bleaugh, this is more complicated than it needs to be */
Packit 06404a
#include<stdio.h>
Packit 06404a
static void max_seeds(vorbis_look_psy *p,
Packit 06404a
                      float *seed,
Packit 06404a
                      float *flr){
Packit 06404a
  long   n=p->total_octave_lines;
Packit 06404a
  int    linesper=p->eighth_octave_lines;
Packit 06404a
  long   linpos=0;
Packit 06404a
  long   pos;
Packit 06404a
Packit 06404a
  seed_chase(seed,linesper,n); /* for masking */
Packit 06404a
Packit 06404a
  pos=p->octave[0]-p->firstoc-(linesper>>1);
Packit 06404a
Packit 06404a
  while(linpos+1<p->n){
Packit 06404a
    float minV=seed[pos];
Packit 06404a
    long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc;
Packit 06404a
    if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit;
Packit 06404a
    while(pos+1<=end){
Packit 06404a
      pos++;
Packit 06404a
      if((seed[pos]>NEGINF && seed[pos]
Packit 06404a
        minV=seed[pos];
Packit 06404a
    }
Packit 06404a
Packit 06404a
    end=pos+p->firstoc;
Packit 06404a
    for(;linpos<p->n && p->octave[linpos]<=end;linpos++)
Packit 06404a
      if(flr[linpos]
Packit 06404a
  }
Packit 06404a
Packit 06404a
  {
Packit 06404a
    float minV=seed[p->total_octave_lines-1];
Packit 06404a
    for(;linpos<p->n;linpos++)
Packit 06404a
      if(flr[linpos]
Packit 06404a
  }
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
static void bark_noise_hybridmp(int n,const long *b,
Packit 06404a
                                const float *f,
Packit 06404a
                                float *noise,
Packit 06404a
                                const float offset,
Packit 06404a
                                const int fixed){
Packit 06404a
Packit 06404a
  float *N=alloca(n*sizeof(*N));
Packit 06404a
  float *X=alloca(n*sizeof(*N));
Packit 06404a
  float *XX=alloca(n*sizeof(*N));
Packit 06404a
  float *Y=alloca(n*sizeof(*N));
Packit 06404a
  float *XY=alloca(n*sizeof(*N));
Packit 06404a
Packit 06404a
  float tN, tX, tXX, tY, tXY;
Packit 06404a
  int i;
Packit 06404a
Packit 06404a
  int lo, hi;
Packit 06404a
  float R=0.f;
Packit 06404a
  float A=0.f;
Packit 06404a
  float B=0.f;
Packit 06404a
  float D=1.f;
Packit 06404a
  float w, x, y;
Packit 06404a
Packit 06404a
  tN = tX = tXX = tY = tXY = 0.f;
Packit 06404a
Packit 06404a
  y = f[0] + offset;
Packit 06404a
  if (y < 1.f) y = 1.f;
Packit 06404a
Packit 06404a
  w = y * y * .5;
Packit 06404a
Packit 06404a
  tN += w;
Packit 06404a
  tX += w;
Packit 06404a
  tY += w * y;
Packit 06404a
Packit 06404a
  N[0] = tN;
Packit 06404a
  X[0] = tX;
Packit 06404a
  XX[0] = tXX;
Packit 06404a
  Y[0] = tY;
Packit 06404a
  XY[0] = tXY;
Packit 06404a
Packit 06404a
  for (i = 1, x = 1.f; i < n; i++, x += 1.f) {
Packit 06404a
Packit 06404a
    y = f[i] + offset;
Packit 06404a
    if (y < 1.f) y = 1.f;
Packit 06404a
Packit 06404a
    w = y * y;
Packit 06404a
Packit 06404a
    tN += w;
Packit 06404a
    tX += w * x;
Packit 06404a
    tXX += w * x * x;
Packit 06404a
    tY += w * y;
Packit 06404a
    tXY += w * x * y;
Packit 06404a
Packit 06404a
    N[i] = tN;
Packit 06404a
    X[i] = tX;
Packit 06404a
    XX[i] = tXX;
Packit 06404a
    Y[i] = tY;
Packit 06404a
    XY[i] = tXY;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for (i = 0, x = 0.f;; i++, x += 1.f) {
Packit 06404a
Packit 06404a
    lo = b[i] >> 16;
Packit 06404a
    if( lo>=0 ) break;
Packit 06404a
    hi = b[i] & 0xffff;
Packit 06404a
Packit 06404a
    tN = N[hi] + N[-lo];
Packit 06404a
    tX = X[hi] - X[-lo];
Packit 06404a
    tXX = XX[hi] + XX[-lo];
Packit 06404a
    tY = Y[hi] + Y[-lo];
Packit 06404a
    tXY = XY[hi] - XY[-lo];
Packit 06404a
Packit 06404a
    A = tY * tXX - tX * tXY;
Packit 06404a
    B = tN * tXY - tX * tY;
Packit 06404a
    D = tN * tXX - tX * tX;
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
    if (R < 0.f)
Packit 06404a
      R = 0.f;
Packit 06404a
Packit 06404a
    noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for ( ;; i++, x += 1.f) {
Packit 06404a
Packit 06404a
    lo = b[i] >> 16;
Packit 06404a
    hi = b[i] & 0xffff;
Packit 06404a
    if(hi>=n)break;
Packit 06404a
Packit 06404a
    tN = N[hi] - N[lo];
Packit 06404a
    tX = X[hi] - X[lo];
Packit 06404a
    tXX = XX[hi] - XX[lo];
Packit 06404a
    tY = Y[hi] - Y[lo];
Packit 06404a
    tXY = XY[hi] - XY[lo];
Packit 06404a
Packit 06404a
    A = tY * tXX - tX * tXY;
Packit 06404a
    B = tN * tXY - tX * tY;
Packit 06404a
    D = tN * tXX - tX * tX;
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
    if (R < 0.f) R = 0.f;
Packit 06404a
Packit 06404a
    noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
  for ( ; i < n; i++, x += 1.f) {
Packit 06404a
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
    if (R < 0.f) R = 0.f;
Packit 06404a
Packit 06404a
    noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if (fixed <= 0) return;
Packit 06404a
Packit 06404a
  for (i = 0, x = 0.f;; i++, x += 1.f) {
Packit 06404a
    hi = i + fixed / 2;
Packit 06404a
    lo = hi - fixed;
Packit 06404a
    if(lo>=0)break;
Packit 06404a
Packit 06404a
    tN = N[hi] + N[-lo];
Packit 06404a
    tX = X[hi] - X[-lo];
Packit 06404a
    tXX = XX[hi] + XX[-lo];
Packit 06404a
    tY = Y[hi] + Y[-lo];
Packit 06404a
    tXY = XY[hi] - XY[-lo];
Packit 06404a
Packit 06404a
Packit 06404a
    A = tY * tXX - tX * tXY;
Packit 06404a
    B = tN * tXY - tX * tY;
Packit 06404a
    D = tN * tXX - tX * tX;
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
Packit 06404a
    if (R - offset < noise[i]) noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
  for ( ;; i++, x += 1.f) {
Packit 06404a
Packit 06404a
    hi = i + fixed / 2;
Packit 06404a
    lo = hi - fixed;
Packit 06404a
    if(hi>=n)break;
Packit 06404a
Packit 06404a
    tN = N[hi] - N[lo];
Packit 06404a
    tX = X[hi] - X[lo];
Packit 06404a
    tXX = XX[hi] - XX[lo];
Packit 06404a
    tY = Y[hi] - Y[lo];
Packit 06404a
    tXY = XY[hi] - XY[lo];
Packit 06404a
Packit 06404a
    A = tY * tXX - tX * tXY;
Packit 06404a
    B = tN * tXY - tX * tY;
Packit 06404a
    D = tN * tXX - tX * tX;
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
Packit 06404a
    if (R - offset < noise[i]) noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
  for ( ; i < n; i++, x += 1.f) {
Packit 06404a
    R = (A + x * B) / D;
Packit 06404a
    if (R - offset < noise[i]) noise[i] = R - offset;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_noisemask(vorbis_look_psy *p,
Packit 06404a
                   float *logmdct,
Packit 06404a
                   float *logmask){
Packit 06404a
Packit 06404a
  int i,n=p->n;
Packit 06404a
  float *work=alloca(n*sizeof(*work));
Packit 06404a
Packit 06404a
  bark_noise_hybridmp(n,p->bark,logmdct,logmask,
Packit 06404a
                      140.,-1);
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
  bark_noise_hybridmp(n,p->bark,work,logmask,0.,
Packit 06404a
                      p->vi->noisewindowfixed);
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
Packit 06404a
#if 0
Packit 06404a
  {
Packit 06404a
    static int seq=0;
Packit 06404a
Packit 06404a
    float work2[n];
Packit 06404a
    for(i=0;i
Packit 06404a
      work2[i]=logmask[i]+work[i];
Packit 06404a
    }
Packit 06404a
Packit 06404a
    if(seq&1)
Packit 06404a
      _analysis_output("median2R",seq/2,work,n,1,0,0);
Packit 06404a
    else
Packit 06404a
      _analysis_output("median2L",seq/2,work,n,1,0,0);
Packit 06404a
Packit 06404a
    if(seq&1)
Packit 06404a
      _analysis_output("envelope2R",seq/2,work2,n,1,0,0);
Packit 06404a
    else
Packit 06404a
      _analysis_output("envelope2L",seq/2,work2,n,1,0,0);
Packit 06404a
    seq++;
Packit 06404a
  }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    int dB=logmask[i]+.5;
Packit 06404a
    if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1;
Packit 06404a
    if(dB<0)dB=0;
Packit 06404a
    logmask[i]= work[i]+p->vi->noisecompand[dB];
Packit 06404a
  }
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_tonemask(vorbis_look_psy *p,
Packit 06404a
                  float *logfft,
Packit 06404a
                  float *logmask,
Packit 06404a
                  float global_specmax,
Packit 06404a
                  float local_specmax){
Packit 06404a
Packit 06404a
  int i,n=p->n;
Packit 06404a
Packit 06404a
  float *seed=alloca(sizeof(*seed)*p->total_octave_lines);
Packit 06404a
  float att=local_specmax+p->vi->ath_adjatt;
Packit 06404a
  for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF;
Packit 06404a
Packit 06404a
  /* set the ATH (floating below localmax, not global max by a
Packit 06404a
     specified att) */
Packit 06404a
  if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    logmask[i]=p->ath[i]+att;
Packit 06404a
Packit 06404a
  /* tone masking */
Packit 06404a
  seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax);
Packit 06404a
  max_seeds(p,seed,logmask);
Packit 06404a
Packit 06404a
}
Packit 06404a
Packit 06404a
void _vp_offset_and_mix(vorbis_look_psy *p,
Packit 06404a
                        float *noise,
Packit 06404a
                        float *tone,
Packit 06404a
                        int offset_select,
Packit 06404a
                        float *logmask,
Packit 06404a
                        float *mdct,
Packit 06404a
                        float *logmdct){
Packit 06404a
  int i,n=p->n;
Packit 06404a
  float de, coeffi, cx;/* AoTuV */
Packit 06404a
  float toneatt=p->vi->tone_masteratt[offset_select];
Packit 06404a
Packit 06404a
  cx = p->m_val;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    float val= noise[i]+p->noiseoffset[offset_select][i];
Packit 06404a
    if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp;
Packit 06404a
    logmask[i]=max(val,tone[i]+toneatt);
Packit 06404a
Packit 06404a
Packit 06404a
    /* AoTuV */
Packit 06404a
    /** @ M1 **
Packit 06404a
        The following codes improve a noise problem.
Packit 06404a
        A fundamental idea uses the value of masking and carries out
Packit 06404a
        the relative compensation of the MDCT.
Packit 06404a
        However, this code is not perfect and all noise problems cannot be solved.
Packit 06404a
        by Aoyumi @ 2004/04/18
Packit 06404a
    */
Packit 06404a
Packit 06404a
    if(offset_select == 1) {
Packit 06404a
      coeffi = -17.2;       /* coeffi is a -17.2dB threshold */
Packit 06404a
      val = val - logmdct[i];  /* val == mdct line value relative to floor in dB */
Packit 06404a
Packit 06404a
      if(val > coeffi){
Packit 06404a
        /* mdct value is > -17.2 dB below floor */
Packit 06404a
Packit 06404a
        de = 1.0-((val-coeffi)*0.005*cx);
Packit 06404a
        /* pro-rated attenuation:
Packit 06404a
           -0.00 dB boost if mdct value is -17.2dB (relative to floor)
Packit 06404a
           -0.77 dB boost if mdct value is 0dB (relative to floor)
Packit 06404a
           -1.64 dB boost if mdct value is +17.2dB (relative to floor)
Packit 06404a
           etc... */
Packit 06404a
Packit 06404a
        if(de < 0) de = 0.0001;
Packit 06404a
      }else
Packit 06404a
        /* mdct value is <= -17.2 dB below floor */
Packit 06404a
Packit 06404a
        de = 1.0-((val-coeffi)*0.0003*cx);
Packit 06404a
      /* pro-rated attenuation:
Packit 06404a
         +0.00 dB atten if mdct value is -17.2dB (relative to floor)
Packit 06404a
         +0.45 dB atten if mdct value is -34.4dB (relative to floor)
Packit 06404a
         etc... */
Packit 06404a
Packit 06404a
      mdct[i] *= de;
Packit 06404a
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){
Packit 06404a
  vorbis_info *vi=vd->vi;
Packit 06404a
  codec_setup_info *ci=vi->codec_setup;
Packit 06404a
  vorbis_info_psy_global *gi=&ci->psy_g_param;
Packit 06404a
Packit 06404a
  int n=ci->blocksizes[vd->W]/2;
Packit 06404a
  float secs=(float)n/vi->rate;
Packit 06404a
Packit 06404a
  amp+=secs*gi->ampmax_att_per_sec;
Packit 06404a
  if(amp<-9999)amp=-9999;
Packit 06404a
  return(amp);
Packit 06404a
}
Packit 06404a
Packit 06404a
static float FLOOR1_fromdB_LOOKUP[256]={
Packit 06404a
  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
Packit 06404a
  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
Packit 06404a
  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
Packit 06404a
  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
Packit 06404a
  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
Packit 06404a
  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
Packit 06404a
  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
Packit 06404a
  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
Packit 06404a
  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
Packit 06404a
  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
Packit 06404a
  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
Packit 06404a
  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
Packit 06404a
  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
Packit 06404a
  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
Packit 06404a
  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
Packit 06404a
  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
Packit 06404a
  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
Packit 06404a
  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
Packit 06404a
  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
Packit 06404a
  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
Packit 06404a
  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
Packit 06404a
  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
Packit 06404a
  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
Packit 06404a
  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
Packit 06404a
  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
Packit 06404a
  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
Packit 06404a
  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
Packit 06404a
  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
Packit 06404a
  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
Packit 06404a
  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
Packit 06404a
  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
Packit 06404a
  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
Packit 06404a
  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
Packit 06404a
  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
Packit 06404a
  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
Packit 06404a
  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
Packit 06404a
  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
Packit 06404a
  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
Packit 06404a
  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
Packit 06404a
  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
Packit 06404a
  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
Packit 06404a
  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
Packit 06404a
  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
Packit 06404a
  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
Packit 06404a
  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
Packit 06404a
  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
Packit 06404a
  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
Packit 06404a
  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
Packit 06404a
  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
Packit 06404a
  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
Packit 06404a
  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
Packit 06404a
  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
Packit 06404a
  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
Packit 06404a
  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
Packit 06404a
  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
Packit 06404a
  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
Packit 06404a
  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
Packit 06404a
  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
Packit 06404a
  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
Packit 06404a
  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
Packit 06404a
  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
Packit 06404a
  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
Packit 06404a
  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
Packit 06404a
  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
Packit 06404a
};
Packit 06404a
Packit 06404a
/* this is for per-channel noise normalization */
Packit 06404a
static int apsort(const void *a, const void *b){
Packit 06404a
  float f1=**(float**)a;
Packit 06404a
  float f2=**(float**)b;
Packit 06404a
  return (f1<f2)-(f1>f2);
Packit 06404a
}
Packit 06404a
Packit 06404a
static void flag_lossless(int limit, float prepoint, float postpoint, float *mdct,
Packit 06404a
                         float *floor, int *flag, int i, int jn){
Packit 06404a
  int j;
Packit 06404a
  for(j=0;j
Packit 06404a
    float point = j>=limit-i ? postpoint : prepoint;
Packit 06404a
    float r = fabs(mdct[j])/floor[j];
Packit 06404a
    if(r
Packit 06404a
      flag[j]=0;
Packit 06404a
    else
Packit 06404a
      flag[j]=1;
Packit 06404a
  }
Packit 06404a
}
Packit 06404a
Packit 06404a
/* Overload/Side effect: On input, the *q vector holds either the
Packit 06404a
   quantized energy (for elements with the flag set) or the absolute
Packit 06404a
   values of the *r vector (for elements with flag unset).  On output,
Packit 06404a
   *q holds the quantized energy for all elements */
Packit 06404a
static float noise_normalize(vorbis_look_psy *p, int limit, float *r, float *q, float *f, int *flags, float acc, int i, int n, int *out){
Packit 06404a
Packit 06404a
  vorbis_info_psy *vi=p->vi;
Packit 06404a
  float **sort = alloca(n*sizeof(*sort));
Packit 06404a
  int j,count=0;
Packit 06404a
  int start = (vi->normal_p ? vi->normal_start-i : n);
Packit 06404a
  if(start>n)start=n;
Packit 06404a
Packit 06404a
  /* force classic behavior where only energy in the current band is considered */
Packit 06404a
  acc=0.f;
Packit 06404a
Packit 06404a
  /* still responsible for populating *out where noise norm not in
Packit 06404a
     effect.  There's no need to [re]populate *q in these areas */
Packit 06404a
  for(j=0;j
Packit 06404a
    if(!flags || !flags[j]){ /* lossless coupling already quantized.
Packit 06404a
                                Don't touch; requantizing based on
Packit 06404a
                                energy would be incorrect. */
Packit 06404a
      float ve = q[j]/f[j];
Packit 06404a
      if(r[j]<0)
Packit 06404a
        out[j] = -rint(sqrt(ve));
Packit 06404a
      else
Packit 06404a
        out[j] = rint(sqrt(ve));
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* sort magnitudes for noise norm portion of partition */
Packit 06404a
  for(;j
Packit 06404a
    if(!flags || !flags[j]){ /* can't noise norm elements that have
Packit 06404a
                                already been loslessly coupled; we can
Packit 06404a
                                only account for their energy error */
Packit 06404a
      float ve = q[j]/f[j];
Packit 06404a
      /* Despite all the new, more capable coupling code, for now we
Packit 06404a
         implement noise norm as it has been up to this point. Only
Packit 06404a
         consider promotions to unit magnitude from 0.  In addition
Packit 06404a
         the only energy error counted is quantizations to zero. */
Packit 06404a
      /* also-- the original point code only applied noise norm at > pointlimit */
Packit 06404a
      if(ve<.25f && (!flags || j>=limit-i)){
Packit 06404a
        acc += ve;
Packit 06404a
        sort[count++]=q+j; /* q is fabs(r) for unflagged element */
Packit 06404a
      }else{
Packit 06404a
        /* For now: no acc adjustment for nonzero quantization.  populate *out and q as this value is final. */
Packit 06404a
        if(r[j]<0)
Packit 06404a
          out[j] = -rint(sqrt(ve));
Packit 06404a
        else
Packit 06404a
          out[j] = rint(sqrt(ve));
Packit 06404a
        q[j] = out[j]*out[j]*f[j];
Packit 06404a
      }
Packit 06404a
    }/* else{
Packit 06404a
        again, no energy adjustment for error in nonzero quant-- for now
Packit 06404a
        }*/
Packit 06404a
  }
Packit 06404a
Packit 06404a
  if(count){
Packit 06404a
    /* noise norm to do */
Packit 06404a
    qsort(sort,count,sizeof(*sort),apsort);
Packit 06404a
    for(j=0;j
Packit 06404a
      int k=sort[j]-q;
Packit 06404a
      if(acc>=vi->normal_thresh){
Packit 06404a
        out[k]=unitnorm(r[k]);
Packit 06404a
        acc-=1.f;
Packit 06404a
        q[k]=f[k];
Packit 06404a
      }else{
Packit 06404a
        out[k]=0;
Packit 06404a
        q[k]=0.f;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return acc;
Packit 06404a
}
Packit 06404a
Packit 06404a
/* Noise normalization, quantization and coupling are not wholly
Packit 06404a
   seperable processes in depth>1 coupling. */
Packit 06404a
void _vp_couple_quantize_normalize(int blobno,
Packit 06404a
                                   vorbis_info_psy_global *g,
Packit 06404a
                                   vorbis_look_psy *p,
Packit 06404a
                                   vorbis_info_mapping0 *vi,
Packit 06404a
                                   float **mdct,
Packit 06404a
                                   int   **iwork,
Packit 06404a
                                   int    *nonzero,
Packit 06404a
                                   int     sliding_lowpass,
Packit 06404a
                                   int     ch){
Packit 06404a
Packit 06404a
  int i;
Packit 06404a
  int n = p->n;
Packit 06404a
  int partition=(p->vi->normal_p ? p->vi->normal_partition : 16);
Packit 06404a
  int limit = g->coupling_pointlimit[p->vi->blockflag][blobno];
Packit 06404a
  float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]];
Packit 06404a
  float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]];
Packit 06404a
#if 0
Packit 06404a
  float de=0.1*p->m_val; /* a blend of the AoTuV M2 and M3 code here and below */
Packit 06404a
#endif
Packit 06404a
Packit 06404a
  /* mdct is our raw mdct output, floor not removed. */
Packit 06404a
  /* inout passes in the ifloor, passes back quantized result */
Packit 06404a
Packit 06404a
  /* unquantized energy (negative indicates amplitude has negative sign) */
Packit 06404a
  float **raw = alloca(ch*sizeof(*raw));
Packit 06404a
Packit 06404a
  /* dual pupose; quantized energy (if flag set), othersize fabs(raw) */
Packit 06404a
  float **quant = alloca(ch*sizeof(*quant));
Packit 06404a
Packit 06404a
  /* floor energy */
Packit 06404a
  float **floor = alloca(ch*sizeof(*floor));
Packit 06404a
Packit 06404a
  /* flags indicating raw/quantized status of elements in raw vector */
Packit 06404a
  int   **flag  = alloca(ch*sizeof(*flag));
Packit 06404a
Packit 06404a
  /* non-zero flag working vector */
Packit 06404a
  int    *nz    = alloca(ch*sizeof(*nz));
Packit 06404a
Packit 06404a
  /* energy surplus/defecit tracking */
Packit 06404a
  float  *acc   = alloca((ch+vi->coupling_steps)*sizeof(*acc));
Packit 06404a
Packit 06404a
  /* The threshold of a stereo is changed with the size of n */
Packit 06404a
  if(n > 1000)
Packit 06404a
    postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]];
Packit 06404a
Packit 06404a
  raw[0]   = alloca(ch*partition*sizeof(**raw));
Packit 06404a
  quant[0] = alloca(ch*partition*sizeof(**quant));
Packit 06404a
  floor[0] = alloca(ch*partition*sizeof(**floor));
Packit 06404a
  flag[0]  = alloca(ch*partition*sizeof(**flag));
Packit 06404a
Packit 06404a
  for(i=1;i
Packit 06404a
    raw[i]   = &raw[0][partition*i];
Packit 06404a
    quant[i] = &quant[0][partition*i];
Packit 06404a
    floor[i] = &floor[0][partition*i];
Packit 06404a
    flag[i]  = &flag[0][partition*i];
Packit 06404a
  }
Packit 06404a
  for(i=0;i<ch+vi->coupling_steps;i++)
Packit 06404a
    acc[i]=0.f;
Packit 06404a
Packit 06404a
  for(i=0;i
Packit 06404a
    int k,j,jn = partition > n-i ? n-i : partition;
Packit 06404a
    int step,track = 0;
Packit 06404a
Packit 06404a
    memcpy(nz,nonzero,sizeof(*nz)*ch);
Packit 06404a
Packit 06404a
    /* prefill */
Packit 06404a
    memset(flag[0],0,ch*partition*sizeof(**flag));
Packit 06404a
    for(k=0;k
Packit 06404a
      int *iout = &iwork[k][i];
Packit 06404a
      if(nz[k]){
Packit 06404a
Packit 06404a
        for(j=0;j
Packit 06404a
          floor[k][j] = FLOOR1_fromdB_LOOKUP[iout[j]];
Packit 06404a
Packit 06404a
        flag_lossless(limit,prepoint,postpoint,&mdct[k][i],floor[k],flag[k],i,jn);
Packit 06404a
Packit 06404a
        for(j=0;j
Packit 06404a
          quant[k][j] = raw[k][j] = mdct[k][i+j]*mdct[k][i+j];
Packit 06404a
          if(mdct[k][i+j]<0.f) raw[k][j]*=-1.f;
Packit 06404a
          floor[k][j]*=floor[k][j];
Packit 06404a
        }
Packit 06404a
Packit 06404a
        acc[track]=noise_normalize(p,limit,raw[k],quant[k],floor[k],NULL,acc[track],i,jn,iout);
Packit 06404a
Packit 06404a
      }else{
Packit 06404a
        for(j=0;j
Packit 06404a
          floor[k][j] = 1e-10f;
Packit 06404a
          raw[k][j] = 0.f;
Packit 06404a
          quant[k][j] = 0.f;
Packit 06404a
          flag[k][j] = 0;
Packit 06404a
          iout[j]=0;
Packit 06404a
        }
Packit 06404a
        acc[track]=0.f;
Packit 06404a
      }
Packit 06404a
      track++;
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* coupling */
Packit 06404a
    for(step=0;step<vi->coupling_steps;step++){
Packit 06404a
      int Mi = vi->coupling_mag[step];
Packit 06404a
      int Ai = vi->coupling_ang[step];
Packit 06404a
      int *iM = &iwork[Mi][i];
Packit 06404a
      int *iA = &iwork[Ai][i];
Packit 06404a
      float *reM = raw[Mi];
Packit 06404a
      float *reA = raw[Ai];
Packit 06404a
      float *qeM = quant[Mi];
Packit 06404a
      float *qeA = quant[Ai];
Packit 06404a
      float *floorM = floor[Mi];
Packit 06404a
      float *floorA = floor[Ai];
Packit 06404a
      int *fM = flag[Mi];
Packit 06404a
      int *fA = flag[Ai];
Packit 06404a
Packit 06404a
      if(nz[Mi] || nz[Ai]){
Packit 06404a
        nz[Mi] = nz[Ai] = 1;
Packit 06404a
Packit 06404a
        for(j=0;j
Packit 06404a
Packit 06404a
          if(j
Packit 06404a
            if(fM[j] || fA[j]){
Packit 06404a
              /* lossless coupling */
Packit 06404a
Packit 06404a
              reM[j] = fabs(reM[j])+fabs(reA[j]);
Packit 06404a
              qeM[j] = qeM[j]+qeA[j];
Packit 06404a
              fM[j]=fA[j]=1;
Packit 06404a
Packit 06404a
              /* couple iM/iA */
Packit 06404a
              {
Packit 06404a
                int A = iM[j];
Packit 06404a
                int B = iA[j];
Packit 06404a
Packit 06404a
                if(abs(A)>abs(B)){
Packit 06404a
                  iA[j]=(A>0?A-B:B-A);
Packit 06404a
                }else{
Packit 06404a
                  iA[j]=(B>0?A-B:B-A);
Packit 06404a
                  iM[j]=B;
Packit 06404a
                }
Packit 06404a
Packit 06404a
                /* collapse two equivalent tuples to one */
Packit 06404a
                if(iA[j]>=abs(iM[j])*2){
Packit 06404a
                  iA[j]= -iA[j];
Packit 06404a
                  iM[j]= -iM[j];
Packit 06404a
                }
Packit 06404a
Packit 06404a
              }
Packit 06404a
Packit 06404a
            }else{
Packit 06404a
              /* lossy (point) coupling */
Packit 06404a
              if(j
Packit 06404a
                /* dipole */
Packit 06404a
                reM[j] += reA[j];
Packit 06404a
                qeM[j] = fabs(reM[j]);
Packit 06404a
              }else{
Packit 06404a
#if 0
Packit 06404a
                /* AoTuV */
Packit 06404a
                /** @ M2 **
Packit 06404a
                    The boost problem by the combination of noise normalization and point stereo is eased.
Packit 06404a
                    However, this is a temporary patch.
Packit 06404a
                    by Aoyumi @ 2004/04/18
Packit 06404a
                */
Packit 06404a
                float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit)));
Packit 06404a
                /* elliptical */
Packit 06404a
                if(reM[j]+reA[j]<0){
Packit 06404a
                  reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
Packit 06404a
                }else{
Packit 06404a
                  reM[j] =   (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
Packit 06404a
                }
Packit 06404a
#else
Packit 06404a
                /* elliptical */
Packit 06404a
                if(reM[j]+reA[j]<0){
Packit 06404a
                  reM[j] = - (qeM[j] = fabs(reM[j])+fabs(reA[j]));
Packit 06404a
                }else{
Packit 06404a
                  reM[j] =   (qeM[j] = fabs(reM[j])+fabs(reA[j]));
Packit 06404a
                }
Packit 06404a
#endif
Packit 06404a
Packit 06404a
              }
Packit 06404a
              reA[j]=qeA[j]=0.f;
Packit 06404a
              fA[j]=1;
Packit 06404a
              iA[j]=0;
Packit 06404a
            }
Packit 06404a
          }
Packit 06404a
          floorM[j]=floorA[j]=floorM[j]+floorA[j];
Packit 06404a
        }
Packit 06404a
        /* normalize the resulting mag vector */
Packit 06404a
        acc[track]=noise_normalize(p,limit,raw[Mi],quant[Mi],floor[Mi],flag[Mi],acc[track],i,jn,iM);
Packit 06404a
        track++;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  for(i=0;i<vi->coupling_steps;i++){
Packit 06404a
    /* make sure coupling a zero and a nonzero channel results in two
Packit 06404a
       nonzero channels. */
Packit 06404a
    if(nonzero[vi->coupling_mag[i]] ||
Packit 06404a
       nonzero[vi->coupling_ang[i]]){
Packit 06404a
      nonzero[vi->coupling_mag[i]]=1;
Packit 06404a
      nonzero[vi->coupling_ang[i]]=1;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
}