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