📄 floor1.c
字号:
int mse=0; int n=0; ady-=abs(base*adx); mse=(y-val); mse*=mse; n++; if(mdct[x]+info->twofitatten>=mask[x]){ if(y+info->maxover<val)return(1); if(y-info->maxunder>val)return(1); } while(++x<x1){ err=err+ady; if(err>=adx){ err-=adx; y+=sy; }else{ y+=base; } val=vorbis_dBquant(mask+x); mse+=((y-val)*(y-val)); n++; if(mdct[x]+info->twofitatten>=mask[x]){ if(val){ if(y+info->maxover<val)return(1); if(y-info->maxunder>val)return(1); } } } if(info->maxover*info->maxover/n>info->maxerr)return(0); if(info->maxunder*info->maxunder/n>info->maxerr)return(0); if(mse/n>info->maxerr)return(1); return(0);}static int post_Y(int *A,int *B,int pos){ if(A[pos]<0) return B[pos]; if(B[pos]<0) return A[pos]; return (A[pos]+B[pos])>>1;}static int seq=0;int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look, const float *logmdct, /* in */ const float *logmask){ long i,j; vorbis_info_floor1 *info=look->vi; long n=look->n; long posts=look->posts; long nonzero=0; lsfit_acc fits[VIF_POSIT+1]; int fit_valueA[VIF_POSIT+2]; /* index by range list position */ int fit_valueB[VIF_POSIT+2]; /* index by range list position */ int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */ int hineighbor[VIF_POSIT+2]; int *output=NULL; int memo[VIF_POSIT+2]; for(i=0;i<posts;i++)fit_valueA[i]=-200; /* mark all unused */ for(i=0;i<posts;i++)fit_valueB[i]=-200; /* mark all unused */ for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */ for(i=0;i<posts;i++)hineighbor[i]=1; /* 1 for the implicit post at n */ for(i=0;i<posts;i++)memo[i]=-1; /* no neighbor yet */ /* quantize the relevant floor points and collect them into line fit structures (one per minimal division) at the same time */ if(posts==0){ nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info); }else{ for(i=0;i<posts-1;i++) nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i], look->sorted_index[i+1],fits+i, n,info); } if(nonzero){ /* start by fitting the implicit base case.... */ int y0=-200; int y1=-200; fit_line(fits,posts-1,&y0,&y1); fit_valueA[0]=y0; fit_valueB[0]=y0; fit_valueB[1]=y1; fit_valueA[1]=y1; /* Non degenerate case */ /* start progressive splitting. This is a greedy, non-optimal algorithm, but simple and close enough to the best answer. */ for(i=2;i<posts;i++){ int sortpos=look->reverse_index[i]; int ln=loneighbor[sortpos]; int hn=hineighbor[sortpos]; /* eliminate repeat searches of a particular range with a memo */ if(memo[ln]!=hn){ /* haven't performed this error search yet */ int lsortpos=look->reverse_index[ln]; int hsortpos=look->reverse_index[hn]; memo[ln]=hn; { /* A note: we want to bound/minimize *local*, not global, error */ int lx=info->postlist[ln]; int hx=info->postlist[hn]; int ly=post_Y(fit_valueA,fit_valueB,ln); int hy=post_Y(fit_valueA,fit_valueB,hn); if(ly==-1 || hy==-1){ exit(1); } if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){ /* outside error bounds/begin search area. Split it. */ int ly0=-200; int ly1=-200; int hy0=-200; int hy1=-200; fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); /* store new edge values */ fit_valueB[ln]=ly0; if(ln==0)fit_valueA[ln]=ly0; fit_valueA[i]=ly1; fit_valueB[i]=hy0; fit_valueA[hn]=hy1; if(hn==1)fit_valueB[hn]=hy1; if(ly1>=0 || hy0>=0){ /* store new neighbor values */ for(j=sortpos-1;j>=0;j--) if(hineighbor[j]==hn) hineighbor[j]=i; else break; for(j=sortpos+1;j<posts;j++) if(loneighbor[j]==ln) loneighbor[j]=i; else break; } }else{ fit_valueA[i]=-200; fit_valueB[i]=-200; } } } } output=_vorbis_block_alloc(vb,sizeof(*output)*posts); output[0]=post_Y(fit_valueA,fit_valueB,0); output[1]=post_Y(fit_valueA,fit_valueB,1); /* fill in posts marked as not using a fit; we will zero back out to 'unused' when encoding them so long as curve interpolation doesn't force them into use */ for(i=2;i<posts;i++){ int ln=look->loneighbor[i-2]; int hn=look->hineighbor[i-2]; int x0=info->postlist[ln]; int x1=info->postlist[hn]; int y0=output[ln]; int y1=output[hn]; int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); int vx=post_Y(fit_valueA,fit_valueB,i); if(vx>=0 && predicted!=vx){ output[i]=vx; }else{ output[i]= predicted|0x8000; } } } return(output); } int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look, int *A,int *B, int del){ long i; long posts=look->posts; int *output=NULL; if(A && B){ output=_vorbis_block_alloc(vb,sizeof(*output)*posts); for(i=0;i<posts;i++){ output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16; if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000; } } return(output);}int floor1_encode(vorbis_block *vb,vorbis_look_floor1 *look, int *post,int *ilogmask){ long i,j; vorbis_info_floor1 *info=look->vi; long n=look->n; long posts=look->posts; codec_setup_info *ci=vb->vd->vi->codec_setup; int out[VIF_POSIT+2]; static_codebook **sbooks=ci->book_param; codebook *books=ci->fullbooks; static long seq=0; /* quantize values to multiplier spec */ if(post){ for(i=0;i<posts;i++){ int val=post[i]&0x7fff; switch(info->mult){ case 1: /* 1024 -> 256 */ val>>=2; break; case 2: /* 1024 -> 128 */ val>>=3; break; case 3: /* 1024 -> 86 */ val/=12; break; case 4: /* 1024 -> 64 */ val>>=4; break; } post[i]=val | (post[i]&0x8000); } out[0]=post[0]; out[1]=post[1]; /* find prediction values for each post and subtract them */ for(i=2;i<posts;i++){ int ln=look->loneighbor[i-2]; int hn=look->hineighbor[i-2]; int x0=info->postlist[ln]; int x1=info->postlist[hn]; int y0=post[ln]; int y1=post[hn]; int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); if((post[i]&0x8000) || (predicted==post[i])){ post[i]=predicted|0x8000; /* in case there was roundoff jitter in interpolation */ out[i]=0; }else{ int headroom=(look->quant_q-predicted<predicted? look->quant_q-predicted:predicted); int val=post[i]-predicted; /* at this point the 'deviation' value is in the range +/- max range, but the real, unique range can always be mapped to only [0-maxrange). So we want to wrap the deviation into this limited range, but do it in the way that least screws an essentially gaussian probability distribution. */ if(val<0) if(val<-headroom) val=headroom-val-1; else val=-1-(val<<1); else if(val>=headroom) val= val+headroom; else val<<=1; out[i]=val; post[ln]&=0x7fff; post[hn]&=0x7fff; } } /* we have everything we need. pack it out */ /* mark nontrivial floor */ oggpack_write(&vb->opb,1,1); /* beginning/end post */ look->frames++; look->postbits+=ilog(look->quant_q-1)*2; oggpack_write(&vb->opb,out[0],ilog(look->quant_q-1)); oggpack_write(&vb->opb,out[1],ilog(look->quant_q-1)); /* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ int class=info->partitionclass[i]; int cdim=info->class_dim[class]; int csubbits=info->class_subs[class]; int csub=1<<csubbits; int bookas[8]={0,0,0,0,0,0,0,0}; int cval=0; int cshift=0; int k,l; /* generate the partition's first stage cascade value */ if(csubbits){ int maxval[8]; for(k=0;k<csub;k++){ int booknum=info->class_subbook[class][k]; if(booknum<0){ maxval[k]=1; }else{ maxval[k]=sbooks[info->class_subbook[class][k]]->entries; } } for(k=0;k<cdim;k++){ for(l=0;l<csub;l++){ int val=out[j+k]; if(val<maxval[l]){ bookas[k]=l; break; } } cval|= bookas[k]<<cshift; cshift+=csubbits; } /* write it */ look->phrasebits+= vorbis_book_encode(books+info->class_book[class],cval,&vb->opb); #ifdef TRAIN_FLOOR1 { FILE *of; char buffer[80]; sprintf(buffer,"line_%dx%ld_class%d.vqd", vb->pcmend/2,posts-2,class); of=fopen(buffer,"a"); fprintf(of,"%d\n",cval); fclose(of); }#endif } /* write post values */ for(k=0;k<cdim;k++){ int book=info->class_subbook[class][bookas[k]]; if(book>=0){ /* hack to allow training with 'bad' books */ if(out[j+k]<(books+book)->entries) look->postbits+=vorbis_book_encode(books+book, out[j+k],&vb->opb); /*else fprintf(stderr,"+!");*/ #ifdef TRAIN_FLOOR1 { FILE *of; char buffer[80]; sprintf(buffer,"line_%dx%ld_%dsub%d.vqd", vb->pcmend/2,posts-2,class,bookas[k]); of=fopen(buffer,"a"); fprintf(of,"%d\n",out[j+k]); fclose(of); }#endif } } j+=cdim; } { /* generate quantized floor equivalent to what we'd unpack in decode */ /* render the lines */ int hx=0; int lx=0; int ly=post[0]*info->mult; for(j=1;j<look->posts;j++){ int current=look->forward_index[j]; int hy=post[current]&0x7fff; if(hy==post[current]){ hy*=info->mult; hx=info->postlist[current]; render_line0(lx,hx,ly,hy,ilogmask); lx=hx; ly=hy; } } for(j=hx;j<vb->pcmend/2;j++)ilogmask[j]=ly; /* be certain */ seq++; return(1); } }else{ oggpack_write(&vb->opb,0,1); memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask)); seq++; return(0); }}static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=vb->vd->vi->codec_setup; int i,j,k; codebook *books=ci->fullbooks; /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); /* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ int class=info->partitionclass[i]; int cdim=info->class_dim[class]; int csubbits=info->class_subs[class]; int csub=1<<csubbits; int cval=0; /* decode the partition's first stage cascade value */ if(csubbits){ cval=vorbis_book_decode(books+info->class_book[class],&vb->opb); if(cval==-1)goto eop; } for(k=0;k<cdim;k++){ int book=info->class_subbook[class][cval&(csub-1)]; cval>>=csubbits; if(book>=0){ if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) goto eop; }else{ fit_value[j+k]=0; } } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ for(i=2;i<look->posts;i++){ int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], fit_value[look->hineighbor[i-2]], info->postlist[i]); int hiroom=look->quant_q-predicted; int loroom=predicted; int room=(hiroom<loroom?hiroom:loroom)<<1; int val=fit_value[i]; if(val){ if(val>=room){ if(hiroom>loroom){ val = val-loroom; }else{ val = -1-(val-hiroom); } }else{ if(val&1){ val= -((val+1)>>1); }else{ val>>=1; } } fit_value[i]=val+predicted; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; }else{ fit_value[i]=predicted|0x8000; } } return(fit_value); } eop: return(NULL);}static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, float *out){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=vb->vd->vi->codec_setup; int n=ci->blocksizes[vb->W]/2; int j; if(memo){ /* render the lines */ int *fit_value=(int *)memo; int hx=0; int lx=0; int ly=fit_value[0]*info->mult; for(j=1;j<look->posts;j++){ int current=look->forward_index[j]; int hy=fit_value[current]&0x7fff; if(hy==fit_value[current]){ hy*=info->mult; hx=info->postlist[current]; render_line(lx,hx,ly,hy,out); lx=hx; ly=hy; } } for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */ return(1); } memset(out,0,sizeof(*out)*n); return(0);}/* export hooks */vorbis_func_floor floor1_exportbundle={ &floor1_pack,&floor1_unpack,&floor1_look,&floor1_free_info, &floor1_free_look,&floor1_inverse1,&floor1_inverse2};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -