nuclear@0: /******************************************************************** nuclear@0: * * nuclear@0: * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * nuclear@0: * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * nuclear@0: * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * nuclear@0: * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * nuclear@0: * * nuclear@0: * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * nuclear@0: * by the Xiph.Org Foundation http://www.xiph.org/ * nuclear@0: * * nuclear@0: ******************************************************************** nuclear@0: nuclear@0: function: residue backend 0, 1 and 2 implementation nuclear@0: last mod: $Id: res0.c 17556 2010-10-21 18:25:19Z tterribe $ nuclear@0: nuclear@0: ********************************************************************/ nuclear@0: nuclear@0: /* Slow, slow, slow, simpleminded and did I mention it was slow? The nuclear@0: encode/decode loops are coded for clarity and performance is not nuclear@0: yet even a nagging little idea lurking in the shadows. Oh and BTW, nuclear@0: it's slow. */ nuclear@0: nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "vorbis/codec.h" nuclear@0: #include "codec_internal.h" nuclear@0: #include "registry.h" nuclear@0: #include "codebook.h" nuclear@0: #include "misc.h" nuclear@0: #include "os.h" nuclear@0: nuclear@0: /*#define TRAIN_RES 1*/ nuclear@0: /*#define TRAIN_RESAUX 1*/ nuclear@0: nuclear@0: #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) nuclear@0: #include nuclear@0: #endif nuclear@0: nuclear@0: typedef struct { nuclear@0: vorbis_info_residue0 *info; nuclear@0: nuclear@0: int parts; nuclear@0: int stages; nuclear@0: codebook *fullbooks; nuclear@0: codebook *phrasebook; nuclear@0: codebook ***partbooks; nuclear@0: nuclear@0: int partvals; nuclear@0: int **decodemap; nuclear@0: nuclear@0: long postbits; nuclear@0: long phrasebits; nuclear@0: long frames; nuclear@0: nuclear@0: #if defined(TRAIN_RES) || defined(TRAIN_RESAUX) nuclear@0: int train_seq; nuclear@0: long *training_data[8][64]; nuclear@0: float training_max[8][64]; nuclear@0: float training_min[8][64]; nuclear@0: float tmin; nuclear@0: float tmax; nuclear@0: int submap; nuclear@0: #endif nuclear@0: nuclear@0: } vorbis_look_residue0; nuclear@0: nuclear@0: void res0_free_info(vorbis_info_residue *i){ nuclear@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; nuclear@0: if(info){ nuclear@0: memset(info,0,sizeof(*info)); nuclear@0: _ogg_free(info); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void res0_free_look(vorbis_look_residue *i){ nuclear@0: int j; nuclear@0: if(i){ nuclear@0: nuclear@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; nuclear@0: nuclear@0: #ifdef TRAIN_RES nuclear@0: { nuclear@0: int j,k,l; nuclear@0: for(j=0;jparts;j++){ nuclear@0: /*fprintf(stderr,"partition %d: ",j);*/ nuclear@0: for(k=0;k<8;k++) nuclear@0: if(look->training_data[k][j]){ nuclear@0: char buffer[80]; nuclear@0: FILE *of; nuclear@0: codebook *statebook=look->partbooks[j][k]; nuclear@0: nuclear@0: /* long and short into the same bucket by current convention */ nuclear@0: sprintf(buffer,"res_sub%d_part%d_pass%d.vqd",look->submap,j,k); nuclear@0: of=fopen(buffer,"a"); nuclear@0: nuclear@0: for(l=0;lentries;l++) nuclear@0: fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]); nuclear@0: nuclear@0: fclose(of); nuclear@0: nuclear@0: /*fprintf(stderr,"%d(%.2f|%.2f) ",k, nuclear@0: look->training_min[k][j],look->training_max[k][j]);*/ nuclear@0: nuclear@0: _ogg_free(look->training_data[k][j]); nuclear@0: look->training_data[k][j]=NULL; nuclear@0: } nuclear@0: /*fprintf(stderr,"\n");*/ nuclear@0: } nuclear@0: } nuclear@0: fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax); nuclear@0: nuclear@0: /*fprintf(stderr,"residue bit usage %f:%f (%f total)\n", nuclear@0: (float)look->phrasebits/look->frames, nuclear@0: (float)look->postbits/look->frames, nuclear@0: (float)(look->postbits+look->phrasebits)/look->frames);*/ nuclear@0: #endif nuclear@0: nuclear@0: nuclear@0: /*vorbis_info_residue0 *info=look->info; nuclear@0: nuclear@0: fprintf(stderr, nuclear@0: "%ld frames encoded in %ld phrasebits and %ld residue bits " nuclear@0: "(%g/frame) \n",look->frames,look->phrasebits, nuclear@0: look->resbitsflat, nuclear@0: (look->phrasebits+look->resbitsflat)/(float)look->frames); nuclear@0: nuclear@0: for(j=0;jparts;j++){ nuclear@0: long acc=0; nuclear@0: fprintf(stderr,"\t[%d] == ",j); nuclear@0: for(k=0;kstages;k++) nuclear@0: if((info->secondstages[j]>>k)&1){ nuclear@0: fprintf(stderr,"%ld,",look->resbits[j][k]); nuclear@0: acc+=look->resbits[j][k]; nuclear@0: } nuclear@0: nuclear@0: fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j], nuclear@0: acc?(float)acc/(look->resvals[j]*info->grouping):0); nuclear@0: } nuclear@0: fprintf(stderr,"\n");*/ nuclear@0: nuclear@0: for(j=0;jparts;j++) nuclear@0: if(look->partbooks[j])_ogg_free(look->partbooks[j]); nuclear@0: _ogg_free(look->partbooks); nuclear@0: for(j=0;jpartvals;j++) nuclear@0: _ogg_free(look->decodemap[j]); nuclear@0: _ogg_free(look->decodemap); nuclear@0: nuclear@0: memset(look,0,sizeof(*look)); nuclear@0: _ogg_free(look); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static int ilog(unsigned int v){ nuclear@0: int ret=0; nuclear@0: while(v){ nuclear@0: ret++; nuclear@0: v>>=1; nuclear@0: } nuclear@0: return(ret); nuclear@0: } nuclear@0: nuclear@0: static int icount(unsigned int v){ nuclear@0: int ret=0; nuclear@0: while(v){ nuclear@0: ret+=v&1; nuclear@0: v>>=1; nuclear@0: } nuclear@0: return(ret); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ nuclear@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; nuclear@0: int j,acc=0; nuclear@0: oggpack_write(opb,info->begin,24); nuclear@0: oggpack_write(opb,info->end,24); nuclear@0: nuclear@0: oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and nuclear@0: code with a partitioned book */ nuclear@0: oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ nuclear@0: oggpack_write(opb,info->groupbook,8); /* group huffman book */ nuclear@0: nuclear@0: /* secondstages is a bitmask; as encoding progresses pass by pass, a nuclear@0: bitmask of one indicates this partition class has bits to write nuclear@0: this pass */ nuclear@0: for(j=0;jpartitions;j++){ nuclear@0: if(ilog(info->secondstages[j])>3){ nuclear@0: /* yes, this is a minor hack due to not thinking ahead */ nuclear@0: oggpack_write(opb,info->secondstages[j],3); nuclear@0: oggpack_write(opb,1,1); nuclear@0: oggpack_write(opb,info->secondstages[j]>>3,5); nuclear@0: }else nuclear@0: oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ nuclear@0: acc+=icount(info->secondstages[j]); nuclear@0: } nuclear@0: for(j=0;jbooklist[j],8); nuclear@0: nuclear@0: } nuclear@0: nuclear@0: /* vorbis_info is for range checking */ nuclear@0: vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ nuclear@0: int j,acc=0; nuclear@0: vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info)); nuclear@0: codec_setup_info *ci=vi->codec_setup; nuclear@0: nuclear@0: info->begin=oggpack_read(opb,24); nuclear@0: info->end=oggpack_read(opb,24); nuclear@0: info->grouping=oggpack_read(opb,24)+1; nuclear@0: info->partitions=oggpack_read(opb,6)+1; nuclear@0: info->groupbook=oggpack_read(opb,8); nuclear@0: nuclear@0: /* check for premature EOP */ nuclear@0: if(info->groupbook<0)goto errout; nuclear@0: nuclear@0: for(j=0;jpartitions;j++){ nuclear@0: int cascade=oggpack_read(opb,3); nuclear@0: int cflag=oggpack_read(opb,1); nuclear@0: if(cflag<0) goto errout; nuclear@0: if(cflag){ nuclear@0: int c=oggpack_read(opb,5); nuclear@0: if(c<0) goto errout; nuclear@0: cascade|=(c<<3); nuclear@0: } nuclear@0: info->secondstages[j]=cascade; nuclear@0: nuclear@0: acc+=icount(cascade); nuclear@0: } nuclear@0: for(j=0;jbooklist[j]=book; nuclear@0: } nuclear@0: nuclear@0: if(info->groupbook>=ci->books)goto errout; nuclear@0: for(j=0;jbooklist[j]>=ci->books)goto errout; nuclear@0: if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; nuclear@0: } nuclear@0: nuclear@0: /* verify the phrasebook is not specifying an impossible or nuclear@0: inconsistent partitioning scheme. */ nuclear@0: /* modify the phrasebook ranging check from r16327; an early beta nuclear@0: encoder had a bug where it used an oversized phrasebook by nuclear@0: accident. These files should continue to be playable, but don't nuclear@0: allow an exploit */ nuclear@0: { nuclear@0: int entries = ci->book_param[info->groupbook]->entries; nuclear@0: int dim = ci->book_param[info->groupbook]->dim; nuclear@0: int partvals = 1; nuclear@0: if (dim<1) goto errout; nuclear@0: while(dim>0){ nuclear@0: partvals *= info->partitions; nuclear@0: if(partvals > entries) goto errout; nuclear@0: dim--; nuclear@0: } nuclear@0: info->partvals = partvals; nuclear@0: } nuclear@0: nuclear@0: return(info); nuclear@0: errout: nuclear@0: res0_free_info(info); nuclear@0: return(NULL); nuclear@0: } nuclear@0: nuclear@0: vorbis_look_residue *res0_look(vorbis_dsp_state *vd, nuclear@0: vorbis_info_residue *vr){ nuclear@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; nuclear@0: vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look)); nuclear@0: codec_setup_info *ci=vd->vi->codec_setup; nuclear@0: nuclear@0: int j,k,acc=0; nuclear@0: int dim; nuclear@0: int maxstage=0; nuclear@0: look->info=info; nuclear@0: nuclear@0: look->parts=info->partitions; nuclear@0: look->fullbooks=ci->fullbooks; nuclear@0: look->phrasebook=ci->fullbooks+info->groupbook; nuclear@0: dim=look->phrasebook->dim; nuclear@0: nuclear@0: look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks)); nuclear@0: nuclear@0: for(j=0;jparts;j++){ nuclear@0: int stages=ilog(info->secondstages[j]); nuclear@0: if(stages){ nuclear@0: if(stages>maxstage)maxstage=stages; nuclear@0: look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j])); nuclear@0: for(k=0;ksecondstages[j]&(1<partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; nuclear@0: #ifdef TRAIN_RES nuclear@0: look->training_data[k][j]=_ogg_calloc(look->partbooks[j][k]->entries, nuclear@0: sizeof(***look->training_data)); nuclear@0: #endif nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: look->partvals=1; nuclear@0: for(j=0;jpartvals*=look->parts; nuclear@0: nuclear@0: look->stages=maxstage; nuclear@0: look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap)); nuclear@0: for(j=0;jpartvals;j++){ nuclear@0: long val=j; nuclear@0: long mult=look->partvals/look->parts; nuclear@0: look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j])); nuclear@0: for(k=0;kparts; nuclear@0: look->decodemap[j][k]=deco; nuclear@0: } nuclear@0: } nuclear@0: #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) nuclear@0: { nuclear@0: static int train_seq=0; nuclear@0: look->train_seq=train_seq++; nuclear@0: } nuclear@0: #endif nuclear@0: return(look); nuclear@0: } nuclear@0: nuclear@0: /* break an abstraction and copy some code for performance purposes */ nuclear@0: static int local_book_besterror(codebook *book,int *a){ nuclear@0: int dim=book->dim; nuclear@0: int i,j,o; nuclear@0: int minval=book->minval; nuclear@0: int del=book->delta; nuclear@0: int qv=book->quantvals; nuclear@0: int ze=(qv>>1); nuclear@0: int index=0; nuclear@0: /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ nuclear@0: int p[8]={0,0,0,0,0,0,0,0}; nuclear@0: nuclear@0: if(del!=1){ nuclear@0: for(i=0,o=dim;i>1))/del; nuclear@0: int m = (v=qv?qv-1:m)); nuclear@0: p[o]=v*del+minval; nuclear@0: } nuclear@0: }else{ nuclear@0: for(i=0,o=dim;i=qv?qv-1:m)); nuclear@0: p[o]=v*del+minval; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(book->c->lengthlist[index]<=0){ nuclear@0: const static_codebook *c=book->c; nuclear@0: int best=-1; nuclear@0: /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ nuclear@0: int e[8]={0,0,0,0,0,0,0,0}; nuclear@0: int maxval = book->minval + book->delta*(book->quantvals-1); nuclear@0: for(i=0;ientries;i++){ nuclear@0: if(c->lengthlist[i]>0){ nuclear@0: int this=0; nuclear@0: for(j=0;j=maxval) nuclear@0: e[j++]=0; nuclear@0: if(e[j]>=0) nuclear@0: e[j]+=book->delta; nuclear@0: e[j]= -e[j]; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(index>-1){ nuclear@0: for(i=0;idim; nuclear@0: int step=n/dim; nuclear@0: nuclear@0: for(i=0;i=0) nuclear@0: acc[entry]++; nuclear@0: #endif nuclear@0: nuclear@0: bits+=vorbis_book_encode(book,entry,opb); nuclear@0: nuclear@0: } nuclear@0: nuclear@0: return(bits); nuclear@0: } nuclear@0: nuclear@0: static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, nuclear@0: int **in,int ch){ nuclear@0: long i,j,k; nuclear@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; nuclear@0: vorbis_info_residue0 *info=look->info; nuclear@0: nuclear@0: /* move all this setup out later */ nuclear@0: int samples_per_partition=info->grouping; nuclear@0: int possible_partitions=info->partitions; nuclear@0: int n=info->end-info->begin; nuclear@0: nuclear@0: int partvals=n/samples_per_partition; nuclear@0: long **partword=_vorbis_block_alloc(vb,ch*sizeof(*partword)); nuclear@0: float scale=100./samples_per_partition; nuclear@0: nuclear@0: /* we find the partition type for each partition of each nuclear@0: channel. We'll go back and do the interleaved encoding in a nuclear@0: bit. For now, clarity */ nuclear@0: nuclear@0: for(i=0;ibegin; nuclear@0: for(j=0;jmax)max=abs(in[j][offset+k]); nuclear@0: ent+=abs(in[j][offset+k]); nuclear@0: } nuclear@0: ent*=scale; nuclear@0: nuclear@0: for(k=0;kclassmetric1[k] && nuclear@0: (info->classmetric2[k]<0 || entclassmetric2[k])) nuclear@0: break; nuclear@0: nuclear@0: partword[j][i]=k; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: #ifdef TRAIN_RESAUX nuclear@0: { nuclear@0: FILE *of; nuclear@0: char buffer[80]; nuclear@0: nuclear@0: for(i=0;itrain_seq); nuclear@0: of=fopen(buffer,"a"); nuclear@0: for(j=0;jframes++; nuclear@0: nuclear@0: return(partword); nuclear@0: } nuclear@0: nuclear@0: /* designed for stereo or other modes where the partition size is an nuclear@0: integer multiple of the number of channels encoded in the current nuclear@0: submap */ nuclear@0: static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,int **in, nuclear@0: int ch){ nuclear@0: long i,j,k,l; nuclear@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; nuclear@0: vorbis_info_residue0 *info=look->info; nuclear@0: nuclear@0: /* move all this setup out later */ nuclear@0: int samples_per_partition=info->grouping; nuclear@0: int possible_partitions=info->partitions; nuclear@0: int n=info->end-info->begin; nuclear@0: nuclear@0: int partvals=n/samples_per_partition; nuclear@0: long **partword=_vorbis_block_alloc(vb,sizeof(*partword)); nuclear@0: nuclear@0: #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) nuclear@0: FILE *of; nuclear@0: char buffer[80]; nuclear@0: #endif nuclear@0: nuclear@0: partword[0]=_vorbis_block_alloc(vb,partvals*sizeof(*partword[0])); nuclear@0: memset(partword[0],0,partvals*sizeof(*partword[0])); nuclear@0: nuclear@0: for(i=0,l=info->begin/ch;imagmax)magmax=abs(in[0][l]); nuclear@0: for(k=1;kangmax)angmax=abs(in[k][l]); nuclear@0: l++; nuclear@0: } nuclear@0: nuclear@0: for(j=0;jclassmetric1[j] && nuclear@0: angmax<=info->classmetric2[j]) nuclear@0: break; nuclear@0: nuclear@0: partword[0][i]=j; nuclear@0: nuclear@0: } nuclear@0: nuclear@0: #ifdef TRAIN_RESAUX nuclear@0: sprintf(buffer,"resaux_%d.vqd",look->train_seq); nuclear@0: of=fopen(buffer,"a"); nuclear@0: for(i=0;iframes++; nuclear@0: nuclear@0: return(partword); nuclear@0: } nuclear@0: nuclear@0: static int _01forward(oggpack_buffer *opb, nuclear@0: vorbis_block *vb,vorbis_look_residue *vl, nuclear@0: int **in,int ch, nuclear@0: long **partword, nuclear@0: int (*encode)(oggpack_buffer *,int *,int, nuclear@0: codebook *,long *), nuclear@0: int submap){ nuclear@0: long i,j,k,s; nuclear@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; nuclear@0: vorbis_info_residue0 *info=look->info; nuclear@0: nuclear@0: #ifdef TRAIN_RES nuclear@0: look->submap=submap; nuclear@0: #endif nuclear@0: nuclear@0: /* move all this setup out later */ nuclear@0: int samples_per_partition=info->grouping; nuclear@0: int possible_partitions=info->partitions; nuclear@0: int partitions_per_word=look->phrasebook->dim; nuclear@0: int n=info->end-info->begin; nuclear@0: nuclear@0: int partvals=n/samples_per_partition; nuclear@0: long resbits[128]; nuclear@0: long resvals[128]; nuclear@0: nuclear@0: #ifdef TRAIN_RES nuclear@0: for(i=0;ibegin;jend;j++){ nuclear@0: if(in[i][j]>look->tmax)look->tmax=in[i][j]; nuclear@0: if(in[i][j]tmin)look->tmin=in[i][j]; nuclear@0: } nuclear@0: #endif nuclear@0: nuclear@0: memset(resbits,0,sizeof(resbits)); nuclear@0: memset(resvals,0,sizeof(resvals)); nuclear@0: nuclear@0: /* we code the partition words for each channel, then the residual nuclear@0: words for a partition per channel until we've written all the nuclear@0: residual words for that partition word. Then write the next nuclear@0: partition channel words... */ nuclear@0: nuclear@0: for(s=0;sstages;s++){ nuclear@0: nuclear@0: for(i=0;iphrasebook->entries) nuclear@0: look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); nuclear@0: #if 0 /*def TRAIN_RES*/ nuclear@0: else nuclear@0: fprintf(stderr,"!"); nuclear@0: #endif nuclear@0: nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: /* now we encode interleaved residual values for the partitions */ nuclear@0: for(k=0;kbegin; nuclear@0: nuclear@0: for(j=0;jsecondstages[partword[j][i]]&(1<partbooks[partword[j][i]][s]; nuclear@0: if(statebook){ nuclear@0: int ret; nuclear@0: long *accumulator=NULL; nuclear@0: nuclear@0: #ifdef TRAIN_RES nuclear@0: accumulator=look->training_data[s][partword[j][i]]; nuclear@0: { nuclear@0: int l; nuclear@0: int *samples=in[j]+offset; nuclear@0: for(l=0;ltraining_min[s][partword[j][i]]) nuclear@0: look->training_min[s][partword[j][i]]=samples[l]; nuclear@0: if(samples[l]>look->training_max[s][partword[j][i]]) nuclear@0: look->training_max[s][partword[j][i]]=samples[l]; nuclear@0: } nuclear@0: } nuclear@0: #endif nuclear@0: nuclear@0: ret=encode(opb,in[j]+offset,samples_per_partition, nuclear@0: statebook,accumulator); nuclear@0: nuclear@0: look->postbits+=ret; nuclear@0: resbits[partword[j][i]]+=ret; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: /*{ nuclear@0: long total=0; nuclear@0: long totalbits=0; nuclear@0: fprintf(stderr,"%d :: ",vb->mode); nuclear@0: for(k=0;kinfo; nuclear@0: nuclear@0: /* move all this setup out later */ nuclear@0: int samples_per_partition=info->grouping; nuclear@0: int partitions_per_word=look->phrasebook->dim; nuclear@0: int max=vb->pcmend>>1; nuclear@0: int end=(info->endend:max); nuclear@0: int n=end-info->begin; nuclear@0: nuclear@0: if(n>0){ nuclear@0: int partvals=n/samples_per_partition; nuclear@0: int partwords=(partvals+partitions_per_word-1)/partitions_per_word; nuclear@0: int ***partword=alloca(ch*sizeof(*partword)); nuclear@0: nuclear@0: for(j=0;jstages;s++){ nuclear@0: nuclear@0: /* each loop decodes on partition codeword containing nuclear@0: partitions_per_word partitions */ nuclear@0: for(i=0,l=0;iphrasebook,&vb->opb); nuclear@0: nuclear@0: if(temp==-1 || temp>=info->partvals)goto eopbreak; nuclear@0: partword[j][l]=look->decodemap[temp]; nuclear@0: if(partword[j][l]==NULL)goto errout; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: /* now we decode residual values for the partitions */ nuclear@0: for(k=0;kbegin+i*samples_per_partition; nuclear@0: if(info->secondstages[partword[j][l][k]]&(1<partbooks[partword[j][l][k]][s]; nuclear@0: if(stagebook){ nuclear@0: if(decodepart(stagebook,in[j]+offset,&vb->opb, nuclear@0: samples_per_partition)==-1)goto eopbreak; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: errout: nuclear@0: eopbreak: nuclear@0: return(0); nuclear@0: } nuclear@0: nuclear@0: int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, nuclear@0: float **in,int *nonzero,int ch){ nuclear@0: int i,used=0; nuclear@0: for(i=0;ipcmend/2,used=0; nuclear@0: nuclear@0: /* don't duplicate the code; use a working vector hack for now and nuclear@0: reshape ourselves into a single channel res1 */ nuclear@0: /* ugly; reallocs for each coupling pass :-( */ nuclear@0: int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work)); nuclear@0: for(i=0;iinfo; nuclear@0: nuclear@0: /* move all this setup out later */ nuclear@0: int samples_per_partition=info->grouping; nuclear@0: int partitions_per_word=look->phrasebook->dim; nuclear@0: int max=(vb->pcmend*ch)>>1; nuclear@0: int end=(info->endend:max); nuclear@0: int n=end-info->begin; nuclear@0: nuclear@0: if(n>0){ nuclear@0: int partvals=n/samples_per_partition; nuclear@0: int partwords=(partvals+partitions_per_word-1)/partitions_per_word; nuclear@0: int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword)); nuclear@0: nuclear@0: for(i=0;istages;s++){ nuclear@0: for(i=0,l=0;iphrasebook,&vb->opb); nuclear@0: if(temp==-1 || temp>=info->partvals)goto eopbreak; nuclear@0: partword[l]=look->decodemap[temp]; nuclear@0: if(partword[l]==NULL)goto errout; nuclear@0: } nuclear@0: nuclear@0: /* now we decode residual values for the partitions */ nuclear@0: for(k=0;ksecondstages[partword[l][k]]&(1<partbooks[partword[l][k]][s]; nuclear@0: nuclear@0: if(stagebook){ nuclear@0: if(vorbis_book_decodevv_add(stagebook,in, nuclear@0: i*samples_per_partition+info->begin,ch, nuclear@0: &vb->opb,samples_per_partition)==-1) nuclear@0: goto eopbreak; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: errout: nuclear@0: eopbreak: nuclear@0: return(0); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: const vorbis_func_residue residue0_exportbundle={ nuclear@0: NULL, nuclear@0: &res0_unpack, nuclear@0: &res0_look, nuclear@0: &res0_free_info, nuclear@0: &res0_free_look, nuclear@0: NULL, nuclear@0: NULL, nuclear@0: &res0_inverse nuclear@0: }; nuclear@0: nuclear@0: const vorbis_func_residue residue1_exportbundle={ nuclear@0: &res0_pack, nuclear@0: &res0_unpack, nuclear@0: &res0_look, nuclear@0: &res0_free_info, nuclear@0: &res0_free_look, nuclear@0: &res1_class, nuclear@0: &res1_forward, nuclear@0: &res1_inverse nuclear@0: }; nuclear@0: nuclear@0: const vorbis_func_residue residue2_exportbundle={ nuclear@0: &res0_pack, nuclear@0: &res0_unpack, nuclear@0: &res0_look, nuclear@0: &res0_free_info, nuclear@0: &res0_free_look, nuclear@0: &res2_class, nuclear@0: &res2_forward, nuclear@0: &res2_inverse nuclear@0: };