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, anduselinearinterpolationtopredicteachnewvaluepastthe edges.Thepositionsarereadintheorderoftheposition list...weprecomputetheboundingpositionsinthelookup.Of course,theneighborscanchange(ifapositionisdeclined),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,butsimpleandcloseenoughtothebest
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 backoutto'unused'whenencodingthemsolongascurve
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,butthereal,uniquerangecanalwaysbemappedto only[0-maxrange).Sowewanttowrapthedeviationinto thislimitedrange,butdoitinthewaythatleastscrews
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 issuesawarningwithout
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.