18e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/********************************************************************
28e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
38e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
48e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
58e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
68e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
78e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
88e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
98e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * by the Xiph.Org Foundation http://www.xiph.org/                  *
108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************
128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels function: psychoacoustics not including preecho
148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels last mod: $Id: psy.c 17077 2010-03-26 06:22:19Z xiphmont $
158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************/
178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdlib.h>
198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <math.h>
208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <string.h>
218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "vorbis/codec.h"
228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "codec_internal.h"
238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "masking.h"
258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "psy.h"
268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "os.h"
278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "lpc.h"
288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "smallft.h"
298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "scales.h"
308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "misc.h"
318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#define NEGINF -9999.f
338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic const double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10};
348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic const double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10};
358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvorbis_look_psy_global *_vp_global_look(vorbis_info *vi){
378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  codec_setup_info *ci=vi->codec_setup;
388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info_psy_global *gi=&ci->psy_g_param;
398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look));
408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  look->channels=vi->channels;
428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  look->ampmax=-9999.;
448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  look->gi=gi;
458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(look);
468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_global_free(vorbis_look_psy_global *look){
498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(look){
508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(look,0,sizeof(*look));
518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _ogg_free(look);
528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vi_gpsy_free(vorbis_info_psy_global *i){
568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(i){
578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(i,0,sizeof(*i));
588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _ogg_free(i);
598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vi_psy_free(vorbis_info_psy *i){
638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(i){
648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(i,0,sizeof(*i));
658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _ogg_free(i);
668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void min_curve(float *c,
708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       float *c2){
718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<EHMER_MAX;i++)if(c2[i]<c[i])c[i]=c2[i];
738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void max_curve(float *c,
758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       float *c2){
768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<EHMER_MAX;i++)if(c2[i]>c[i])c[i]=c2[i];
788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void attenuate_curve(float *c,float att){
818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<EHMER_MAX;i++)
838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    c[i]+=att;
848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic float ***setup_tone_curves(float curveatt_dB[P_BANDS],float binHz,int n,
878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                  float center_boost, float center_decay_rate){
888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j,k,m;
898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float ath[EHMER_MAX];
908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float workc[P_BANDS][P_LEVELS][EHMER_MAX];
918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float athc[P_LEVELS][EHMER_MAX];
928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *brute_buffer=alloca(n*sizeof(*brute_buffer));
938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float ***ret=_ogg_malloc(sizeof(*ret)*P_BANDS);
958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  memset(workc,0,sizeof(workc));
978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<P_BANDS;i++){
998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* we add back in the ATH to avoid low level curves falling off to
1008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       -infinity and unnecessarily cutting off high level curves in the
1018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       curve limiting (last step). */
1028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* A half-band's settings must be valid over the whole band, and
1048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       it's better to mask too little than too much */
1058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int ath_offset=i*4;
1068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<EHMER_MAX;j++){
1078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float min=999.;
1088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(k=0;k<4;k++)
1098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(j+k+ath_offset<MAX_ATH){
1108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(min>ATH[j+k+ath_offset])min=ATH[j+k+ath_offset];
1118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }else{
1128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1];
1138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
1148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ath[j]=min;
1158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* copy curves into working space, replicate the 50dB curve to 30
1188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       and 40, replicate the 100dB curve to 110 */
1198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<6;j++)
1208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j]));
1218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
1228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0]));
1238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* apply centered curve boost/decay */
1258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<P_LEVELS;j++){
1268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(k=0;k<EHMER_MAX;k++){
1278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        float adj=center_boost+abs(EHMER_OFFSET-k)*center_decay_rate;
1288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(adj<0. && center_boost>0)adj=0.;
1298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(adj>0. && center_boost<0)adj=0.;
1308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        workc[i][j][k]+=adj;
1318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* normalize curves so the driving amplitude is 0dB */
1358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* make temp curves with the ATH overlayed */
1368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<P_LEVELS;j++){
1378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      attenuate_curve(workc[i][j],curveatt_dB[i]+100.-(j<2?2:j)*10.-P_LEVEL_0);
1388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      memcpy(athc[j],ath,EHMER_MAX*sizeof(**athc));
1398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      attenuate_curve(athc[j],+100.-j*10.f-P_LEVEL_0);
1408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      max_curve(athc[j],workc[i][j]);
1418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* Now limit the louder curves.
1448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       the idea is this: We don't know what the playback attenuation
1468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       will be; 0dB SL moves every time the user twiddles the volume
1478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       knob. So that means we have to use a single 'most pessimal' curve
1488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       for all masking amplitudes, right?  Wrong.  The *loudest* sound
1498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       can be in (we assume) a range of ...+100dB] SL.  However, sounds
1508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       20dB down will be in a range ...+80], 40dB down is from ...+60],
1518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       etc... */
1528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=1;j<P_LEVELS;j++){
1548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      min_curve(athc[j],athc[j-1]);
1558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      min_curve(workc[i][j],athc[j]);
1568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
1588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<P_BANDS;i++){
1608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int hi_curve,lo_curve,bin;
1618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    ret[i]=_ogg_malloc(sizeof(**ret)*P_LEVELS);
1628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* low frequency curves are measured with greater resolution than
1648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       the MDCT/FFT will actually give us; we want the curve applied
1658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       to the tone data to be pessimistic and thus apply the minimum
1668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       masking possible for a given bin.  That means that a single bin
1678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       could span more than one octave and that the curve will be a
1688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       composite of multiple octaves.  It also may mean that a single
1698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       bin may span > an eighth of an octave and that the eighth
1708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       octave values may also be composited. */
1718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* which octave curves will we be compositing? */
1738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    bin=floor(fromOC(i*.5)/binHz);
1748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lo_curve=  ceil(toOC(bin*binHz+1)*2);
1758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    hi_curve=  floor(toOC((bin+1)*binHz)*2);
1768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(lo_curve>i)lo_curve=i;
1778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(lo_curve<0)lo_curve=0;
1788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1;
1798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(m=0;m<P_LEVELS;m++){
1818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ret[i][m]=_ogg_malloc(sizeof(***ret)*(EHMER_MAX+2));
1828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(j=0;j<n;j++)brute_buffer[j]=999.;
1848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* render the curve into bins, then pull values back into curve.
1868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         The point is that any inherent subsampling aliasing results in
1878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         a safe minimum */
1888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(k=lo_curve;k<=hi_curve;k++){
1898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        int l=0;
1908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<EHMER_MAX;j++){
1928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          int lo_bin= fromOC(j*.125+k*.5-2.0625)/binHz;
1938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          int hi_bin= fromOC(j*.125+k*.5-1.9375)/binHz+1;
1948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin<0)lo_bin=0;
1968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin>n)lo_bin=n;
1978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin<l)l=lo_bin;
1988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(hi_bin<0)hi_bin=0;
1998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(hi_bin>n)hi_bin=n;
2008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          for(;l<hi_bin && l<n;l++)
2028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(brute_buffer[l]>workc[k][m][j])
2038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              brute_buffer[l]=workc[k][m][j];
2048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
2058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(;l<n;l++)
2078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
2088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
2098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
2118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* be equally paranoid about being valid up to next half ocatve */
2138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(i+1<P_BANDS){
2148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        int l=0;
2158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        k=i+1;
2168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<EHMER_MAX;j++){
2178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          int lo_bin= fromOC(j*.125+i*.5-2.0625)/binHz;
2188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          int hi_bin= fromOC(j*.125+i*.5-1.9375)/binHz+1;
2198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin<0)lo_bin=0;
2218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin>n)lo_bin=n;
2228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(lo_bin<l)l=lo_bin;
2238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(hi_bin<0)hi_bin=0;
2248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(hi_bin>n)hi_bin=n;
2258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          for(;l<hi_bin && l<n;l++)
2278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(brute_buffer[l]>workc[k][m][j])
2288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              brute_buffer[l]=workc[k][m][j];
2298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
2308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(;l<n;l++)
2328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(brute_buffer[l]>workc[k][m][EHMER_MAX-1])
2338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            brute_buffer[l]=workc[k][m][EHMER_MAX-1];
2348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
2368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(j=0;j<EHMER_MAX;j++){
2398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        int bin=fromOC(j*.125+i*.5-2.)/binHz;
2408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(bin<0){
2418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          ret[i][m][j+2]=-999.;
2428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }else{
2438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(bin>=n){
2448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            ret[i][m][j+2]=-999.;
2458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }else{
2468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            ret[i][m][j+2]=brute_buffer[bin];
2478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }
2488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
2498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
2508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* add fenceposts */
2528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(j=0;j<EHMER_OFFSET;j++)
2538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(ret[i][m][j+2]>-200.f)break;
2548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ret[i][m][0]=j;
2558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--)
2578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(ret[i][m][j+2]>-200.f)
2588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          break;
2598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ret[i][m][1]=j;
2608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
2628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(ret);
2658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
2668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
2688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  vorbis_info_psy_global *gi,int n,long rate){
2698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long i,j,lo=-99,hi=1;
2708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long maxoc;
2718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  memset(p,0,sizeof(*p));
2728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->eighth_octave_lines=gi->eighth_octave_lines;
2748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1;
2758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines;
2778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f;
2788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->total_octave_lines=maxoc-p->firstoc+1;
2798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->ath=_ogg_malloc(n*sizeof(*p->ath));
2808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->octave=_ogg_malloc(n*sizeof(*p->octave));
2828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->bark=_ogg_malloc(n*sizeof(*p->bark));
2838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->vi=vi;
2848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->n=n;
2858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->rate=rate;
2868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* AoTuV HF weighting */
2888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->m_val = 1.;
2898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(rate < 26000) p->m_val = 0;
2908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  else if(rate < 38000) p->m_val = .94;   /* 32kHz */
2918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  else if(rate > 46000) p->m_val = 1.275; /* 48kHz */
2928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* set up the lookups for a given blocksize and sample rate */
2948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0,j=0;i<MAX_ATH-1;i++){
2968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate);
2978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float base=ATH[i];
2988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(j<endpos){
2998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float delta=(ATH[i+1]-base)/(endpos-j);
3008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(;j<endpos && j<n;j++){
3018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        p->ath[j]=base+100.;
3028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        base+=delta;
3038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(;j<n;j++){
3088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    p->ath[j]=p->ath[j-1];
3098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
3128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float bark=toBARK(rate/(2*n)*i);
3138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(;lo+vi->noisewindowlomin<i &&
3158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++);
3168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(;hi<=n && (hi<i+vi->noisewindowhimin ||
3188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++);
3198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    p->bark[i]=((lo-1)<<16)+(hi-1);
3218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++)
3258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f;
3268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n,
3288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                  vi->tone_centerboost,vi->tone_decay);
3298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* set up rolling noise median */
3318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  p->noiseoffset=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset));
3328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<P_NOISECURVES;i++)
3338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    p->noiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset));
3348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
3368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float halfoc=toOC((i+.5)*rate/(2.*n))*2.;
3378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int inthalfoc;
3388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float del;
3398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(halfoc<0)halfoc=0;
3418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1;
3428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    inthalfoc=(int)halfoc;
3438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    del=halfoc-inthalfoc;
3448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<P_NOISECURVES;j++)
3468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      p->noiseoffset[j][i]=
3478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        p->vi->noiseoff[j][inthalfoc]*(1.-del) +
3488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        p->vi->noiseoff[j][inthalfoc+1]*del;
3498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#if 0
3528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
3538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    static int ls=0;
3548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0);
3558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0);
3568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0);
3578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
3598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_psy_clear(vorbis_look_psy *p){
3628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j;
3638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(p){
3648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(p->ath)_ogg_free(p->ath);
3658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(p->octave)_ogg_free(p->octave);
3668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(p->bark)_ogg_free(p->bark);
3678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(p->tonecurves){
3688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(i=0;i<P_BANDS;i++){
3698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<P_LEVELS;j++){
3708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          _ogg_free(p->tonecurves[i][j]);
3718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
3728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        _ogg_free(p->tonecurves[i]);
3738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _ogg_free(p->tonecurves);
3758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(p->noiseoffset){
3778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(i=0;i<P_NOISECURVES;i++){
3788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        _ogg_free(p->noiseoffset[i]);
3798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _ogg_free(p->noiseoffset);
3818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(p,0,sizeof(*p));
3838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* octave/(8*eighth_octave_lines) x scale and dB y scale */
3878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void seed_curve(float *seed,
3888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       const float **curves,
3898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       float amp,
3908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       int oc, int n,
3918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                       int linesper,float dBoffset){
3928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,post1;
3938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int seedptr;
3948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  const float *posts,*curve;
3958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f);
3978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  choice=max(choice,0);
3988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  choice=min(choice,P_LEVELS-1);
3998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  posts=curves[choice];
4008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  curve=posts+2;
4018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  post1=(int)posts[1];
4028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1);
4038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=posts[0];i<post1;i++){
4058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(seedptr>0){
4068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float lin=amp+curve[i];
4078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(seed[seedptr]<lin)seed[seedptr]=lin;
4088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    seedptr+=linesper;
4108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(seedptr>=n)break;
4118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
4138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void seed_loop(vorbis_look_psy *p,
4158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      const float ***curves,
4168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      const float *f,
4178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      const float *flr,
4188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      float *seed,
4198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      float specmax){
4208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info_psy *vi=p->vi;
4218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long n=p->n,i;
4228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float dBoffset=vi->max_curve_dB-specmax;
4238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* prime the working vector with peak values */
4258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
4278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float max=f[i];
4288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long oc=p->octave[i];
4298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    while(i+1<n && p->octave[i+1]==oc){
4308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      i++;
4318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(f[i]>max)max=f[i];
4328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(max+6.f>flr[i]){
4358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oc=oc>>p->shiftoc;
4368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(oc>=P_BANDS)oc=P_BANDS-1;
4388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(oc<0)oc=0;
4398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      seed_curve(seed,
4418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 curves[oc],
4428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 max,
4438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 p->octave[i]-p->firstoc,
4448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 p->total_octave_lines,
4458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 p->eighth_octave_lines,
4468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 dBoffset);
4478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
4508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void seed_chase(float *seeds, int linesper, long n){
4528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long  *posstack=alloca(n*sizeof(*posstack));
4538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *ampstack=alloca(n*sizeof(*ampstack));
4548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   stack=0;
4558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   pos=0;
4568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   i;
4578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
4598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(stack<2){
4608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      posstack[stack]=i;
4618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ampstack[stack++]=seeds[i];
4628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else{
4638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      while(1){
4648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(seeds[i]<ampstack[stack-1]){
4658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          posstack[stack]=i;
4668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          ampstack[stack++]=seeds[i];
4678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          break;
4688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }else{
4698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(i<posstack[stack-1]+linesper){
4708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(stack>1 && ampstack[stack-1]<=ampstack[stack-2] &&
4718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               i<posstack[stack-2]+linesper){
4728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              /* we completely overlap, making stack-1 irrelevant.  pop it */
4738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              stack--;
4748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              continue;
4758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }
4768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }
4778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          posstack[stack]=i;
4788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          ampstack[stack++]=seeds[i];
4798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          break;
4808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
4828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
4838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* the stack now contains only the positions that are relevant. Scan
4878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     'em straight through */
4888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<stack;i++){
4908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long endpos;
4918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(i<stack-1 && ampstack[i+1]>ampstack[i]){
4928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      endpos=posstack[i+1];
4938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else{
4948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is
4958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                        discarded in short frames */
4968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(endpos>n)endpos=n;
4988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(;pos<endpos;pos++)
4998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      seeds[pos]=ampstack[i];
5008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* there.  Linear time.  I now remember this was on a problem set I
5038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     had in Grad Skool... I didn't solve it at the time ;-) */
5048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
5068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* bleaugh, this is more complicated than it needs to be */
5088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include<stdio.h>
5098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void max_seeds(vorbis_look_psy *p,
5108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      float *seed,
5118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      float *flr){
5128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   n=p->total_octave_lines;
5138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int    linesper=p->eighth_octave_lines;
5148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   linpos=0;
5158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long   pos;
5168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  seed_chase(seed,linesper,n); /* for masking */
5188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  pos=p->octave[0]-p->firstoc-(linesper>>1);
5208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(linpos+1<p->n){
5228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float minV=seed[pos];
5238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc;
5248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit;
5258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    while(pos+1<=end){
5268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      pos++;
5278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if((seed[pos]>NEGINF && seed[pos]<minV) || minV==NEGINF)
5288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        minV=seed[pos];
5298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
5308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    end=pos+p->firstoc;
5328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(;linpos<p->n && p->octave[linpos]<=end;linpos++)
5338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(flr[linpos]<minV)flr[linpos]=minV;
5348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
5378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float minV=seed[p->total_octave_lines-1];
5388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(;linpos<p->n;linpos++)
5398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(flr[linpos]<minV)flr[linpos]=minV;
5408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
5438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void bark_noise_hybridmp(int n,const long *b,
5458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                const float *f,
5468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                float *noise,
5478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                const float offset,
5488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                const int fixed){
5498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *N=alloca(n*sizeof(*N));
5518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *X=alloca(n*sizeof(*N));
5528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *XX=alloca(n*sizeof(*N));
5538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *Y=alloca(n*sizeof(*N));
5548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *XY=alloca(n*sizeof(*N));
5558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float tN, tX, tXX, tY, tXY;
5578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
5588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int lo, hi;
5608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float R=0.f;
5618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float A=0.f;
5628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float B=0.f;
5638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float D=1.f;
5648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float w, x, y;
5658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  tN = tX = tXX = tY = tXY = 0.f;
5678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  y = f[0] + offset;
5698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if (y < 1.f) y = 1.f;
5708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  w = y * y * .5;
5728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  tN += w;
5748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  tX += w;
5758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  tY += w * y;
5768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  N[0] = tN;
5788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  X[0] = tX;
5798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  XX[0] = tXX;
5808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  Y[0] = tY;
5818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  XY[0] = tXY;
5828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for (i = 1, x = 1.f; i < n; i++, x += 1.f) {
5848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    y = f[i] + offset;
5868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (y < 1.f) y = 1.f;
5878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w = y * y;
5898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tN += w;
5918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tX += w * x;
5928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXX += w * x * x;
5938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tY += w * y;
5948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXY += w * x * y;
5958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    N[i] = tN;
5978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    X[i] = tX;
5988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    XX[i] = tXX;
5998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    Y[i] = tY;
6008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    XY[i] = tXY;
6018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for (i = 0, x = 0.f;; i++, x += 1.f) {
6048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lo = b[i] >> 16;
6068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if( lo>=0 ) break;
6078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    hi = b[i] & 0xffff;
6088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tN = N[hi] + N[-lo];
6108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tX = X[hi] - X[-lo];
6118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXX = XX[hi] + XX[-lo];
6128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tY = Y[hi] + Y[-lo];
6138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXY = XY[hi] - XY[-lo];
6148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    A = tY * tXX - tX * tXY;
6168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    B = tN * tXY - tX * tY;
6178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    D = tN * tXX - tX * tX;
6188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R < 0.f)
6208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      R = 0.f;
6218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    noise[i] = R - offset;
6238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for ( ;; i++, x += 1.f) {
6268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lo = b[i] >> 16;
6288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    hi = b[i] & 0xffff;
6298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(hi>=n)break;
6308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tN = N[hi] - N[lo];
6328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tX = X[hi] - X[lo];
6338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXX = XX[hi] - XX[lo];
6348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tY = Y[hi] - Y[lo];
6358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXY = XY[hi] - XY[lo];
6368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    A = tY * tXX - tX * tXY;
6388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    B = tN * tXY - tX * tY;
6398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    D = tN * tXX - tX * tX;
6408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R < 0.f) R = 0.f;
6428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    noise[i] = R - offset;
6448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for ( ; i < n; i++, x += 1.f) {
6468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R < 0.f) R = 0.f;
6498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    noise[i] = R - offset;
6518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if (fixed <= 0) return;
6548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for (i = 0, x = 0.f;; i++, x += 1.f) {
6568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    hi = i + fixed / 2;
6578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lo = hi - fixed;
6588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(lo>=0)break;
6598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tN = N[hi] + N[-lo];
6618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tX = X[hi] - X[-lo];
6628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXX = XX[hi] + XX[-lo];
6638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tY = Y[hi] + Y[-lo];
6648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXY = XY[hi] - XY[-lo];
6658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    A = tY * tXX - tX * tXY;
6688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    B = tN * tXY - tX * tY;
6698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    D = tN * tXX - tX * tX;
6708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R - offset < noise[i]) noise[i] = R - offset;
6738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for ( ;; i++, x += 1.f) {
6758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    hi = i + fixed / 2;
6778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lo = hi - fixed;
6788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(hi>=n)break;
6798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tN = N[hi] - N[lo];
6818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tX = X[hi] - X[lo];
6828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXX = XX[hi] - XX[lo];
6838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tY = Y[hi] - Y[lo];
6848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    tXY = XY[hi] - XY[lo];
6858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    A = tY * tXX - tX * tXY;
6878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    B = tN * tXY - tX * tY;
6888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    D = tN * tXX - tX * tX;
6898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R - offset < noise[i]) noise[i] = R - offset;
6928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for ( ; i < n; i++, x += 1.f) {
6948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    R = (A + x * B) / D;
6958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if (R - offset < noise[i]) noise[i] = R - offset;
6968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
6978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
6988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
6998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_noisemask(vorbis_look_psy *p,
7008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                   float *logmdct,
7018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                   float *logmask){
7028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,n=p->n;
7048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *work=alloca(n*sizeof(*work));
7058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  bark_noise_hybridmp(n,p->bark,logmdct,logmask,
7078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      140.,-1);
7088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++)work[i]=logmdct[i]-logmask[i];
7108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  bark_noise_hybridmp(n,p->bark,work,logmask,0.,
7128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      p->vi->noisewindowfixed);
7138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++)work[i]=logmdct[i]-work[i];
7158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#if 0
7178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
7188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    static int seq=0;
7198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float work2[n];
7218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0;i<n;i++){
7228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      work2[i]=logmask[i]+work[i];
7238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
7248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(seq&1)
7268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _analysis_output("median2R",seq/2,work,n,1,0,0);
7278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    else
7288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _analysis_output("median2L",seq/2,work,n,1,0,0);
7298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(seq&1)
7318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _analysis_output("envelope2R",seq/2,work2,n,1,0,0);
7328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    else
7338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      _analysis_output("envelope2L",seq/2,work2,n,1,0,0);
7348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    seq++;
7358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
7368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
7378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
7398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int dB=logmask[i]+.5;
7408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1;
7418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(dB<0)dB=0;
7428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    logmask[i]= work[i]+p->vi->noisecompand[dB];
7438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
7448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
7468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_tonemask(vorbis_look_psy *p,
7488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  float *logfft,
7498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  float *logmask,
7508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  float global_specmax,
7518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  float local_specmax){
7528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,n=p->n;
7548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float *seed=alloca(sizeof(*seed)*p->total_octave_lines);
7568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float att=local_specmax+p->vi->ath_adjatt;
7578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF;
7588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* set the ATH (floating below localmax, not global max by a
7608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     specified att) */
7618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
7628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++)
7648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    logmask[i]=p->ath[i]+att;
7658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* tone masking */
7678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax);
7688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  max_seeds(p,seed,logmask);
7698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
7718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_offset_and_mix(vorbis_look_psy *p,
7738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        float *noise,
7748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        float *tone,
7758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        int offset_select,
7768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        float *logmask,
7778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        float *mdct,
7788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        float *logmdct){
7798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,n=p->n;
7808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float de, coeffi, cx;/* AoTuV */
7818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float toneatt=p->vi->tone_masteratt[offset_select];
7828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  cx = p->m_val;
7848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i++){
7868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float val= noise[i]+p->noiseoffset[offset_select][i];
7878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp;
7888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    logmask[i]=max(val,tone[i]+toneatt);
7898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
7918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* AoTuV */
7928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /** @ M1 **
7938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        The following codes improve a noise problem.
7948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        A fundamental idea uses the value of masking and carries out
7958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        the relative compensation of the MDCT.
7968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        However, this code is not perfect and all noise problems cannot be solved.
7978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        by Aoyumi @ 2004/04/18
7988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    */
7998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(offset_select == 1) {
8018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      coeffi = -17.2;       /* coeffi is a -17.2dB threshold */
8028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      val = val - logmdct[i];  /* val == mdct line value relative to floor in dB */
8038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(val > coeffi){
8058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* mdct value is > -17.2 dB below floor */
8068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        de = 1.0-((val-coeffi)*0.005*cx);
8088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* pro-rated attenuation:
8098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           -0.00 dB boost if mdct value is -17.2dB (relative to floor)
8108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           -0.77 dB boost if mdct value is 0dB (relative to floor)
8118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           -1.64 dB boost if mdct value is +17.2dB (relative to floor)
8128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           etc... */
8138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(de < 0) de = 0.0001;
8158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }else
8168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* mdct value is <= -17.2 dB below floor */
8178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        de = 1.0-((val-coeffi)*0.0003*cx);
8198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* pro-rated attenuation:
8208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         +0.00 dB atten if mdct value is -17.2dB (relative to floor)
8218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         +0.45 dB atten if mdct value is -34.4dB (relative to floor)
8228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         etc... */
8238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      mdct[i] *= de;
8258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
8278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
8288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
8298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsfloat _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){
8318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info *vi=vd->vi;
8328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  codec_setup_info *ci=vi->codec_setup;
8338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info_psy_global *gi=&ci->psy_g_param;
8348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n=ci->blocksizes[vd->W]/2;
8368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float secs=(float)n/vi->rate;
8378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  amp+=secs*gi->ampmax_att_per_sec;
8398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(amp<-9999)amp=-9999;
8408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(amp);
8418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
8428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
8438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic float FLOOR1_fromdB_LOOKUP[256]={
8448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
8458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
8468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
8478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
8488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
8498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
8508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
8518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
8528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
8538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
8548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
8558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
8568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
8578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
8588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
8598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
8608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
8618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
8628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
8638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
8648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
8658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
8668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
8678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
8688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
8698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
8708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
8718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
8728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
8738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
8748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
8758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
8768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
8778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
8788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
8798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
8808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
8818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
8828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
8838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
8848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
8858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
8868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
8878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
8888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
8898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
8908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
8918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
8928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
8938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
8948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
8958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
8968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
8978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
8988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
8998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
9008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
9018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
9028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
9038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
9048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
9058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
9068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
9078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  0.82788260F, 0.88168307F, 0.9389798F, 1.F,
9088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels};
9098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* this is for per-channel noise normalization */
9118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic int apsort(const void *a, const void *b){
9128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float f1=**(float**)a;
9138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float f2=**(float**)b;
9148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return (f1<f2)-(f1>f2);
9158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
9168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic void flag_lossless(int limit, float prepoint, float postpoint, float *mdct,
9188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                         float *floor, int *flag, int i, int jn){
9198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int j;
9208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(j=0;j<jn;j++){
9218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float point = j>=limit-i ? postpoint : prepoint;
9228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    float r = fabs(mdct[j])/floor[j];
9238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(r<point)
9248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      flag[j]=0;
9258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    else
9268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      flag[j]=1;
9278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
9288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
9298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* Overload/Side effect: On input, the *q vector holds either the
9318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   quantized energy (for elements with the flag set) or the absolute
9328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   values of the *r vector (for elements with flag unset).  On output,
9338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   *q holds the quantized energy for all elements */
9348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic 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){
9358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info_psy *vi=p->vi;
9378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float **sort = alloca(n*sizeof(*sort));
9388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int j,count=0;
9398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int start = (vi->normal_p ? vi->normal_start-i : n);
9408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(start>n)start=n;
9418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* force classic behavior where only energy in the current band is considered */
9438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  acc=0.f;
9448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* still responsible for populating *out where noise norm not in
9468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     effect.  There's no need to [re]populate *q in these areas */
9478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(j=0;j<start;j++){
9488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(!flags || !flags[j]){ /* lossless coupling already quantized.
9498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                Don't touch; requantizing based on
9508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                energy would be incorrect. */
9518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float ve = q[j]/f[j];
9528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(r[j]<0)
9538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        out[j] = -rint(sqrt(ve));
9548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      else
9558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        out[j] = rint(sqrt(ve));
9568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
9578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
9588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* sort magnitudes for noise norm portion of partition */
9608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(;j<n;j++){
9618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(!flags || !flags[j]){ /* can't noise norm elements that have
9628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                already been loslessly coupled; we can
9638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                only account for their energy error */
9648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float ve = q[j]/f[j];
9658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* Despite all the new, more capable coupling code, for now we
9668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         implement noise norm as it has been up to this point. Only
9678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         consider promotions to unit magnitude from 0.  In addition
9688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         the only energy error counted is quantizations to zero. */
9698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* also-- the original point code only applied noise norm at > pointlimit */
9708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(ve<.25f && (!flags || j>=limit-i)){
9718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        acc += ve;
9728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        sort[count++]=q+j; /* q is fabs(r) for unflagged element */
9738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }else{
9748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* For now: no acc adjustment for nonzero quantization.  populate *out and q as this value is final. */
9758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(r[j]<0)
9768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          out[j] = -rint(sqrt(ve));
9778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        else
9788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          out[j] = rint(sqrt(ve));
9798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        q[j] = out[j]*out[j]*f[j];
9808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
9818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }/* else{
9828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        again, no energy adjustment for error in nonzero quant-- for now
9838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }*/
9848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
9858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
9868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(count){
9878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* noise norm to do */
9888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    qsort(sort,count,sizeof(*sort),apsort);
9898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<count;j++){
9908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int k=sort[j]-q;
9918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(acc>=vi->normal_thresh){
9928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        out[k]=unitnorm(r[k]);
9938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        acc-=1.f;
9948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        q[k]=f[k];
9958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }else{
9968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        out[k]=0;
9978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        q[k]=0.f;
9988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
9998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
10008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
10018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return acc;
10038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
10048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* Noise normalization, quantization and coupling are not wholly
10068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   seperable processes in depth>1 coupling. */
10078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid _vp_couple_quantize_normalize(int blobno,
10088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   vorbis_info_psy_global *g,
10098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   vorbis_look_psy *p,
10108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   vorbis_info_mapping0 *vi,
10118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   float **mdct,
10128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   int   **iwork,
10138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   int    *nonzero,
10148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   int     sliding_lowpass,
10158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                   int     ch){
10168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
10188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n = p->n;
10198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int partition=(p->vi->normal_p ? p->vi->normal_partition : 16);
10208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int limit = g->coupling_pointlimit[p->vi->blockflag][blobno];
10218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]];
10228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]];
10238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float de=0.1*p->m_val; /* a blend of the AoTuV M2 and M3 code here and below */
10248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* mdct is our raw mdct output, floor not removed. */
10268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* inout passes in the ifloor, passes back quantized result */
10278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* unquantized energy (negative indicates amplitude has negative sign) */
10298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float **raw = alloca(ch*sizeof(*raw));
10308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* dual pupose; quantized energy (if flag set), othersize fabs(raw) */
10328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float **quant = alloca(ch*sizeof(*quant));
10338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* floor energy */
10358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float **floor = alloca(ch*sizeof(*floor));
10368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* flags indicating raw/quantized status of elements in raw vector */
10388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int   **flag  = alloca(ch*sizeof(*flag));
10398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* non-zero flag working vector */
10418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int    *nz    = alloca(ch*sizeof(*nz));
10428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* energy surplus/defecit tracking */
10448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float  *acc   = alloca((ch+vi->coupling_steps)*sizeof(*acc));
10458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* The threshold of a stereo is changed with the size of n */
10478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(n > 1000)
10488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]];
10498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  raw[0]   = alloca(ch*partition*sizeof(**raw));
10518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  quant[0] = alloca(ch*partition*sizeof(**quant));
10528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  floor[0] = alloca(ch*partition*sizeof(**floor));
10538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  flag[0]  = alloca(ch*partition*sizeof(**flag));
10548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=1;i<ch;i++){
10568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    raw[i]   = &raw[0][partition*i];
10578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    quant[i] = &quant[0][partition*i];
10588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    floor[i] = &floor[0][partition*i];
10598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    flag[i]  = &flag[0][partition*i];
10608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
10618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<ch+vi->coupling_steps;i++)
10628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    acc[i]=0.f;
10638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n;i+=partition){
10658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int k,j,jn = partition > n-i ? n-i : partition;
10668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int step,track = 0;
10678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memcpy(nz,nonzero,sizeof(*nz)*ch);
10698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* prefill */
10718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(flag[0],0,ch*partition*sizeof(**flag));
10728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(k=0;k<ch;k++){
10738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int *iout = &iwork[k][i];
10748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(nz[k]){
10758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<jn;j++)
10778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          floor[k][j] = FLOOR1_fromdB_LOOKUP[iout[j]];
10788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        flag_lossless(limit,prepoint,postpoint,&mdct[k][i],floor[k],flag[k],i,jn);
10808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<jn;j++){
10828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          quant[k][j] = raw[k][j] = mdct[k][i+j]*mdct[k][i+j];
10838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(mdct[k][i+j]<0.f) raw[k][j]*=-1.f;
10848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          floor[k][j]*=floor[k][j];
10858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
10868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        acc[track]=noise_normalize(p,limit,raw[k],quant[k],floor[k],NULL,acc[track],i,jn,iout);
10888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
10898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }else{
10908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<jn;j++){
10918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          floor[k][j] = 1e-10f;
10928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          raw[k][j] = 0.f;
10938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          quant[k][j] = 0.f;
10948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          flag[k][j] = 0;
10958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          iout[j]=0;
10968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
10978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        acc[track]=0.f;
10988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
10998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      track++;
11008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
11018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* coupling */
11038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(step=0;step<vi->coupling_steps;step++){
11048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int Mi = vi->coupling_mag[step];
11058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int Ai = vi->coupling_ang[step];
11068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int *iM = &iwork[Mi][i];
11078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int *iA = &iwork[Ai][i];
11088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *reM = raw[Mi];
11098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *reA = raw[Ai];
11108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *qeM = quant[Mi];
11118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *qeA = quant[Ai];
11128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *floorM = floor[Mi];
11138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float *floorA = floor[Ai];
11148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int *fM = flag[Mi];
11158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int *fA = flag[Ai];
11168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(nz[Mi] || nz[Ai]){
11188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        nz[Mi] = nz[Ai] = 1;
11198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<jn;j++){
11218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(j<sliding_lowpass-i){
11238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(fM[j] || fA[j]){
11248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              /* lossless coupling */
11258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              reM[j] = fabs(reM[j])+fabs(reA[j]);
11278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              qeM[j] = qeM[j]+qeA[j];
11288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              fM[j]=fA[j]=1;
11298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              /* couple iM/iA */
11318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              {
11328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                int A = iM[j];
11338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                int B = iA[j];
11348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                if(abs(A)>abs(B)){
11368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  iA[j]=(A>0?A-B:B-A);
11378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }else{
11388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  iA[j]=(B>0?A-B:B-A);
11398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  iM[j]=B;
11408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }
11418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* collapse two equivalent tuples to one */
11438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                if(iA[j]>=abs(iM[j])*2){
11448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  iA[j]= -iA[j];
11458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  iM[j]= -iM[j];
11468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }
11478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              }
11498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }else{
11518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              /* lossy (point) coupling */
11528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              if(j<limit-i){
11538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* dipole */
11548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                reM[j] += reA[j];
11558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                qeM[j] = fabs(reM[j]);
11568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              }else{
11578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* AoTuV */
11588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /** @ M2 **
11598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    The boost problem by the combination of noise normalization and point stereo is eased.
11608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    However, this is a temporary patch.
11618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    by Aoyumi @ 2004/04/18
11628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                */
11638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit)));
11648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* elliptical */
11668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                if(reM[j]+reA[j]<0){
11678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
11688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }else{
11698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  reM[j] =   (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate);
11708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }
11718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              }
11728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              reA[j]=qeA[j]=0.f;
11738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              fA[j]=1;
11748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              iA[j]=0;
11758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }
11768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }
11778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          floorM[j]=floorA[j]=floorM[j]+floorA[j];
11788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
11798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* normalize the resulting mag vector */
11808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        acc[track]=noise_normalize(p,limit,raw[Mi],quant[Mi],floor[Mi],flag[Mi],acc[track],i,jn,iM);
11818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        track++;
11828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
11838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
11848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
11858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
11868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<vi->coupling_steps;i++){
11878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* make sure coupling a zero and a nonzero channel results in two
11888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       nonzero channels. */
11898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(nonzero[vi->coupling_mag[i]] ||
11908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       nonzero[vi->coupling_ang[i]]){
11918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      nonzero[vi->coupling_mag[i]]=1;
11928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      nonzero[vi->coupling_ang[i]]=1;
11938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
11948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
11958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1196