/******************************************************************** * * * 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-2015 * * by the Xiph.Org Foundation https://xiph.org/ * * * ********************************************************************
staticvoid floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){
vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; int j,k; int count=0; int rangebits; int maxposit=info->postlist[1]; int maxclass=-1;
/* save out partitions */
oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */ for(j=0;j<info->partitions;j++){
oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */ if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j];
}
/* save out partition classes */ for(j=0;j<maxclass+1;j++){
oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */
oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); for(k=0;k<(1<<info->class_subs[j]);k++)
oggpack_write(opb,info->class_subbook[j][k]+1,8);
}
/* save out the post list */
oggpack_write(opb,info->mult-1,2); /* only 1,2,3,4 legal now */ /* maxposit cannot legally be less than 1; this is encode-side, we
can assume our setup is OK */
oggpack_write(opb,ov_ilog(maxposit-1),4);
rangebits=ov_ilog(maxposit-1);
/* don't allow repeated values in post list as they'd result in
zero-length segments */
{ int *sortpointer[VIF_POSIT+2]; for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j;
qsort(sortpointer,count+2,sizeof(*sortpointer),icomp);
int *sortpointer[VIF_POSIT+2];
vorbis_info_floor1 *info=(vorbis_info_floor1 *)in;
vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look)); int i,j,n=0;
(void)vd;
look->vi=info;
look->n=info->postlist[1];
/* we drop each position value in-between already decoded values, and use linear interpolation to predict each new value past the edges. The positions are read in the order of the position list... we precompute the bounding positions in the lookup. Of course, the neighbors can change (if a position is declined), but
this is an initial mapping */
/* also store a sorted position index */ for(i=0;i<n;i++)sortpointer[i]=info->postlist+i;
qsort(sortpointer,n,sizeof(*sortpointer),icomp);
/* points from sort order back to range number */ for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist; /* points from range order to sorted position */ for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i; /* we actually need the post values too */ for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]];
/* discover our neighbors for decode where we don't use fit flags
(that would push the neighbors outward) */ for(i=0;i<n-2;i++){ int lo=0; int hi=1; int lx=0; int hx=look->n; int currentx=info->postlist[i+2]; for(j=0;j<i+2;j++){ int x=info->postlist[j]; if(x>lx && x<currentx){
lo=j;
lx=x;
} if(x<hx && x>currentx){
hi=j;
hx=x;
}
}
look->loneighbor[i]=lo;
look->hineighbor[i]=hi;
}
return(look);
}
staticint render_point(int x0,int x1,int y0,int y1,int x){
y0&=0x7fff; /* mask off flag */
y1&=0x7fff;
{ int dy=y1-y0; int adx=x1-x0; int ady=abs(dy); int err=ady*(x-x0);
int off=err/adx; if(dy<0)return(y0-off); return(y0+off);
}
}
staticvoid render_line(int n, int x0,int x1,int y0,int y1,float *d){ 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;
staticvoid render_line0(int n, int x0,int x1,int y0,int y1,int *d){ 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;
/* the floor has already been filtered to only include relevant sections */ staticint accumulate_fit(constfloat *flr,constfloat *mdct, int x0, int x1,lsfit_acc *a, int n,vorbis_info_floor1 *info){ long i;
int xa=0,ya=0,x2a=0,y2a=0,xya=0,na=0, xb=0,yb=0,x2b=0,y2b=0,xyb=0,nb=0;
/* limit to our range! */ if(*y0>1023)*y0=1023; if(*y1>1023)*y1=1023; if(*y0<0)*y0=0; if(*y1<0)*y1=0;
return0;
}else{
*y0=0;
*y1=0; return1;
}
}
}
staticint inspect_error(int x0,int x1,int y0,int y1,constfloat *mask, constfloat *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;
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look, constfloat *logmdct, /* in */ constfloat *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,info);
/* 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; int ret0=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1,info); int ret1=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1,info);
/* 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);
/* overly simpleminded--- look again post 1.2 */ for(i=0;i<posts;i++){
output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&e='color: green'>0x7fff)+32768)>>16; if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000;
}
}
return(output);
}
int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
vorbis_look_floor1 *look, int *post,int *ilogmask){
long i,j;
vorbis_info_floor1 *info=look->vi; 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;
/* 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. */
/* we have everything we need. pack it out */ /* mark nontrivial floor */
oggpack_write(opb,1,1);
/* beginning/end post */
look->frames++;
look->postbits+=ov_ilog(look->quant_q-1)*2;
oggpack_write(opb,out[0],ov_ilog(look->quant_q-1));
oggpack_write(opb,out[1],ov_ilog(look->quant_q-1));
/* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ intclass=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]={0,0,0,0,0,0,0,0}; /* gcc's static analysis issues a warning without
initialization */ 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,opb);
/* 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],opb); /*else
fprintf(stderr,"+!");*/
{ /* 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; int n=ci->blocksizes[vb->W]/2;
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(n,lx,hx,ly,hy,ilogmask);
lx=hx;
ly=hy;
}
} for(j=hx;j<vb->pcmend/2;j++)ilogmask[j]=ly; /* be certain */ return(1);
}
}else{
oggpack_write(opb,0,1);
memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask)); return(0);
}
}
/* 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));
/* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ intclass=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);
/* 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;
}
}
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; /* guard lookup against out-of-range values */
ly=(ly<0?0:ly>255?255:ly);
for(j=1;j<look->posts;j++){ int current=look->forward_index[j]; int hy=fit_value[current]&0x7fff; if(hy==fit_value[current]){
hx=info->postlist[current];
hy*=info->mult; /* guard lookup against out-of-range values */
hy=(hy<0?0:hy>255?255:hy);
render_line(n,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);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.