📄 floor1.c
字号:
static void fit_line(lsfit_acc *a,int fits,int *y0,int *y1){
ogg_int32_t x=0,y=0,x2=0,y2=0,xy=0,n=0,an=0,i;
ogg_int32_t x0=a[0].x0;
ogg_int32_t x1=a[fits-1].x1;
for(i=0;i<fits;i++){
x+=a[i].xa;
y+=a[i].ya;
x2+=a[i].x2a;
y2+=a[i].y2a;
xy+=a[i].xya;
an+=a[i].an;
}
if(*y0>=0){
x+= x0;
y+= *y0;
x2+= x0 * x0;
y2+= *y0 * *y0;
xy+= *y0 * x0;
an++;
}
if(*y1>=0){
x+= x1;
y+= *y1;
x2+= x1 * x1;
y2+= *y1 * *y1;
xy+= *y1 * x1;
an++;
}
if(an){
/* need 64 bit multiplies, which C doesn't give portably as int */
float fx=(float)x;
float fy=(float)y;
float fx2=(float)x2;
float fxy=(float)xy;
float denom=1.0f/(an*fx2-fx*fx);
float a=(fy*fx2-fxy*fx)*denom;
float b=(an*fxy-fx*fy)*denom;
*y0 = (int)ogg_rint(a+b*x0);
*y1 = (int)ogg_rint(a+b*x1);
/* limit to our range! */
if(*y0>1023)*y0=1023;
if(*y1>1023)*y1=1023;
if(*y0<0)*y0=0;
if(*y1<0)*y1=0;
}else{
*y0=0;
*y1=0;
}
}
/*static void fit_line_point(lsfit_acc *a,int fits,int *y0,int *y1){
ogg_int32_t y=0;
int i;
for(i=0;i<fits && y==0;i++)
y+=a[i].ya;
*y0=*y1=y;
}*/
static int inspect_error(int x0,int x1,int y0,int y1,const float *mask,
const float *mdct,
vorbis_info_floor1 *info){
int dy=y1-y0;
int adx=x1-x0;
int ady=abs(dy);
int base=dy/adx;
int sy=(dy<0?base-1:base+1);
int x=x0;
int y=y0;
int err=0;
int val=vorbis_dBquant(mask+x);
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;
#if 0
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look,
const float *logmdct, /* in */
const float *logmask){
ogg_int32_t i,j;
vorbis_info_floor1 *info=look->vi;
ogg_int32_t n=look->n;
ogg_int32_t posts=look->posts;
ogg_int32_t 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){
ogg_int32_t i;
ogg_int32_t 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);
}
#endif
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=
{
NULL, //&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 + -