michael@0: /******************************************************************** michael@0: * * michael@0: * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * michael@0: * * michael@0: * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * michael@0: * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * michael@0: * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * michael@0: * * michael@0: * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * michael@0: * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * michael@0: * * michael@0: ******************************************************************** michael@0: michael@0: function: residue backend 0, 1 and 2 implementation michael@0: michael@0: ********************************************************************/ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include "ivorbiscodec.h" michael@0: #include "codec_internal.h" michael@0: #include "registry.h" michael@0: #include "codebook.h" michael@0: #include "misc.h" michael@0: #include "os.h" michael@0: #include "block.h" michael@0: michael@0: typedef struct { michael@0: vorbis_info_residue0 *info; michael@0: int map; michael@0: michael@0: int parts; michael@0: int stages; michael@0: codebook *fullbooks; michael@0: codebook *phrasebook; michael@0: codebook ***partbooks; michael@0: michael@0: int partvals; michael@0: int **decodemap; michael@0: michael@0: } vorbis_look_residue0; michael@0: michael@0: void res0_free_info(vorbis_info_residue *i){ michael@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; michael@0: if(info){ michael@0: memset(info,0,sizeof(*info)); michael@0: _ogg_free(info); michael@0: } michael@0: } michael@0: michael@0: void res0_free_look(vorbis_look_residue *i){ michael@0: int j; michael@0: if(i){ michael@0: michael@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; michael@0: michael@0: for(j=0;jparts;j++) michael@0: if(look->partbooks[j])_ogg_free(look->partbooks[j]); michael@0: _ogg_free(look->partbooks); michael@0: for(j=0;jpartvals;j++) michael@0: _ogg_free(look->decodemap[j]); michael@0: _ogg_free(look->decodemap); michael@0: michael@0: memset(look,0,sizeof(*look)); michael@0: _ogg_free(look); michael@0: } michael@0: } michael@0: michael@0: static int ilog(unsigned int v){ michael@0: int ret=0; michael@0: while(v){ michael@0: ret++; michael@0: v>>=1; michael@0: } michael@0: return(ret); michael@0: } michael@0: michael@0: static int icount(unsigned int v){ michael@0: int ret=0; michael@0: while(v){ michael@0: ret+=v&1; michael@0: v>>=1; michael@0: } michael@0: return(ret); michael@0: } michael@0: michael@0: /* vorbis_info is for range checking */ michael@0: vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ michael@0: int j,acc=0; michael@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); michael@0: codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; michael@0: michael@0: info->begin=oggpack_read(opb,24); michael@0: info->end=oggpack_read(opb,24); michael@0: info->grouping=oggpack_read(opb,24)+1; michael@0: info->partitions=oggpack_read(opb,6)+1; michael@0: info->groupbook=oggpack_read(opb,8); michael@0: michael@0: /* check for premature EOP */ michael@0: if(info->groupbook<0)goto errout; michael@0: michael@0: for(j=0;jpartitions;j++){ michael@0: int cascade=oggpack_read(opb,3); michael@0: int cflag=oggpack_read(opb,1); michael@0: if(cflag<0) goto errout; michael@0: if(cflag){ michael@0: int c=oggpack_read(opb,5); michael@0: if(c<0) goto errout; michael@0: cascade|=(c<<3); michael@0: } michael@0: info->secondstages[j]=cascade; michael@0: michael@0: acc+=icount(cascade); michael@0: } michael@0: for(j=0;jbooklist[j]=book; michael@0: } michael@0: michael@0: if(info->groupbook>=ci->books)goto errout; michael@0: for(j=0;jbooklist[j]>=ci->books)goto errout; michael@0: if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; michael@0: } michael@0: michael@0: /* verify the phrasebook is not specifying an impossible or michael@0: inconsistent partitioning scheme. */ michael@0: /* modify the phrasebook ranging check from r16327; an early beta michael@0: encoder had a bug where it used an oversized phrasebook by michael@0: accident. These files should continue to be playable, but don't michael@0: allow an exploit */ michael@0: { michael@0: int entries = ci->book_param[info->groupbook]->entries; michael@0: int dim = ci->book_param[info->groupbook]->dim; michael@0: int partvals = 1; michael@0: if (dim<1) goto errout; michael@0: while(dim>0){ michael@0: partvals *= info->partitions; michael@0: if(partvals > entries) goto errout; michael@0: dim--; michael@0: } michael@0: info->partvals = partvals; michael@0: } michael@0: michael@0: return(info); michael@0: errout: michael@0: res0_free_info(info); michael@0: return(NULL); michael@0: } michael@0: michael@0: vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, michael@0: vorbis_info_residue *vr){ michael@0: vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; michael@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); michael@0: codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; michael@0: michael@0: int j,k,acc=0; michael@0: int dim; michael@0: int maxstage=0; michael@0: look->info=info; michael@0: look->map=vm->mapping; michael@0: michael@0: look->parts=info->partitions; michael@0: look->fullbooks=ci->fullbooks; michael@0: look->phrasebook=ci->fullbooks+info->groupbook; michael@0: dim=look->phrasebook->dim; michael@0: michael@0: look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); michael@0: michael@0: for(j=0;jparts;j++){ michael@0: int stages=ilog(info->secondstages[j]); michael@0: if(stages){ michael@0: if(stages>maxstage)maxstage=stages; michael@0: look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); michael@0: for(k=0;ksecondstages[j]&(1<partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; michael@0: #ifdef TRAIN_RES michael@0: look->training_data[k][j]=calloc(look->partbooks[j][k]->entries, michael@0: sizeof(***look->training_data)); michael@0: #endif michael@0: } michael@0: } michael@0: } michael@0: michael@0: look->partvals=look->parts; michael@0: for(j=1;jpartvals*=look->parts; michael@0: look->stages=maxstage; michael@0: look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); michael@0: for(j=0;jpartvals;j++){ michael@0: long val=j; michael@0: long mult=look->partvals/look->parts; michael@0: look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); michael@0: for(k=0;kparts; michael@0: look->decodemap[j][k]=deco; michael@0: } michael@0: } michael@0: michael@0: return(look); michael@0: } michael@0: michael@0: michael@0: /* a truncated packet here just means 'stop working'; it's not an error */ michael@0: static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, michael@0: ogg_int32_t **in,int ch, michael@0: long (*decodepart)(codebook *, ogg_int32_t *, michael@0: oggpack_buffer *,int,int)){ michael@0: michael@0: long i,j,k,l,s; michael@0: vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; michael@0: vorbis_info_residue0 *info=look->info; michael@0: michael@0: /* move all this setup out later */ michael@0: int samples_per_partition=info->grouping; michael@0: int partitions_per_word=look->phrasebook->dim; michael@0: int max=vb->pcmend>>1; michael@0: int end=(info->endend:max); michael@0: int n=end-info->begin; michael@0: michael@0: if(n>0){ michael@0: int partvals=n/samples_per_partition; michael@0: int partwords=(partvals+partitions_per_word-1)/partitions_per_word; michael@0: int ***partword=(int ***)alloca(ch*sizeof(*partword)); michael@0: michael@0: for(j=0;jstages;s++){ michael@0: michael@0: /* each loop decodes on partition codeword containing michael@0: partitions_pre_word partitions */ michael@0: for(i=0,l=0;iphrasebook,&vb->opb); michael@0: if(temp==-1 || temp>=info->partvals)goto eopbreak; michael@0: partword[j][l]=look->decodemap[temp]; michael@0: if(partword[j][l]==NULL)goto errout; michael@0: } michael@0: } michael@0: michael@0: /* now we decode residual values for the partitions */ michael@0: for(k=0;kbegin+i*samples_per_partition; michael@0: if(info->secondstages[partword[j][l][k]]&(1<partbooks[partword[j][l][k]][s]; michael@0: if(stagebook){ michael@0: if(decodepart(stagebook,in[j]+offset,&vb->opb, michael@0: samples_per_partition,-8)==-1)goto eopbreak; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: errout: michael@0: eopbreak: michael@0: return(0); michael@0: } michael@0: michael@0: int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, michael@0: ogg_int32_t **in,int *nonzero,int ch){ michael@0: int i,used=0; michael@0: for(i=0;iinfo; michael@0: michael@0: /* move all this setup out later */ michael@0: int samples_per_partition=info->grouping; michael@0: int partitions_per_word=look->phrasebook->dim; michael@0: int max=(vb->pcmend*ch)>>1; michael@0: int end=(info->endend:max); michael@0: int n=end-info->begin; michael@0: michael@0: if(n>0){ michael@0: michael@0: int partvals=n/samples_per_partition; michael@0: int partwords=(partvals+partitions_per_word-1)/partitions_per_word; michael@0: int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); michael@0: int beginoff=info->begin/ch; michael@0: michael@0: for(i=0;istages;s++){ michael@0: for(i=0,l=0;iphrasebook,&vb->opb); michael@0: if(temp==-1 || temp>=info->partvals)goto eopbreak; michael@0: partword[l]=look->decodemap[temp]; michael@0: if(partword[l]==NULL)goto errout; michael@0: } michael@0: michael@0: /* now we decode residual values for the partitions */ michael@0: for(k=0;ksecondstages[partword[l][k]]&(1<partbooks[partword[l][k]][s]; michael@0: michael@0: if(stagebook){ michael@0: if(vorbis_book_decodevv_add(stagebook,in, michael@0: i*samples_per_partition+beginoff,ch, michael@0: &vb->opb, michael@0: samples_per_partition,-8)==-1) michael@0: goto eopbreak; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: errout: michael@0: eopbreak: michael@0: return(0); michael@0: } michael@0: michael@0: michael@0: vorbis_func_residue residue0_exportbundle={ michael@0: &res0_unpack, michael@0: &res0_look, michael@0: &res0_free_info, michael@0: &res0_free_look, michael@0: &res0_inverse michael@0: }; michael@0: michael@0: vorbis_func_residue residue1_exportbundle={ michael@0: &res0_unpack, michael@0: &res0_look, michael@0: &res0_free_info, michael@0: &res0_free_look, michael@0: &res1_inverse michael@0: }; michael@0: michael@0: vorbis_func_residue residue2_exportbundle={ michael@0: &res0_unpack, michael@0: &res0_look, michael@0: &res0_free_info, michael@0: &res0_free_look, michael@0: &res2_inverse michael@0: };