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