examples/sfexamples/oggvorbiscodec/src/tremor/codebook.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
00004  *                                                                  *
00005  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00006  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00007  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00008  *                                                                  *
00009  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
00010  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
00011  *                                                                  *
00012  ********************************************************************
00013 
00014  function: basic codebook pack/unpack/code/decode operations
00015 
00016  ********************************************************************/
00017 
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <math.h>
00021 #include "ogg.h"
00022 #include "ivorbiscodec.h"
00023 #include "codebook.h"
00024 #include "misc.h"
00025 #include "os.h"
00026 
00027 /* unpacks a codebook from the packet buffer into the codebook struct,
00028    readies the codebook auxiliary structures for decode *************/
00029 int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){
00030   long i,j;
00031   memset(s,0,sizeof(*s));
00032 
00033   /* make sure alignment is correct */
00034   if(oggpack_read(opb,24)!=0x564342)goto _eofout;
00035 
00036   /* first the basic parameters */
00037   s->dim=oggpack_read(opb,16);
00038   s->entries=oggpack_read(opb,24);
00039   if(s->entries==-1)goto _eofout;
00040 
00041   /* codeword ordering.... length ordered or unordered? */
00042   switch((int)oggpack_read(opb,1)){
00043   case 0:
00044     /* unordered */
00045     s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
00046 
00047     /* allocated but unused entries? */
00048     if(oggpack_read(opb,1)){
00049       /* yes, unused entries */
00050 
00051       for(i=0;i<s->entries;i++){
00052         if(oggpack_read(opb,1)){
00053           long num=oggpack_read(opb,5);
00054           if(num==-1)goto _eofout;
00055           s->lengthlist[i]=num+1;
00056         }else
00057           s->lengthlist[i]=0;
00058       }
00059     }else{
00060       /* all entries used; no tagging */
00061       for(i=0;i<s->entries;i++){
00062         long num=oggpack_read(opb,5);
00063         if(num==-1)goto _eofout;
00064         s->lengthlist[i]=num+1;
00065       }
00066     }
00067     
00068     break;
00069   case 1:
00070     /* ordered */
00071     {
00072       long length=oggpack_read(opb,5)+1;
00073       s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
00074 
00075       for(i=0;i<s->entries;){
00076         long num=oggpack_read(opb,_ilog(s->entries-i));
00077         if(num==-1)goto _eofout;
00078         for(j=0;j<num && i<s->entries;j++,i++)
00079           s->lengthlist[i]=length;
00080         length++;
00081       }
00082     }
00083     break;
00084   default:
00085     /* EOF */
00086     return(-1);
00087   }
00088   
00089   /* Do we have a mapping to unpack? */
00090   switch((s->maptype=oggpack_read(opb,4))){
00091   case 0:
00092     /* no mapping */
00093     break;
00094   case 1: case 2:
00095     /* implicitly populated value mapping */
00096     /* explicitly populated value mapping */
00097 
00098     s->q_min=oggpack_read(opb,32);
00099     s->q_delta=oggpack_read(opb,32);
00100     s->q_quant=oggpack_read(opb,4)+1;
00101     s->q_sequencep=oggpack_read(opb,1);
00102 
00103     {
00104       int quantvals=0;
00105       switch(s->maptype){
00106       case 1:
00107         quantvals=_book_maptype1_quantvals(s);
00108         break;
00109       case 2:
00110         quantvals=s->entries*s->dim;
00111         break;
00112       }
00113       
00114       /* quantized values */
00115       s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals);
00116       for(i=0;i<quantvals;i++)
00117         s->quantlist[i]=oggpack_read(opb,s->q_quant);
00118       
00119       if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
00120     }
00121     break;
00122   default:
00123     goto _errout;
00124   }
00125 
00126   /* all set */
00127   return(0);
00128   
00129  _errout:
00130  _eofout:
00131   vorbis_staticbook_clear(s);
00132   return(-1); 
00133 }
00134 
00135 /* the 'eliminate the decode tree' optimization actually requires the
00136    codewords to be MSb first, not LSb.  This is an annoying inelegancy
00137    (and one of the first places where carefully thought out design
00138    turned out to be wrong; Vorbis II and future Ogg codecs should go
00139    to an MSb bitpacker), but not actually the huge hit it appears to
00140    be.  The first-stage decode table catches most words so that
00141    bitreverse is not in the main execution path. */
00142 
00143 static ogg_uint32_t bitreverse(ogg_uint32_t x){
00144   x=    ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
00145   x=    ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
00146   x=    ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
00147   x=    ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
00148   return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
00149 }
00150 
00151 static long decode_packed_entry_number(codebook *book, 
00152                                               oggpack_buffer *b){
00153   int  read=book->dec_maxlength;
00154   long lo,hi;
00155   long lok = oggpack_look(b,book->dec_firsttablen);
00156  
00157   if (lok >= 0) {
00158     long entry = book->dec_firsttable[lok];
00159     if(entry&0x80000000UL){
00160       lo=(entry>>15)&0x7fff;
00161       hi=book->used_entries-(entry&0x7fff);
00162     }else{
00163       oggpack_adv(b, book->dec_codelengths[entry-1]);
00164       return(entry-1);
00165     }
00166   }else{
00167     lo=0;
00168     hi=book->used_entries;
00169   }
00170 
00171   lok = oggpack_look(b, read);
00172 
00173   while(lok<0 && read>1)
00174     lok = oggpack_look(b, --read);
00175   if(lok<0)return -1;
00176 
00177   /* bisect search for the codeword in the ordered list */
00178   {
00179     ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
00180 
00181     while(hi-lo>1){
00182       long p=(hi-lo)>>1;
00183       long test=book->codelist[lo+p]>testword;    
00184       lo+=p&(test-1);
00185       hi-=p&(-test);
00186     }
00187 
00188     if(book->dec_codelengths[lo]<=read){
00189       oggpack_adv(b, book->dec_codelengths[lo]);
00190       return(lo);
00191     }
00192   }
00193   
00194   oggpack_adv(b, read);
00195   return(-1);
00196 }
00197 
00198 /* Decode side is specced and easier, because we don't need to find
00199    matches using different criteria; we simply read and map.  There are
00200    two things we need to do 'depending':
00201    
00202    We may need to support interleave.  We don't really, but it's
00203    convenient to do it here rather than rebuild the vector later.
00204 
00205    Cascades may be additive or multiplicitive; this is not inherent in
00206    the codebook, but set in the code using the codebook.  Like
00207    interleaving, it's easiest to do it here.  
00208    addmul==0 -> declarative (set the value)
00209    addmul==1 -> additive
00210    addmul==2 -> multiplicitive */
00211 
00212 /* returns the [original, not compacted] entry number or -1 on eof *********/
00213 long vorbis_book_decode(codebook *book, oggpack_buffer *b){
00214   long packed_entry=decode_packed_entry_number(book,b);
00215   if(packed_entry>=0)
00216     return(book->dec_index[packed_entry]);
00217   
00218   /* if there's no dec_index, the codebook unpacking isn't collapsed */
00219   return(packed_entry);
00220 }
00221 
00222 /* returns 0 on OK or -1 on eof *************************************/
00223 long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
00224                               oggpack_buffer *b,int n,int point){
00225   int step=n/book->dim;
00226   long *entry = (long *)_ogg_malloc(sizeof(*entry)*step);
00227   ogg_int32_t **t = (ogg_int32_t **)_ogg_malloc(sizeof(*t)*step);
00228   int i,j,o;
00229   int shift=point-book->binarypoint;
00230 
00231   if(shift>=0){
00232     for (i = 0; i < step; i++) {
00233       entry[i]=decode_packed_entry_number(book,b);
00234       if(entry[i]==-1)
00235         {
00236         _ogg_free(entry);
00237         _ogg_free(t);
00238         return(-1);
00239         }
00240       t[i] = book->valuelist+entry[i]*book->dim;
00241     }
00242     for(i=0,o=0;i<book->dim;i++,o+=step)
00243       for (j=0;j<step;j++)
00244         a[o+j]+=t[j][i]>>shift;
00245   }else{
00246     for (i = 0; i < step; i++) {
00247       entry[i]=decode_packed_entry_number(book,b);
00248       if(entry[i]==-1)return(-1);
00249       t[i] = book->valuelist+entry[i]*book->dim;
00250     }
00251     for(i=0,o=0;i<book->dim;i++,o+=step)
00252       for (j=0;j<step;j++)
00253         a[o+j]+=t[j][i]<<-shift;
00254   }
00255   _ogg_free(entry);
00256   _ogg_free(t);
00257   return(0);
00258 }
00259 
00260 long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
00261                              oggpack_buffer *b,int n,int point){
00262   int i,j,entry;
00263   ogg_int32_t *t;
00264   int shift=point-book->binarypoint;
00265   
00266   if(shift>=0){
00267     for(i=0;i<n;){
00268       entry = decode_packed_entry_number(book,b);
00269       if(entry==-1)return(-1);
00270       t     = book->valuelist+entry*book->dim;
00271       for (j=0;j<book->dim;)
00272         a[i++]+=t[j++]>>shift;
00273     }
00274   }else{
00275     for(i=0;i<n;){
00276       entry = decode_packed_entry_number(book,b);
00277       if(entry==-1)return(-1);
00278       t     = book->valuelist+entry*book->dim;
00279       for (j=0;j<book->dim;)
00280         a[i++]+=t[j++]<<-shift;
00281     }
00282   }
00283   return(0);
00284 }
00285 
00286 long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
00287                              oggpack_buffer *b,int n,int point){
00288   int i,j,entry;
00289   ogg_int32_t *t;
00290   int shift=point-book->binarypoint;
00291   
00292   if(shift>=0){
00293 
00294     for(i=0;i<n;){
00295       entry = decode_packed_entry_number(book,b);
00296       if(entry==-1)return(-1);
00297       t     = book->valuelist+entry*book->dim;
00298       for (j=0;j<book->dim;){
00299         a[i++]=t[j++]>>shift;
00300       }
00301     }
00302   }else{
00303 
00304     for(i=0;i<n;){
00305       entry = decode_packed_entry_number(book,b);
00306       if(entry==-1)return(-1);
00307       t     = book->valuelist+entry*book->dim;
00308       for (j=0;j<book->dim;){
00309         a[i++]=t[j++]<<-shift;
00310       }
00311     }
00312   }
00313   return(0);
00314 }
00315 
00316 long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,\
00317                               long offset,int ch,
00318                               oggpack_buffer *b,int n,int point){
00319   long i,j,entry;
00320   int chptr=0;
00321   int shift=point-book->binarypoint;
00322   
00323   if(shift>=0){
00324     
00325     for(i=offset;i<offset+n;){
00326       entry = decode_packed_entry_number(book,b);
00327       if(entry==-1)return(-1);
00328       {
00329         const ogg_int32_t *t = book->valuelist+entry*book->dim;
00330         for (j=0;j<book->dim;j++){
00331           a[chptr++][i]+=t[j]>>shift;
00332           if(chptr==ch){
00333             chptr=0;
00334             i++;
00335           }
00336         }
00337       }
00338     }
00339   }else{
00340 
00341     for(i=offset;i<offset+n;){
00342       entry = decode_packed_entry_number(book,b);
00343       if(entry==-1)return(-1);
00344       {
00345         const ogg_int32_t *t = book->valuelist+entry*book->dim;
00346         for (j=0;j<book->dim;j++){
00347           a[chptr++][i]+=t[j]<<-shift;
00348           if(chptr==ch){
00349             chptr=0;
00350             i++;
00351           }
00352         }
00353       }
00354     }
00355   }
00356   return(0);
00357 }

Generated by  doxygen 1.6.2