/******************************************************************** * * * 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-2010 * * by the Xiph.Org Foundation https://xiph.org/ * * * ********************************************************************
function: residue backend 0, 1 and 2 implementation
/* Slow, slow, slow, simpleminded and did I mention it was slow? The encode/decode loops are coded for clarity and performance is not yet even a nagging little idea lurking in the shadows. Oh and BTW,
it's slow. */
oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and
code with a partitioned book */
oggpack_write(opb,info->partitions-1,6); /* possible partition choices */
oggpack_write(opb,info->groupbook,8); /* group huffman book */
/* secondstages is a bitmask; as encoding progresses pass by pass, a bitmask of one indicates this partition class has bits to write
this pass */ for(j=0;j<info->partitions;j++){ if(ov_ilog(info->secondstages[j])>3){ /* yes, this is a minor hack due to not thinking ahead */
oggpack_write(opb,info->secondstages[j],3);
oggpack_write(opb,1,1);
oggpack_write(opb,info->secondstages[j]>>3,5);
}else
oggpack_write(opb,info->secondstages[j],4); /* trailing zero */
acc+=icount(info->secondstages[j]);
} for(j=0;j<acc;j++)
oggpack_write(opb,info->booklist[j],8);
}
/* vorbis_info is for range checking */
vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int j,acc=0;
vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info));
codec_setup_info *ci=vi->codec_setup;
/* verify the phrasebook is not specifying an impossible or
inconsistent partitioning scheme. */ /* modify the phrasebook ranging check from r16327; an early beta encoder had a bug where it used an oversized phrasebook by accident. These files should continue to be playable, but don't
allow an exploit */
{ int entries = ci->book_param[info->groupbook]->entries; int dim = ci->book_param[info->groupbook]->dim; int partvals = 1; if (dim<1) goto errout; while(dim>0){
partvals *= info->partitions; if(partvals > entries) goto errout;
dim--;
}
info->partvals = partvals;
}
look->stages=maxstage;
look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap)); for(j=0;j<look->partvals;j++){ long val=j; long mult=look->partvals/look->parts;
look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j])); for(k=0;k<dim;k++){ long deco=val/mult;
val-=deco*mult;
mult/=look->parts;
look->decodemap[j][k]=deco;
}
} #ifdefined(TRAIN_RES) || defined (TRAIN_RESAUX)
{ staticint train_seq=0;
look->train_seq=train_seq++;
} #endif return(look);
}
/* break an abstraction and copy some code for performance purposes */ staticint local_book_besterror(codebook *book,int *a){ int dim=book->dim; int i,j,o; int minval=book->minval; int del=book->delta; int qv=book->quantvals; int ze=(qv>>1); int index=0; /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ int p[8]={0,0,0,0,0,0,0,0};
if(del!=1){ for(i=0,o=dim;i<dim;i++){ int v = (a[--o]-minval+(del>>1))/del; int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
p[o]=v*del+minval;
}
}else{ for(i=0,o=dim;i<dim;i++){ int v = a[--o]-minval; int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
p[o]=v*del+minval;
}
}
if(book->c->lengthlist[index]<=0){ const static_codebook *c=book->c; int best=-1; /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ int e[8]={0,0,0,0,0,0,0,0}; int maxval = book->minval + book->delta*(book->quantvals-1); for(i=0;i<book->entries;i++){ if(c->lengthlist[i]>0){ intthis=0; for(j=0;j<dim;j++){ int val=(e[j]-a[j]); this+=val*val;
} if(best==-1 || this<best){
memcpy(p,e,sizeof(p));
best=this;
index=i;
}
} /* assumes the value patterning created by the tools in vq/ */
j=0; while(e[j]>=maxval)
e[j++]=0; if(e[j]>=0)
e[j]+=book->delta;
e[j]= -e[j];
}
}
if(index>-1){ for(i=0;i<dim;i++)
*a++ -= p[i];
}
return(index);
}
#ifdef TRAIN_RES staticint _encodepart(oggpack_buffer *opb,int *vec, int n,
codebook *book,long *acc){ #else staticint _encodepart(oggpack_buffer *opb,int *vec, int n,
codebook *book){ #endif int i,bits=0; int dim=book->dim; int step=n/dim;
for(i=0;i<step;i++){ int entry=local_book_besterror(book,vec+i*dim);
for(i=0;i<partvals;i++){ int offset=i*samples_per_partition+info->begin; for(j=0;j<ch;j++){ int max=0; int ent=0; for(k=0;k<samples_per_partition;k++){ if(abs(in[j][offset+k])>max)max=abs(in[j][offset+k]);
ent+=abs(in[j][offset+k]);
}
ent*=scale;
/* designed for stereo or other modes where the partition size is an integer multiple of the number of channels encoded in the current
submap */ staticlong **_2class(vorbis_block *vb,vorbis_look_residue *vl,int **in, int ch){ long i,j,k,l;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int n=info->end-info->begin;
int partvals=n/samples_per_partition; long **partword=_vorbis_block_alloc(vb,sizeof(*partword));
#ifdefined(TRAIN_RES) || defined (TRAIN_RESAUX)
FILE *of; char buffer[80]; #endif
staticint _01forward(oggpack_buffer *opb,
vorbis_look_residue *vl, int **in,int ch, long **partword, #ifdef TRAIN_RES int (*encode)(oggpack_buffer *,int *,int,
codebook *,long *), int submap #else int (*encode)(oggpack_buffer *,int *,int,
codebook *) #endif
){ long i,j,k,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
#ifdef TRAIN_RES
look->submap=submap; #endif
/* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int partitions_per_word=look->phrasebook->dim; int n=info->end-info->begin;
int partvals=n/samples_per_partition; long resbits[128]; long resvals[128];
/* we code the partition words for each channel, then the residual words for a partition per channel until we've written all the residual words for that partition word. Then write the next
partition channel words... */
for(s=0;s<look->stages;s++){
for(i=0;i<partvals;){
/* first we encode a partition codeword for each channel */ if(s==0){ for(j=0;j<ch;j++){ long val=partword[j][i]; for(k=1;k<partitions_per_word;k++){
val*=possible_partitions; if(i+k<partvals)
val+=partword[j][i+k];
}
/* now we encode interleaved residual values for the partitions */ for(k=0;k<partitions_per_word && i<partvals;k++,i++){ long offset=i*samples_per_partition+info->begin;
for(j=0;j<ch;j++){ if(s==0)resvals[partword[j][i]]+=samples_per_partition; if(info->secondstages[partword[j][i]]&(1<<s)){
codebook *statebook=look->partbooks[partword[j][i]][s]; if(statebook){ int ret; #ifdef TRAIN_RES long *accumulator=NULL;
accumulator=look->training_data[s][partword[j][i]];
{ int l; int *samples=in[j]+offset; for(l=0;l<samples_per_partition;l++){ if(samples[l]<look->training_min[s][partword[j][i]])
look->training_min[s][partword[j][i]]=samples[l]; if(samples[l]>look->training_max[s][partword[j][i]])
look->training_max[s][partword[j][i]]=samples[l];
}
}
ret=encode(opb,in[j]+offset,samples_per_partition,
statebook,accumulator); #else
ret=encode(opb,in[j]+offset,samples_per_partition,
statebook); #endif
/* a truncated packet here just means 'stop working'; it's not an error */ staticint _01inverse(vorbis_block *vb,vorbis_look_residue *vl, float **in,int ch, long (*decodepart)(codebook *, float *,
oggpack_buffer *,int)){
long i,j,k,l,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int max=vb->pcmend>>1; int end=(info->end<max?info->end:max); int n=end-info->begin;
if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int ***partword=alloca(ch*sizeof(*partword));
/* each loop decodes on partition codeword containing
partitions_per_word partitions */ for(i=0,l=0;i<partvals;l++){ if(s==0){ /* fetch the partition word for each channel */ for(j=0;j<ch;j++){ int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
/* now we decode residual values for the partitions */ for(k=0;k<partitions_per_word && i<partvals;k++,i++) for(j=0;j<ch;j++){ long offset=info->begin+i*samples_per_partition; if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s]; if(stagebook){ if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition)==-1)goto eopbreak;
}
}
}
}
}
}
errout:
eopbreak: return(0);
}
int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, float **in,int *nonzero,int ch){ int i,used=0; for(i=0;i<ch;i++) if(nonzero[i])
in[used++]=in[i]; if(used) return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); else return(0);
}
int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl, int **in,int *nonzero,int ch, long **partword, int submap){ int i,used=0;
(void)vb; for(i=0;i<ch;i++) if(nonzero[i])
in[used++]=in[i];
long **res1_class(vorbis_block *vb,vorbis_look_residue *vl, int **in,int *nonzero,int ch){ int i,used=0; for(i=0;i<ch;i++) if(nonzero[i])
in[used++]=in[i]; if(used) return(_01class(vb,vl,in,used)); else return(0);
}
int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, float **in,int *nonzero,int ch){ int i,used=0; for(i=0;i<ch;i++) if(nonzero[i])
in[used++]=in[i]; if(used) return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); else return(0);
}
long **res2_class(vorbis_block *vb,vorbis_look_residue *vl, int **in,int *nonzero,int ch){ int i,used=0; for(i=0;i<ch;i++) if(nonzero[i])used++; if(used) return(_2class(vb,vl,in,ch)); else return(0);
}
/* res2 is slightly more different; all the channels are interleaved
into a single vector and encoded. */
int res2_forward(oggpack_buffer *opb,
vorbis_block *vb,vorbis_look_residue *vl, int **in,int *nonzero,int ch, long **partword,int submap){ long i,j,k,n=vb->pcmend/2,used=0;
/* don't duplicate the code; use a working vector hack for now and
reshape ourselves into a single channel res1 */ /* ugly; reallocs for each coupling pass :-( */ int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work)); for(i=0;i<ch;i++){ int *pcm=in[i]; if(nonzero[i])used++; for(j=0,k=i;j<n;j++,k+=ch)
work[k]=pcm[j];
}
/* duplicate code here as speed is somewhat more important */ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, float **in,int *nonzero,int ch){ long i,k,l,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int max=(vb->pcmend*ch)>>1; int end=(info->end<max?info->end:max); int n=end-info->begin;
if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword));
for(i=0;i<ch;i++)if(nonzero[i])break; if(i==ch)return(0); /* no nonzero vectors */
if(s==0){ /* fetch the partition word */ int temp=vorbis_book_decode(look->phrasebook,&vb->opb); if(temp==-1 || temp>=info->partvals)goto eopbreak;
partword[l]=look->decodemap[temp]; if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */ for(k=0;k<partitions_per_word && i<partvals;k++,i++) if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
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.