From bafbcd9bf16dbaca136ed65f000dd17b717534e5 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 29 Mar 2000 20:08:49 +0000 Subject: Incremental update svn path=/branches/unlabeled-1.16.2/vorbis/; revision=287 --- lib/psy.c | 252 ++++++++++++++++++++++++++------------------------------------ 1 file changed, 104 insertions(+), 148 deletions(-) diff --git a/lib/psy.c b/lib/psy.c index 16926b34..480e88a5 100644 --- a/lib/psy.c +++ b/lib/psy.c @@ -12,7 +12,7 @@ ******************************************************************** function: psychoacoustics not including preecho - last mod: $Id: psy.c,v 1.16.2.1 2000/03/29 03:49:28 xiphmont Exp $ + last mod: $Id: psy.c,v 1.16.2.2 2000/03/29 20:08:49 xiphmont Exp $ ********************************************************************/ @@ -26,6 +26,9 @@ #include "psy.h" #include "scales.h" +/* the beginnings of real psychoacoustic infrastructure. This is + still not tightly tuned */ + void _vi_psy_free(vorbis_info_psy *i){ if(i){ memset(i,0,sizeof(vorbis_info_psy)); @@ -74,25 +77,26 @@ static void linear_curve(double *c){ c[i]=fromdB(c[i]); } +static void interp_curve_dB(double *c,double *c1,double *c2,double del){ + int i; + for(i=0;itempc[i*2][j];j++){ + c[i*2][j]=att; + tempc[i*2][j]=att; + att+=peakhighrolloff; + } + att=peakatt_dB[i]+peaklowrolloff; + for(j=EHMER_OFFSET-1;j>=0 && att>tempc[i*2][j];j--){ + c[i*2][j]=att; + tempc[i*2][j]=att; + att+=peaklowrolloff; + } + } + + /* The c array is comes in as dB curves at 20 40 60 80 100 dB. interpolate intermediate dB curves */ - interp_curve(c[1],c[0],c[2],.5); - interp_curve(c[3],c[2],c[4],.5); - interp_curve(c[5],c[4],c[6],.5); - interp_curve(c[7],c[6],c[8],.5); - interp_curve(c[9],c[8],c[10],.5); - interp_curve(tempc[1],tempc[0],tempc[2],.5); - interp_curve(tempc[3],tempc[2],tempc[4],.5); - interp_curve(tempc[5],tempc[4],tempc[6],.5); - interp_curve(tempc[7],tempc[6],tempc[8],.5); - interp_curve(tempc[9],tempc[8],tempc[10],.5); + for(i=0;i<7;i+=2){ + interp_curve(c[i+1],c[i],c[i+2],.5); + interp_curve(tempc[i+1],tempc[i],tempc[i+2],.5); + } /* take things out of dB domain into linear amplitude */ - for(i=0;i<11;i++) + for(i=0;i<9;i++) linear_curve(c[i]); - for(i=0;i<11;i++) + for(i=0;i<9;i++) linear_curve(tempc[i]); /* Now limit the louder curves. the idea is this: We don't know what the playback attenuation - will be; 0dB moves every time the user twiddles the volume + 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 0-120dB SL. However, sounds - 20dB down will be in a range of 0-100, 40dB down is from 0-80, + 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(i=10;i>=0;i--){ - analysis("Craw",oc*100+i,c[i],EHMER_MAX,0,1); - analysis("Ctemp",oc*100+i,tempc[i],EHMER_MAX,0,1); + + for(i=8;i>=0;i--){ for(j=0;jath, p->ath,n,rate); + set_curve(ATH_Bark_dB, p->ath,n,rate); for(i=0;ipre[i]=(pre<0?0:pre); p->octave[i]=oc; - p->post[i]=(postpost[i]=(post<0?0:post); } p->curves=malloc(11*sizeof(double **)); for(i=0;i<11;i++) - p->curves[i]=malloc(11*sizeof(double *)); + p->curves[i]=malloc(9*sizeof(double *)); for(i=0;i<11;i++) - for(j=0;j<11;j++) + for(j=0;j<9;j++) p->curves[i][j]=malloc(EHMER_MAX*sizeof(double)); memcpy(p->curves[0][2],tone_250_40dB_SL,sizeof(double)*EHMER_MAX); @@ -234,12 +234,22 @@ void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,int n,long rate){ memcpy(p->curves[10][6],tone_4000_80dB_SL,sizeof(double)*EHMER_MAX); memcpy(p->curves[10][8],tone_8000_100dB_SL,sizeof(double)*EHMER_MAX); + setup_curve(p->curves[0],0,vi->curveatt_250Hz,vi->peakatt_250Hz, + vi->peakpre,vi->peakpost); + setup_curve(p->curves[2],2,vi->curveatt_500Hz,vi->peakatt_500Hz, + vi->peakpre,vi->peakpost); + setup_curve(p->curves[4],4,vi->curveatt_1000Hz,vi->peakatt_1000Hz, + vi->peakpre,vi->peakpost); + setup_curve(p->curves[6],6,vi->curveatt_2000Hz,vi->peakatt_2000Hz, + vi->peakpre,vi->peakpost); + setup_curve(p->curves[8],8,vi->curveatt_4000Hz,vi->peakatt_4000Hz, + vi->peakpre,vi->peakpost); + setup_curve(p->curves[10],10,vi->curveatt_8000Hz,vi->peakatt_8000Hz, + vi->peakpre,vi->peakpost); + for(i=1;i<11;i+=2) - for(j=0;j<11;j+=2) - interp_curve(p->curves[i][j],p->curves[i-1][j],p->curves[i+1][j],.5); - - for(i=0;i<11;i++) - setup_curve(p->curves[i],i,-35.,-40.,-60.,-80.,-100.,-105.); + for(j=0;j<9;j+=2) + interp_curve_dB(p->curves[i][j],p->curves[i-1][j],p->curves[i+1][j],.5); } @@ -252,7 +262,7 @@ void _vp_psy_clear(vorbis_look_psy *p){ if(p->post)free(p->post); if(p->curves){ for(i=0;i<11;i++){ - for(j=0;j<11;j++) + for(j=0;j<9;j++) free(p->curves[i][j]); free(p->curves[i]); } @@ -295,40 +305,41 @@ static double _eights[EHMER_MAX]={ static double seed_peaks(double *floor,int *len,double **curve, double amp,double specmax, int *pre,int *post, - int x,int n,int addp){ + int x,int n,double specatt){ int i; int ix=x*_eights[0]; - int prevx=(ix<0?-1:pre[ix]); + int prevx=pre[ix]; int nextx; double ret=0.; /* make this attenuation adjustable */ - int choice=rint((amp-specmax+100.)/10.)-2; + int choice=rint((amp-specmax+specatt)/10.)-2; if(choice<0)choice=0; if(choice>8)choice=8; amp=fromdB(amp); - for(i=0;ifloor[to]){ - /* new maximum */ - arbitrate_peak(floor,len,end,floor[to],len[to],n); - floor[to]=val; - len[to]=end; - }else - arbitrate_peak(floor,len,len[to],val,end,n); - } -} - -static void max_seeds(double *floor,int *len,int n){ - int i; - double acc=0.; - int end=0; - for(i=0;iacc){ - /* new maximum */ - arbitrate_peak(floor,len,len[i],acc,end,n); - acc=floor[i]; - end=len[i]; - }else{ - /* nope, but see if we're maximum later */ - arbitrate_peak(floor,len,end,floor[i],len[i],n); - } - floor[i]=(acc>0?todB(acc):-DYNAMIC_RANGE_dB); - } -} - /* octave/dB SL scale for masking curves, Bark/dB SPL scale for ATH. Why Bark scale for encoding but not masking? Because masking has a strong harmonic dependancy */ - -extern int frameno; void _vp_tone_tone_mask(vorbis_look_psy *p,double *f, double *flr, - int athp, int addp, int decayp, double *decay){ + int athp, int decayp, double *decay){ vorbis_info_psy *vi=p->vi; long n=p->n,i; double *acctemp=alloca(n*sizeof(double)); double *work=alloca(n*sizeof(double)); double *workdB=alloca(n*sizeof(double)); - /*double *max=alloca(n*sizeof(double)); - int *maxlen=alloca(n*sizeof(int));*/ double specmax=-DYNAMIC_RANGE_dB; double acc=0.; - /*memset(maxlen,0,n*sizeof(int));*/ for(i=0;i0;i--)work[i]=hypot(work[i],work[i-1]);*/ - /* handle decay */ if(decayp){ double decscale=1.-pow(vi->decay_coeff,n); @@ -421,13 +389,6 @@ void _vp_tone_tone_mask(vorbis_look_psy *p,double *f, double *flr, if(workdB[i]>specmax)specmax=workdB[i]; } - /* subtract the absolute threshhold of hearing curve so the Ehmer - curves can be used on the data directly */ - for(i=0;iath[i]; clearly incorrect; ehmer's early data is not - on an ATH relative scale */ - /*max[i]= -DYNAMIC_RANGE_dB;*/ - } memset(flr,0,sizeof(double)*n); /* prime the working vector with peak values */ @@ -438,26 +399,21 @@ void _vp_tone_tone_mask(vorbis_look_psy *p,double *f, double *flr, int o=rint(p->octave[i]*2.); if(o<0)o=0; if(o>10)o=10; + acc+=seed_peaks(flr,NULL,p->curves[o],workdB[i], - specmax,p->pre,p->post,i,n,1); - /*seed_peaks(max,maxlen,p->curves[o],workdB[i], - specmax,p->pre,p->post,i,n,0);*/ + specmax,p->pre,p->post,i,n,vi->max_curve_dB); } acctemp[i]=acc; } /* now, chase curves down from the peak seeds */ add_seeds(flr,n); - /*max_seeds(max,maxlen,n);*/ - - - analysis("Pwork",frameno,workdB,n,1,0); - analysis("Padd",frameno,flr,n,1,0); - analysis("Pacc",frameno,acctemp,n,1,1); - /* analysis("Pmax",frameno,max,n,1,0);*/ - for(i=0;iath[i]-vi->master_att)flr[i]=p->ath[i]-vi->master_att; - for(i=0;iath[i]+vi->ath_att) + flr[i]=p->ath[i]+vi->ath_att; } -- cgit v1.2.1