void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi, vorbis_info_psy_global *gi,int n,long rate){ long i,j,lo=-99,hi=1; long maxoc; memset(p,0,sizeof(*p)); p->eighth_octave_lines=gi->eighth_octave_lines; p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1; p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines; maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f; p->total_octave_lines=maxoc-p->firstoc+1; p->ath=(float*)_ogg_malloc(n*sizeof(*p->ath)); p->octave=(long*)_ogg_malloc(n*sizeof(*p->octave)); p->bark=(long*)_ogg_malloc(n*sizeof(*p->bark)); p->vi=vi; p->n=n; p->rate=rate; /* AoTuV HF weighting */ p->m_val = 1.; if(rate < 26000) p->m_val = 0; else if(rate < 38000) p->m_val = .94; /* 32kHz */ else if(rate > 46000) p->m_val = 1.275; /* 48kHz */ /* set up the lookups for a given blocksize and sample rate */ for(i=0,j=0;i<MAX_ATH-1;i++){ int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate); float base=ATH[i]; if(j<endpos){ float delta=(ATH[i+1]-base)/(endpos-j); for(;j<endpos && j<n;j++){ p->ath[j]=base+100.; base+=delta; } } } for(i=0;i<n;i++){ float bark=toBARK(rate/(2*n)*i); for(;lo+vi->noisewindowlomin<i && toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++); for(;hi<=n && (hi<i+vi->noisewindowhimin || toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++); p->bark[i]=((lo-1)<<16)+(hi-1); } for(i=0;i<n;i++) p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f; p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n, vi->tone_centerboost,vi->tone_decay); /* set up rolling noise median */ p->noiseoffset=(float**)_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset)); for(i=0;i<P_NOISECURVES;i++) p->noiseoffset[i]=(float*)_ogg_malloc(n*sizeof(**p->noiseoffset)); for(i=0;i<n;i++){ float halfoc=toOC((i+.5)*rate/(2.*n))*2.; int inthalfoc; float del; if(halfoc<0)halfoc=0; if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1; inthalfoc=(int)halfoc; del=halfoc-inthalfoc; for(j=0;j<P_NOISECURVES;j++) p->noiseoffset[j][i]= p->vi->noiseoff[j][inthalfoc]*(1.-del) + p->vi->noiseoff[j][inthalfoc+1]*del; } #if 0 { static int ls=0; _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0); _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0); _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0); } #endif }
static void setup_curve(float **c, int band, float *curveatt_dB){ int i,j; float ath[EHMER_MAX]; float tempc[P_LEVELS][EHMER_MAX]; float *ATH=ATH_Bark_dB_lspconservative; /* just for limiting here */ memcpy(c[0]+2,c[4]+2,sizeof(float)*EHMER_MAX); memcpy(c[2]+2,c[4]+2,sizeof(float)*EHMER_MAX); /* we add back in the ATH to avoid low level curves falling off to -infinity and unneccessarily cutting off high level curves in the curve limiting (last step). But again, remember... a half-band's settings must be valid over the whole band, and it's better to mask too little than too much, so be pessimal. */ for(i=0;i<EHMER_MAX;i++){ float oc_min=band*.5+(i-EHMER_OFFSET)*.125; float oc_max=band*.5+(i-EHMER_OFFSET+1)*.125; float bark=toBARK(fromOC(oc_min)); int ibark=floor(bark); float del=bark-ibark; float ath_min,ath_max; if(ibark<26) ath_min=ATH[ibark]*(1.f-del)+ATH[ibark+1]*del; else ath_min=ATH[25]; bark=toBARK(fromOC(oc_max)); ibark=floor(bark); del=bark-ibark; if(ibark<26) ath_max=ATH[ibark]*(1.f-del)+ATH[ibark+1]*del; else ath_max=ATH[25]; ath[i]=min(ath_min,ath_max); } /* The c array is comes in as dB curves at 20 40 60 80 100 dB. interpolate intermediate dB curves */ for(i=1;i<P_LEVELS;i+=2){ interp_curve(c[i]+2,c[i-1]+2,c[i+1]+2,.5); } /* normalize curves so the driving amplitude is 0dB */ /* make temp curves with the ATH overlayed */ for(i=0;i<P_LEVELS;i++){ attenuate_curve(c[i]+2,curveatt_dB[i]); memcpy(tempc[i],ath,EHMER_MAX*sizeof(float)); attenuate_curve(tempc[i],-i*10.f); max_curve(tempc[i],c[i]+2); } /* Now limit the louder curves. the idea is this: We don't know what the playback attenuation will be; 0dB SL moves every time the user twiddles the volume knob. So that means we have to use a single 'most pessimal' curve for all masking amplitudes, right? Wrong. The *loudest* sound can be in (we assume) a range of ...+100dB] SL. However, sounds 20dB down will be in a range ...+80], 40dB down is from ...+60], etc... */ for(j=1;j<P_LEVELS;j++){ min_curve(tempc[j],tempc[j-1]); min_curve(c[j]+2,tempc[j]); } /* add fenceposts */ for(j=0;j<P_LEVELS;j++){ for(i=0;i<EHMER_OFFSET;i++) if(c[j][i+2]>-200.f)break; c[j][0]=i; for(i=EHMER_MAX-1;i>EHMER_OFFSET+1;i--) if(c[j][i+2]>-200.f) break; c[j][1]=i; } }