/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * by the XIPHOPHORUS Company http://www.xiph.org/ * * * ******************************************************************** function: psychoacoustics not including preecho last mod: $Id: psy.c 7187 2004-07-20 07:24:27Z xiphmont $ ********************************************************************/ #include #include #include #include "vorbis/codec.h" #include "codec_internal.h" #include "masking.h" #include "psy.h" #include "os.h" #include "lpc.h" #include "smallft.h" #include "scales.h" #include "misc.h" #define NEGINF -9999.f static double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10}; static double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10}; vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){ codec_setup_info *ci=vi->codec_setup; vorbis_info_psy_global *gi=&ci->psy_g_param; vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look)); look->channels=vi->channels; look->ampmax=-9999.; look->gi=gi; return(look); } void _vp_global_free(vorbis_look_psy_global *look){ if(look){ memset(look,0,sizeof(*look)); _ogg_free(look); } } void _vi_gpsy_free(vorbis_info_psy_global *i){ if(i){ memset(i,0,sizeof(*i)); _ogg_free(i); } } void _vi_psy_free(vorbis_info_psy *i){ if(i){ memset(i,0,sizeof(*i)); _ogg_free(i); } } static void min_curve(float *c, float *c2){ int i; for(i=0;ic[i])c[i]=c2[i]; } static void attenuate_curve(float *c,float att){ int i; for(i=0;iATH[j+k+ath_offset])min=ATH[j+k+ath_offset]; }else{ if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1]; } ath[j]=min; } /* copy curves into working space, replicate the 50dB curve to 30 and 40, replicate the 100dB curve to 110 */ for(j=0;j<6;j++) memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j])); memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); /* apply centered curve boost/decay */ for(j=0;j0)adj=0.; if(adj>0. && center_boost<0)adj=0.; workc[i][j][k]+=adj; } } /* normalize curves so the driving amplitude is 0dB */ /* make temp curves with the ATH overlayed */ for(j=0;j an eighth of an octave and that the eighth octave values may also be composited. */ /* which octave curves will we be compositing? */ bin=floor(fromOC(i*.5)/binHz); lo_curve= ceil(toOC(bin*binHz+1)*2); hi_curve= floor(toOC((bin+1)*binHz)*2); if(lo_curve>i)lo_curve=i; if(lo_curve<0)lo_curve=0; if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1; for(m=0;mn)lo_bin=n; if(lo_binn)hi_bin=n; for(;lworkc[k][m][j]) brute_buffer[l]=workc[k][m][j]; } for(;lworkc[k][m][EHMER_MAX-1]) brute_buffer[l]=workc[k][m][EHMER_MAX-1]; } /* be equally paranoid about being valid up to next half ocatve */ if(i+1n)lo_bin=n; if(lo_binn)hi_bin=n; for(;lworkc[k][m][j]) brute_buffer[l]=workc[k][m][j]; } for(;lworkc[k][m][EHMER_MAX-1]) brute_buffer[l]=workc[k][m][EHMER_MAX-1]; } for(j=0;j=n){ ret[i][m][j+2]=-999.; }else{ ret[i][m][j+2]=brute_buffer[bin]; } } } /* add fenceposts */ for(j=0;j-200.f)break; ret[i][m][0]=j; for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--) if(ret[i][m][j+2]>-200.f) break; ret[i][m][1]=j; } } #ifdef Plan9 free(brute_buffer); #endif return(ret); } 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=_ogg_malloc(n*sizeof(*p->ath)); p->octave=_ogg_malloc(n*sizeof(*p->octave)); p->bark=_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;iath[j]=base+100.; base+=delta; } } } for(i=0;inoisewindowlominnoisewindowlo);lo++); for(;hi<=n && (hinoisewindowhimin || toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++); p->bark[i]=((lo-1)<<16)+(hi-1); } for(i=0;ioctave[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=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset)); for(i=0;inoiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset)); for(i=0;i=P_BANDS-1)halfoc=P_BANDS-1; inthalfoc=(int)halfoc; del=halfoc-inthalfoc; for(j=0;jnoiseoffset[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 } void _vp_psy_clear(vorbis_look_psy *p){ int i,j; if(p){ if(p->ath)_ogg_free(p->ath); if(p->octave)_ogg_free(p->octave); if(p->bark)_ogg_free(p->bark); if(p->tonecurves){ for(i=0;itonecurves[i][j]); } _ogg_free(p->tonecurves[i]); } _ogg_free(p->tonecurves); } if(p->noiseoffset){ for(i=0;inoiseoffset[i]); } _ogg_free(p->noiseoffset); } memset(p,0,sizeof(*p)); } } /* octave/(8*eighth_octave_lines) x scale and dB y scale */ static void seed_curve(float *seed, const float **curves, float amp, int oc, int n, int linesper,float dBoffset){ int i,post1; int seedptr; const float *posts,*curve; int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f); choice=max(choice,0); choice=min(choice,P_LEVELS-1); posts=curves[choice]; curve=posts+2; post1=(int)posts[1]; seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1); for(i=posts[0];i0){ float lin=amp+curve[i]; if(seed[seedptr]=n)break; } } static void seed_loop(vorbis_look_psy *p, const float ***curves, const float *f, const float *flr, float *seed, float specmax){ vorbis_info_psy *vi=p->vi; long n=p->n,i; float dBoffset=vi->max_curve_dB-specmax; /* prime the working vector with peak values */ for(i=0;ioctave[i]; while(i+1octave[i+1]==oc){ i++; if(f[i]>max)max=f[i]; } if(max+6.f>flr[i]){ oc=oc>>p->shiftoc; if(oc>=P_BANDS)oc=P_BANDS-1; if(oc<0)oc=0; seed_curve(seed, curves[oc], max, p->octave[i]-p->firstoc, p->total_octave_lines, p->eighth_octave_lines, dBoffset); } } } static void seed_chase(float *seeds, int linesper, long n){ #ifdef Plan9 long *posstack=malloc(n*sizeof(*posstack)); float *ampstack=malloc(n*sizeof(*ampstack)); #else long *posstack=alloca(n*sizeof(*posstack)); float *ampstack=alloca(n*sizeof(*ampstack)); #endif long stack=0; long pos=0; long i; for(i=0;i1 && ampstack[stack-1]<=ampstack[stack-2] && iampstack[i]){ endpos=posstack[i+1]; }else{ endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is discarded in short frames */ } if(endpos>n)endpos=n; for(;pos static void max_seeds(vorbis_look_psy *p, float *seed, float *flr){ long n=p->total_octave_lines; int linesper=p->eighth_octave_lines; long linpos=0; long pos; seed_chase(seed,linesper,n); /* for masking */ pos=p->octave[0]-p->firstoc-(linesper>>1); while(linpos+1n){ float minV=seed[pos]; long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc; if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit; while(pos+1<=end){ pos++; if((seed[pos]>NEGINF && seed[pos]firstoc; for(;linposn && p->octave[linpos]<=end;linpos++) if(flr[linpos]total_octave_lines-1]; for(;linposn;linpos++) if(flr[linpos]> 16; if( lo>=0 ) break; hi = b[i] & 0xffff; tN = N[hi] + N[-lo]; tX = X[hi] - X[-lo]; tXX = XX[hi] + XX[-lo]; tY = Y[hi] + Y[-lo]; tXY = XY[hi] - XY[-lo]; A = tY * tXX - tX * tXY; B = tN * tXY - tX * tY; D = tN * tXX - tX * tX; R = (A + x * B) / D; if (R < 0.f) R = 0.f; noise[i] = R - offset; } for ( ;; i++, x += 1.f) { lo = b[i] >> 16; hi = b[i] & 0xffff; if(hi>=n)break; tN = N[hi] - N[lo]; tX = X[hi] - X[lo]; tXX = XX[hi] - XX[lo]; tY = Y[hi] - Y[lo]; tXY = XY[hi] - XY[lo]; A = tY * tXX - tX * tXY; B = tN * tXY - tX * tY; D = tN * tXX - tX * tX; R = (A + x * B) / D; if (R < 0.f) R = 0.f; noise[i] = R - offset; } for ( ; i < n; i++, x += 1.f) { R = (A + x * B) / D; if (R < 0.f) R = 0.f; noise[i] = R - offset; } #ifdef Plan9 if(fixed <= 0){ free(N); free(X); free(XX); free(Y); free(XY); return; } #else if (fixed <= 0) return; #endif for (i = 0, x = 0.f;; i++, x += 1.f) { hi = i + fixed / 2; lo = hi - fixed; if(lo>=0)break; tN = N[hi] + N[-lo]; tX = X[hi] - X[-lo]; tXX = XX[hi] + XX[-lo]; tY = Y[hi] + Y[-lo]; tXY = XY[hi] - XY[-lo]; A = tY * tXX - tX * tXY; B = tN * tXY - tX * tY; D = tN * tXX - tX * tX; R = (A + x * B) / D; if (R - offset < noise[i]) noise[i] = R - offset; } for ( ;; i++, x += 1.f) { hi = i + fixed / 2; lo = hi - fixed; if(hi>=n)break; tN = N[hi] - N[lo]; tX = X[hi] - X[lo]; tXX = XX[hi] - XX[lo]; tY = Y[hi] - Y[lo]; tXY = XY[hi] - XY[lo]; A = tY * tXX - tX * tXY; B = tN * tXY - tX * tY; D = tN * tXX - tX * tX; R = (A + x * B) / D; if (R - offset < noise[i]) noise[i] = R - offset; } for ( ; i < n; i++, x += 1.f) { R = (A + x * B) / D; if (R - offset < noise[i]) noise[i] = R - offset; } #ifdef Plan9 free(N); free(X); free(XX); free(Y); free(XY); #endif } static float FLOOR1_fromdB_INV_LOOKUP[256]={ 0.F, 8.81683e+06F, 8.27882e+06F, 7.77365e+06F, 7.29930e+06F, 6.85389e+06F, 6.43567e+06F, 6.04296e+06F, 5.67422e+06F, 5.32798e+06F, 5.00286e+06F, 4.69759e+06F, 4.41094e+06F, 4.14178e+06F, 3.88905e+06F, 3.65174e+06F, 3.42891e+06F, 3.21968e+06F, 3.02321e+06F, 2.83873e+06F, 2.66551e+06F, 2.50286e+06F, 2.35014e+06F, 2.20673e+06F, 2.07208e+06F, 1.94564e+06F, 1.82692e+06F, 1.71544e+06F, 1.61076e+06F, 1.51247e+06F, 1.42018e+06F, 1.33352e+06F, 1.25215e+06F, 1.17574e+06F, 1.10400e+06F, 1.03663e+06F, 973377.F, 913981.F, 858210.F, 805842.F, 756669.F, 710497.F, 667142.F, 626433.F, 588208.F, 552316.F, 518613.F, 486967.F, 457252.F, 429351.F, 403152.F, 378551.F, 355452.F, 333762.F, 313396.F, 294273.F, 276316.F, 259455.F, 243623.F, 228757.F, 214798.F, 201691.F, 189384.F, 177828.F, 166977.F, 156788.F, 147221.F, 138237.F, 129802.F, 121881.F, 114444.F, 107461.F, 100903.F, 94746.3F, 88964.9F, 83536.2F, 78438.8F, 73652.5F, 69158.2F, 64938.1F, 60975.6F, 57254.9F, 53761.2F, 50480.6F, 47400.3F, 44507.9F, 41792.0F, 39241.9F, 36847.3F, 34598.9F, 32487.7F, 30505.3F, 28643.8F, 26896.0F, 25254.8F, 23713.7F, 22266.7F, 20908.0F, 19632.2F, 18434.2F, 17309.4F, 16253.1F, 15261.4F, 14330.1F, 13455.7F, 12634.6F, 11863.7F, 11139.7F, 10460.0F, 9821.72F, 9222.39F, 8659.64F, 8131.23F, 7635.06F, 7169.17F, 6731.70F, 6320.93F, 5935.23F, 5573.06F, 5232.99F, 4913.67F, 4613.84F, 4332.30F, 4067.94F, 3819.72F, 3586.64F, 3367.78F, 3162.28F, 2969.31F, 2788.13F, 2617.99F, 2458.24F, 2308.24F, 2167.39F, 2035.14F, 1910.95F, 1794.35F, 1684.85F, 1582.04F, 1485.51F, 1394.86F, 1309.75F, 1229.83F, 1154.78F, 1084.32F, 1018.15F, 956.024F, 897.687F, 842.910F, 791.475F, 743.179F, 697.830F, 655.249F, 615.265F, 577.722F, 542.469F, 509.367F, 478.286F, 449.101F, 421.696F, 395.964F, 371.803F, 349.115F, 327.812F, 307.809F, 289.026F, 271.390F, 254.830F, 239.280F, 224.679F, 210.969F, 198.096F, 186.008F, 174.658F, 164.000F, 153.993F, 144.596F, 135.773F, 127.488F, 119.708F, 112.404F, 105.545F, 99.1046F, 93.0572F, 87.3788F, 82.0469F, 77.0404F, 72.3394F, 67.9252F, 63.7804F, 59.8885F, 56.2341F, 52.8027F, 49.5807F, 46.5553F, 43.7144F, 41.0470F, 38.5423F, 36.1904F, 33.9821F, 31.9085F, 29.9614F, 28.1332F, 26.4165F, 24.8045F, 23.2910F, 21.8697F, 20.5352F, 19.2822F, 18.1056F, 17.0008F, 15.9634F, 14.9893F, 14.0746F, 13.2158F, 12.4094F, 11.6522F, 10.9411F, 10.2735F, 9.64662F, 9.05798F, 8.50526F, 7.98626F, 7.49894F, 7.04135F, 6.61169F, 6.20824F, 5.82941F, 5.47370F, 5.13970F, 4.82607F, 4.53158F, 4.25507F, 3.99542F, 3.75162F, 3.52269F, 3.30774F, 3.10590F, 2.91638F, 2.73842F, 2.57132F, 2.41442F, 2.26709F, 2.12875F, 1.99885F, 1.87688F, 1.76236F, 1.65482F, 1.55384F, 1.45902F, 1.36999F, 1.28640F, 1.20790F, 1.13419F, 1.06499F, 1.F }; void _vp_remove_floor(vorbis_look_psy *p, float *mdct, int *codedflr, float *residue, int sliding_lowpass){ int i,n=p->n; if(sliding_lowpass>n)sliding_lowpass=n; for(i=0;in; #ifdef Plan9 float *work=malloc(n*sizeof(*work)); #else float *work=alloca(n*sizeof(*work)); #endif bark_noise_hybridmp(n,p->bark,logmdct,logmask, 140.,-1); for(i=0;ibark,work,logmask,0., p->vi->noisewindowfixed); for(i=0;i=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1; if(dB<0)dB=0; logmask[i]= work[i]+p->vi->noisecompand[dB]; } #ifdef Plan9 free(work); #endif } void _vp_tonemask(vorbis_look_psy *p, float *logfft, float *logmask, float global_specmax, float local_specmax){ int i,n=p->n; #ifdef Plan9 float *seed=malloc(sizeof(*seed)*p->total_octave_lines); #else float *seed=alloca(sizeof(*seed)*p->total_octave_lines); #endif float att=local_specmax+p->vi->ath_adjatt; for(i=0;itotal_octave_lines;i++)seed[i]=NEGINF; /* set the ATH (floating below localmax, not global max by a specified att) */ if(attvi->ath_maxatt)att=p->vi->ath_maxatt; for(i=0;iath[i]+att; /* tone masking */ seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax); max_seeds(p,seed,logmask); #ifdef Plan9 free(seed); #endif } void _vp_offset_and_mix(vorbis_look_psy *p, float *noise, float *tone, int offset_select, float *logmask, float *mdct, float *logmdct){ int i,n=p->n; float de, coeffi, cx;/* AoTuV */ float toneatt=p->vi->tone_masteratt[offset_select]; cx = p->m_val; for(i=0;inoiseoffset[offset_select][i]; if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp; logmask[i]=max(val,tone[i]+toneatt); /* AoTuV */ /** @ M1 ** The following codes improve a noise problem. A fundamental idea uses the value of masking and carries out the relative compensation of the MDCT. However, this code is not perfect and all noise problems cannot be solved. by Aoyumi @ 2004/04/18 */ if(offset_select == 1) { coeffi = -17.2; /* coeffi is a -17.2dB threshold */ val = val - logmdct[i]; /* val == mdct line value relative to floor in dB */ if(val > coeffi){ /* mdct value is > -17.2 dB below floor */ de = 1.0-((val-coeffi)*0.005*cx); /* pro-rated attenuation: -0.00 dB boost if mdct value is -17.2dB (relative to floor) -0.77 dB boost if mdct value is 0dB (relative to floor) -1.64 dB boost if mdct value is +17.2dB (relative to floor) etc... */ if(de < 0) de = 0.0001; }else /* mdct value is <= -17.2 dB below floor */ de = 1.0-((val-coeffi)*0.0003*cx); /* pro-rated attenuation: +0.00 dB atten if mdct value is -17.2dB (relative to floor) +0.45 dB atten if mdct value is -34.4dB (relative to floor) etc... */ mdct[i] *= de; } } } float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){ vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; vorbis_info_psy_global *gi=&ci->psy_g_param; int n=ci->blocksizes[vd->W]/2; float secs=(float)n/vi->rate; amp+=secs*gi->ampmax_att_per_sec; if(amp<-9999)amp=-9999; return(amp); } static void couple_lossless(float A, float B, float *qA, float *qB){ int test1=fabs(*qA)>fabs(*qB); test1-= fabs(*qA)fabs(B))<<1)-1; if(test1==1){ *qB=(*qA>0.f?*qA-*qB:*qB-*qA); }else{ float temp=*qB; *qB=(*qB>0.f?*qA-*qB:*qB-*qA); *qA=temp; } if(*qB>fabs(*qA)*1.9999f){ *qB= -fabs(*qA)*2.f; *qA= -*qA; } } static float hypot_lookup[32]={ -0.009935, -0.011245, -0.012726, -0.014397, -0.016282, -0.018407, -0.020800, -0.023494, -0.026522, -0.029923, -0.033737, -0.038010, -0.042787, -0.048121, -0.054064, -0.060671, -0.068000, -0.076109, -0.085054, -0.094892, -0.105675, -0.117451, -0.130260, -0.144134, -0.159093, -0.175146, -0.192286, -0.210490, -0.229718, -0.249913, -0.271001, -0.292893}; static void precomputed_couple_point(float premag, int floorA,int floorB, float *mag, float *ang){ int test=(floorA>floorB)-1; int offset=31-abs(floorA-floorB); float floormag=hypot_lookup[((offset<0)-1)&offset]+1.f; floormag*=FLOOR1_fromdB_INV_LOOKUP[(floorB&test)|(floorA&(~test))]; *mag=premag*floormag; *ang=0.f; } /* just like below, this is currently set up to only do single-step-depth coupling. Otherwise, we'd have to do more copying (which will be inevitable later) */ /* doing the real circular magnitude calculation is audibly superior to (A+B)/sqrt(2) */ static float dipole_hypot(float a, float b){ if(a>0.){ if(b>0.)return sqrt(a*a+b*b); if(a>-b)return sqrt(a*a-b*b); return -sqrt(b*b-a*a); } if(b<0.)return -sqrt(a*a+b*b); if(-a>b)return -sqrt(a*a-b*b); return sqrt(b*b-a*a); } static float round_hypot(float a, float b){ if(a>0.){ if(b>0.)return sqrt(a*a+b*b); if(a>-b)return sqrt(a*a+b*b); return -sqrt(b*b+a*a); } if(b<0.)return -sqrt(a*a+b*b); if(-a>b)return -sqrt(a*a+b*b); return sqrt(b*b+a*a); } /* revert to round hypot for now */ float **_vp_quantize_couple_memo(vorbis_block *vb, vorbis_info_psy_global *g, vorbis_look_psy *p, vorbis_info_mapping0 *vi, float **mdct){ int i,j,n=p->n; float **ret=_vorbis_block_alloc(vb,vi->coupling_steps*sizeof(*ret)); int limit=g->coupling_pointlimit[p->vi->blockflag][PACKETBLOBS/2]; for(i=0;icoupling_steps;i++){ float *mdctM=mdct[vi->coupling_mag[i]]; float *mdctA=mdct[vi->coupling_ang[i]]; ret[i]=_vorbis_block_alloc(vb,n*sizeof(**ret)); for(j=0;jf2); } int **_vp_quantize_couple_sort(vorbis_block *vb, vorbis_look_psy *p, vorbis_info_mapping0 *vi, float **mags){ if(p->vi->normal_point_p){ int i,j,k,n=p->n; int **ret=_vorbis_block_alloc(vb,vi->coupling_steps*sizeof(*ret)); int partition=p->vi->normal_partition; #ifdef Plan9 float **work=malloc(sizeof(*work)*partition); #else float **work=alloca(sizeof(*work)*partition); #endif for(i=0;icoupling_steps;i++){ ret[i]=_vorbis_block_alloc(vb,n*sizeof(**ret)); for(j=0;jn; vorbis_info_psy *vi=p->vi; int partition=vi->normal_partition; #ifdef Plan9 float **work=malloc(sizeof(*work)*partition); #else float **work=alloca(sizeof(*work)*partition); #endif int start=vi->normal_start; for(j=start;jn)partition=n-j; for(i=0;in; vorbis_info_psy *vi=p->vi; int partition=vi->normal_partition; int start=vi->normal_start; if(start>n)start=n; if(vi->normal_channel_p){ for(;j=.25f){ out[k]=rint(in[k]); acc-=in[k]*in[k]; flag=1; }else{ if(accnormal_thresh)break; out[k]=unitnorm(in[k]); acc-=1.; } } for(;in; /* perform any requested channel coupling */ /* point stereo can only be used in a first stage (in this encoder) because of the dependency on floor lookups */ for(i=0;icoupling_steps;i++){ /* once we're doing multistage coupling in which a channel goes through more than one coupling step, the floor vector magnitudes will also have to be recalculated an propogated along with PCM. Right now, we're not (that will wait until 5.1 most likely), so the code isn't here yet. The memory management here is all assuming single depth couplings anyway. */ /* make sure coupling a zero and a nonzero channel results in two nonzero channels. */ if(nonzero[vi->coupling_mag[i]] || nonzero[vi->coupling_ang[i]]){ float *rM=res[vi->coupling_mag[i]]; float *rA=res[vi->coupling_ang[i]]; float *qM=rM+n; float *qA=rA+n; int *floorM=ifloor[vi->coupling_mag[i]]; int *floorA=ifloor[vi->coupling_ang[i]]; float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]]; float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]]; int partition=(p->vi->normal_point_p?p->vi->normal_partition:p->n); int limit=g->coupling_pointlimit[p->vi->blockflag][blobno]; int pointlimit=limit; nonzero[vi->coupling_mag[i]]=1; nonzero[vi->coupling_ang[i]]=1; /* The threshold of a stereo is changed with the size of n */ if(n > 1000) postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]]; for(j=0;jn;j+=partition){ float acc=0.f; for(k=0;k=limit && fabs(rM[l])vi->normal_point_p){ for(k=0;k=p->vi->normal_thresh;k++){ int l=mag_sort[i][j+k]; if(l=pointlimit && rint(qM[l])==0.f){ qM[l]=unitnorm(qM[l]); acc-=1.f; } } } } } } } /* AoTuV */ /** @ M2 ** The boost problem by the combination of noise normalization and point stereo is eased. However, this is a temporary patch. by Aoyumi @ 2004/04/18 */ void hf_reduction(vorbis_info_psy_global *g, vorbis_look_psy *p, vorbis_info_mapping0 *vi, float **mdct){ int i,j,n=p->n, de=0.3*p->m_val; int limit=g->coupling_pointlimit[p->vi->blockflag][PACKETBLOBS/2]; int start=p->vi->normal_start; for(i=0; icoupling_steps; i++){ /* for(j=start; j