📄 psy.c
字号:
float *residue,
int sliding_lowpass){
int i,n=p->n;
if(sliding_lowpass>n)sliding_lowpass=n;
for(i=0;i<sliding_lowpass;i++){
residue[i]=
mdct[i]*FLOOR1_fromdB_INV_LOOKUP[codedflr[i]];
}
for(;i<n;i++)
residue[i]=0.0f;
}
void _vp_noisemask(vorbis_look_psy *p,
float *logmdct,
float *logmask){
int i,n=p->n;
float *work=alloca(n*sizeof(*work));
bark_noise_hybridmp(n,p->bark,logmdct,logmask,
140.,-1);
for(i=0;i<n;i++)work[i]=logmdct[i]-logmask[i];
bark_noise_hybridmp(n,p->bark,work,logmask,0.,
p->vi->noisewindowfixed);
for(i=0;i<n;i++)work[i]=logmdct[i]-work[i];
for(i=0;i<n;i++){
int dB=(int)(logmask[i]+0.5f);
if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1;
if(dB<0)dB=0;
logmask[i]= work[i]+p->vi->noisecompand[dB];
}
}
void _vp_tonemask(vorbis_look_psy *p,
float *logfft,
float *logmask,
float global_specmax,
float local_specmax){
int i,n=p->n;
float *seed=alloca(sizeof(*seed)*p->total_octave_lines);
float att=local_specmax+p->vi->ath_adjatt;
for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF;
/* set the ATH (floating below localmax, not global max by a
specified att) */
if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt;
for(i=0;i<n;i++)
logmask[i]=p->ath[i]+att;
/* tone masking */
seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax);
max_seeds(p,seed,logmask);
}
void _vp_offset_and_mix(vorbis_look_psy *p,
float *noise,
float *tone,
int offset_select,
float *logmask){
int i,n=p->n;
float toneatt=p->vi->tone_masteratt[offset_select];
for(i=0;i<n;i++){
float val= noise[i]+p->noiseoffset[offset_select][i];
if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp;
logmask[i]=max(val,tone[i]+toneatt);
}
}
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=ogg_fabs(*qA)>ogg_fabs(*qB);
test1-= ogg_fabs(*qA)<ogg_fabs(*qB);
if(!test1) test1=(int)(((ogg_fabs(A)>ogg_fabs(B))<<1) - 1.0f);
if(test1==1){
*qB=(*qA>0.0f?*qA-*qB:*qB-*qA);
}else{
float temp=*qB;
*qB=(*qB>0.f?*qA-*qB:*qB-*qA);
*qA=temp;
}
if(*qB>ogg_fabs(*qA)*1.9999f){
*qB=-ogg_fabs(*qA)*2.0f;
*qA=-*qA;
}
}
static float hypot_lookup[32]={
-0.009935f, -0.011245f, -0.012726f, -0.014397f,
-0.016282f, -0.018407f, -0.020800f, -0.023494f,
-0.026522f, -0.029923f, -0.033737f, -0.038010f,
-0.042787f, -0.048121f, -0.054064f, -0.060671f,
-0.068000f, -0.076109f, -0.085054f, -0.094892f,
-0.105675f, -0.117451f, -0.130260f, -0.144134f,
-0.159093f, -0.175146f, -0.192286f, -0.210490f,
-0.229718f, -0.249913f, -0.271001f, -0.292893f};
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.0f;
}
/* 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)/ogg_sqrt(2) */
static float dipole_hypot(float a, float b){
if(a>0.0f){
if(b>0.0f)return ogg_sqrt(a*a+b*b);
if(a>-b)return ogg_sqrt(a*a-b*b);
return -ogg_sqrt(b*b-a*a);
}
if(b<0.0f)return -ogg_sqrt(a*a+b*b);
if(-a>b)return -ogg_sqrt(a*a-b*b);
return ogg_sqrt(b*b-a*a);
}
static float round_hypot(float a, float b){
if(a>0.0f){
if(b>0.0f)return ogg_sqrt(a*a+b*b);
if(a>-b)return ogg_sqrt(a*a+b*b);
return -ogg_sqrt(b*b+a*a);
}
if(b<0.0f)return -ogg_sqrt(a*a+b*b);
if(-a>b)return -ogg_sqrt(a*a+b*b);
return ogg_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;i<vi->coupling_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;j<limit;j++)
ret[i][j]=dipole_hypot(mdctM[j],mdctA[j]);
for(;j<n;j++)
ret[i][j]=round_hypot(mdctM[j],mdctA[j]);
}
return(ret);
}
/* this is for per-channel noise normalization */
static int apsort(const void *a, const void *b){
float f1=ogg_fabs(**(float**)a);
float f2=ogg_fabs(**(float**)b);
return (f1<f2)-(f1>f2);
}
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;
float **work=alloca(sizeof(*work)*partition);
for(i=0;i<vi->coupling_steps;i++){
ret[i]=_vorbis_block_alloc(vb,n*sizeof(**ret));
for(j=0;j<n;j+=partition){
for(k=0;k<partition;k++)work[k]=mags[i]+k+j;
qsort(work,partition,sizeof(*work),apsort);
for(k=0;k<partition;k++)ret[i][k+j]=(int)(work[k]-mags[i]);
}
}
return(ret);
}
return(NULL);
}
void _vp_noise_normalize_sort(vorbis_look_psy *p,
float *magnitudes,int *sortedindex){
int i,j,n=p->n;
vorbis_info_psy *vi=p->vi;
int partition=vi->normal_partition;
float **work=alloca(sizeof(*work)*partition);
int start=vi->normal_start;
for(j=start;j<n;j+=partition){
if(j+partition>n)partition=n-j;
for(i=0;i<partition;i++)work[i]=magnitudes+i+j;
qsort(work,partition,sizeof(*work),apsort);
for(i=0;i<partition;i++){
sortedindex[i+j-start]=(int)(work[i]-magnitudes);
}
}
}
void _vp_noise_normalize(vorbis_look_psy *p,
float *in,float *out,int *sortedindex){
int flag=0,i,j=0,n=p->n;
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<start;j++)
out[j]=ogg_rint(in[j]);
for(;j+partition<=n;j+=partition){
float acc=0.0f;
int k;
for(i=j;i<j+partition;i++)
acc+=in[i]*in[i];
for(i=0;i<partition;i++){
k=sortedindex[i+j-start];
if(in[k]*in[k]>=.25f){
out[k]=ogg_rint(in[k]);
acc-=in[k]*in[k];
flag=1;
}else{
if(acc<vi->normal_thresh)break;
out[k]=unitnorm(in[k]);
acc-=1.0f;
}
}
for(;i<partition;i++){
k=sortedindex[i+j-start];
out[k]=0.0f;
}
}
}
for(;j<n;j++)
out[j]=ogg_rint(in[j]);
}
void _vp_couple(int blobno,
vorbis_info_psy_global *g,
vorbis_look_psy *p,
vorbis_info_mapping0 *vi,
float **res,
float **mag_memo,
int **mag_sort,
int **ifloor,
int *nonzero,
int sliding_lowpass)
{
int i,j,k,n=p->n;
/* 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;i<vi->coupling_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;
for(j=0;j<p->n;j+=partition){
float acc=0.f;
for(k=0;k<partition;k++){
int l=k+j;
if(l<sliding_lowpass){
if((l>=limit && ogg_fabs(rM[l])<postpoint && ogg_fabs(rA[l])<postpoint) ||
(ogg_fabs(rM[l])<prepoint && ogg_fabs(rA[l])<prepoint)){
precomputed_couple_point(mag_memo[i][l],
floorM[l],floorA[l],
qM+l,qA+l);
if(ogg_rint(qM[l])==0.f)acc+=qM[l]*qM[l];
}else{
couple_lossless(rM[l],rA[l],qM+l,qA+l);
}
}else{
qM[l]=0.0f;
qA[l]=0.0f;
}
}
if(p->vi->normal_point_p){
for(k=0;k<partition && acc>=p->vi->normal_thresh;k++){
int l=mag_sort[i][j+k];
if(l<sliding_lowpass && l>=pointlimit && ogg_rint(qM[l])==0.f){
qM[l]=unitnorm(qM[l]);
acc-=1.0f;
}
}
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -