[xiph-cvs] cvs commit: vorbis/lib block.c codebook.c codebook.h sharedbook.c

Monty xiphmont at xiph.org
Fri Jan 18 20:52:41 PST 2002



xiphmont    02/01/18 20:52:41

  Modified:    lib      block.c codebook.c codebook.h sharedbook.c
  Log:
  Memory use reduction:
  
  eliminate huffman decode tree
  eliminate need to keep static codebook for decode
  compact sparse codebooks to reduce mem usage
  
  experimental, test it well.

Revision  Changes    Path
1.56      +7 -3      vorbis/lib/block.c

Index: block.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/block.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- block.c	2001/12/23 11:53:52	1.55
+++ block.c	2002/01/19 04:52:39	1.56
@@ -5,13 +5,13 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.55 2001/12/23 11:53:52 xiphmont Exp $
+ last mod: $Id: block.c,v 1.56 2002/01/19 04:52:39 xiphmont Exp $
 
  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
  more amusing by Vorbis' current two allowed block sizes.
@@ -221,8 +221,12 @@
   }else{
     /* finish the codebooks */
     b->fullbooks=_ogg_calloc(ci->books,sizeof(*b->fullbooks));
-    for(i=0;i<ci->books;i++)
+    for(i=0;i<ci->books;i++){
       vorbis_book_init_decode(b->fullbooks+i,ci->book_param[i]);
+      /* decode codebooks are now standalone after init */
+      vorbis_staticbook_destroy(ci->book_param[i]);
+      ci->book_param[i]=NULL;
+    }
   }
 
   /* initialize the storage vectors to a decent size greater than the

<p><p>1.36      +76 -32    vorbis/lib/codebook.c

Index: codebook.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/codebook.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- codebook.c	2001/12/21 14:52:35	1.35
+++ codebook.c	2002/01/19 04:52:39	1.36
@@ -5,13 +5,13 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: basic codebook pack/unpack/code/decode operations
- last mod: $Id: codebook.c,v 1.35 2001/12/21 14:52:35 segher Exp $
+ last mod: $Id: codebook.c,v 1.36 2002/01/19 04:52:39 xiphmont Exp $
 
  ********************************************************************/
 
@@ -299,6 +299,68 @@
   return(vorbis_book_encode(book,best,b));
 }
 
+/* the 'eliminate the decode tree' optimization actually requires the
+   codewords to be MSb first, not LSb.  This is an annoying inelegancy
+   (and one of the first places where carefully thought out design
+   turned out to be wrong; Vorbis II and future Ogg codecs should go
+   to an MSb bitpacker), but not actually the huge hit it appears to
+   be.  The first-stage decode table catches most words so that
+   bitreverse is not in the main execution path. */
+
+static ogg_uint32_t bitreverse(ogg_uint32_t x){
+  x=    ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
+  x=    ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
+  x=    ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
+  x=    ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
+  return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
+}
+
+static long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
+  int read;
+  long lok = oggpack_look(b, book->dec_firsttablen);
+
+  if (lok >= 0) {
+    long entry = book->dec_firsttable[lok];
+    if(entry>=0){
+      oggpack_adv(b, book->dec_codelengths[entry]);
+      return(entry);
+    }
+  }
+
+  read=book->dec_maxlength;
+  lok = oggpack_look(b, read);
+
+  while(lok<0 && read>1)
+    lok = oggpack_look(b, --read);
+
+  if(lok<0)return -1;
+
+  /* bisect search for the codeword in the ordered list */
+  {
+    ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
+
+    long lo=0;
+    long hi=book->used_entries;
+    long p=(lo+hi)>>1;
+
+    while(hi-lo>1){
+      if(book->codelist[p]<=testword)
+	lo=p;
+      else
+	hi=p;
+      p=(lo+hi)>>1;
+    }
+
+    if(book->dec_codelengths[p]<=read){
+      oggpack_adv(b, book->dec_codelengths[p]);
+      return(p);
+    }
+  }
+  
+  oggpack_adv(b, read);
+  return(-1);
+}
+
 /* Decode side is specced and easier, because we don't need to find
    matches using different criteria; we simply read and map.  There are
    two things we need to do 'depending':
@@ -313,32 +375,14 @@
    addmul==1 -> additive
    addmul==2 -> multiplicitive */
 
-/* returns the entry number or -1 on eof *************************************/
+/* returns the [original, not compacted] entry number or -1 on eof *********/
 long vorbis_book_decode(codebook *book, oggpack_buffer *b){
-  long ptr=0;
-  decode_aux *t=book->decode_tree;
-  int lok = oggpack_look(b, t->tabn);
-
-  if (lok >= 0) {
-    ptr = t->tab[lok];
-    oggpack_adv(b, t->tabl[lok]);
-    if (ptr <= 0)
-      return -ptr;
-  }
-
-  do{
-    switch((int)oggpack_read1(b)){
-    case 0:
-      ptr=t->ptr0[ptr];
-      break;
-    case 1:
-      ptr=t->ptr1[ptr];
-      break;
-    case -1:
-      return(-1);
-    }
-  }while(ptr>0);
-  return(-ptr);
+  long packed_entry=decode_packed_entry_number(book,b);
+  if(packed_entry>=0)
+    return(book->dec_index[packed_entry]);
+  
+  /* if there's no dec_index, the codebook unpacking isn't collapsed */
+  return(packed_entry);
 }
 
 /* returns 0 on OK or -1 on eof *************************************/
@@ -349,7 +393,7 @@
   int i,j,o;
 
   for (i = 0; i < step; i++) {
-    entry[i]=vorbis_book_decode(book,b);
+    entry[i]=decode_packed_entry_number(book,b);
     if(entry[i]==-1)return(-1);
     t[i] = book->valuelist+entry[i]*book->dim;
   }
@@ -365,7 +409,7 @@
 
   if(book->dim>8){
     for(i=0;i<n;){
-      entry = vorbis_book_decode(book,b);
+      entry = decode_packed_entry_number(book,b);
       if(entry==-1)return(-1);
       t     = book->valuelist+entry*book->dim;
       for (j=0;j<book->dim;)
@@ -373,7 +417,7 @@
     }
   }else{
     for(i=0;i<n;){
-      entry = vorbis_book_decode(book,b);
+      entry = decode_packed_entry_number(book,b);
       if(entry==-1)return(-1);
       t     = book->valuelist+entry*book->dim;
       j=0;
@@ -407,7 +451,7 @@
   float *t;
 
   for(i=0;i<n;){
-    entry = vorbis_book_decode(book,b);
+    entry = decode_packed_entry_number(book,b);
     if(entry==-1)return(-1);
     t     = book->valuelist+entry*book->dim;
     for (j=0;j<book->dim;)
@@ -422,7 +466,7 @@
   int chptr=0;
 
   for(i=offset/ch;i<(offset+n)/ch;){
-    entry = vorbis_book_decode(book,b);
+    entry = decode_packed_entry_number(book,b);
     if(entry==-1)return(-1);
     {
       const float *t = book->valuelist+entry*book->dim;

<p><p>1.11      +15 -17    vorbis/lib/codebook.h

Index: codebook.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/codebook.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- codebook.h	2001/12/20 01:00:26	1.10
+++ codebook.h	2002/01/19 04:52:40	1.11
@@ -5,13 +5,13 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: basic shared codebook operations
- last mod: $Id: codebook.h,v 1.10 2001/12/20 01:00:26 segher Exp $
+ last mod: $Id: codebook.h,v 1.11 2002/01/19 04:52:40 xiphmont Exp $
 
  ********************************************************************/
 
@@ -96,26 +96,24 @@
   long *fitlength;
 } encode_aux_pigeonhole;
 
-typedef struct decode_aux{
-  long   *tab;
-  int    *tabl;
-  int    tabn;
-
-  long   *ptr0;
-  long   *ptr1;
-  long   aux;        /* number of tree entries */
-} decode_aux;
-
 typedef struct codebook{
   long dim;           /* codebook dimensions (elements per vector) */
   long entries;       /* codebook entries */
+  long used_entries;  /* populated codebook entries */
   const static_codebook *c;
 
-  float  *valuelist;  /* list of dim*entries actual entry values */
-  long   *codelist;   /* list of bitstream codewords for each entry */
-  struct decode_aux *decode_tree;
+  /* for encode, the below are entry-ordered, fully populated */
+  /* for decode, the below are ordered by bitreversed codeword and only
+     used entries are populated */
+  float        *valuelist;  /* list of dim*entries actual entry values */  
+  ogg_uint32_t *codelist;   /* list of bitstream codewords for each entry */
+
+  int          *dec_index;  /* only used if sparseness collapsed */
+  char         *dec_codelengths;
+  int          *dec_firsttable;
+  int           dec_firsttablen;
+  int           dec_maxlength;
 
-  long zeroentry;
 } codebook;
 
 extern void vorbis_staticbook_clear(static_codebook *b);
@@ -124,7 +122,7 @@
 extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source);
 extern void vorbis_book_clear(codebook *b);
 
-extern float *_book_unquantize(const static_codebook *b);
+extern float *_book_unquantize(const static_codebook *b,int n,int *map);
 extern float *_book_logdist(const static_codebook *b,float *vals);
 extern float _float32_unpack(long val);
 extern long   _float32_pack(float val);

<p><p>1.23      +158 -122  vorbis/lib/sharedbook.c

Index: sharedbook.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/sharedbook.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- sharedbook.c	2001/12/21 14:52:36	1.22
+++ sharedbook.c	2002/01/19 04:52:40	1.23
@@ -5,13 +5,13 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: basic shared codebook operations
- last mod: $Id: sharedbook.c,v 1.22 2001/12/21 14:52:36 segher Exp $
+ last mod: $Id: sharedbook.c,v 1.23 2002/01/19 04:52:40 xiphmont Exp $
 
  ********************************************************************/
 
@@ -69,16 +69,16 @@
 /* given a list of word lengths, generate a list of codewords.  Works
    for length ordered or unordered, always assigns the lowest valued
    codewords first.  Extended to handle unused entries (length 0) */
-long *_make_words(long *l,long n){
-  long i,j;
-  long marker[33];
-  long *r=_ogg_malloc(n*sizeof(*r));
+ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
+  long i,j,count=0;
+  ogg_uint32_t marker[33];
+  ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
   memset(marker,0,sizeof(marker));
 
   for(i=0;i<n;i++){
     long length=l[i];
     if(length>0){
-      long entry=marker[length];
+      ogg_uint32_t entry=marker[length];
       
       /* when we claim a node for an entry, we also claim the nodes
          below it (pruning off the imagined tree that may have dangled
@@ -91,7 +91,7 @@
         _ogg_free(r);
         return(NULL);
       }
-      r[i]=entry;
+      r[count++]=entry;
     
       /* Look to see if the next shorter marker points to the node
          above. if so, update it and repeat.  */
@@ -120,79 +120,26 @@
           marker[j]=marker[j-1]<<1;
         }else
           break;
-    }    
+    }else
+      if(sparsecount==0)count++;
   }
     
   /* bitreverse the words because our bitwise packer/unpacker is LSb
      endian */
-  for(i=0;i<n;i++){
-    long temp=0;
+  for(i=0,count=0;i<n;i++){
+    ogg_uint32_t temp=0;
     for(j=0;j<l[i];j++){
       temp<<=1;
-      temp|=(r[i]>>j)&1;
+      temp|=(r[count]>>j)&1;
     }
-    r[i]=temp;
+    r[count]=temp;
+    if(l[i] || sparsecount==0)
+      count++;
   }
 
   return(r);
 }
 
-/* build the decode helper tree from the codewords */
-decode_aux *_make_decode_tree(codebook *c){
-  const static_codebook *s=c->c;
-  long top=0,i,j,n;
-  decode_aux *t=_ogg_malloc(sizeof(*t));
-  long *ptr0=t->ptr0=_ogg_calloc(c->entries*2,sizeof(*ptr0));
-  long *ptr1=t->ptr1=_ogg_calloc(c->entries*2,sizeof(*ptr1));
-  long *codelist=_make_words(s->lengthlist,s->entries);
-
-  if(codelist==NULL)return(NULL);
-  t->aux=c->entries*2;
-
-  for(i=0;i<c->entries;i++){
-    if(s->lengthlist[i]>0){
-      long ptr=0;
-      for(j=0;j<s->lengthlist[i]-1;j++){
-	int bit=(codelist[i]>>j)&1;
-	if(!bit){
-	  if(!ptr0[ptr])
-	    ptr0[ptr]= ++top;
-	  ptr=ptr0[ptr];
-	}else{
-	  if(!ptr1[ptr])
-	    ptr1[ptr]= ++top;
-	  ptr=ptr1[ptr];
-	}
-      }
-      if(!((codelist[i]>>j)&1))
-	ptr0[ptr]=-i;
-      else
-	ptr1[ptr]=-i;
-    }
-  }
-  _ogg_free(codelist);
-
-  t->tabn = _ilog(c->entries)-4; /* this is magic */
-  if(t->tabn<5)t->tabn=5;
-  n = 1<<t->tabn;
-  t->tab = _ogg_malloc(n*sizeof(*t->tab));
-  t->tabl = _ogg_malloc(n*sizeof(*t->tabl));
-  for (i = 0; i < n; i++) {
-    long p = 0;
-    for (j = 0; j < t->tabn && (p > 0 || j == 0); j++) {
-      if (i & (1 << j))
-	p = ptr1[p];
-      else
-	p = ptr0[p];
-    }
-    /* now j == length, and p == -code */
-    t->tab[i] = p;
-    t->tabl[i] = j;
-  }
-
-  return(t);
-}
-
 /* there might be a straightforward one-line way to do the below
    that's portable and totally safe against roundoff, but I haven't
    thought of it.  Therefore, we opt on the side of caution */
@@ -229,13 +176,13 @@
    generated algorithmically (each column of the vector counts through
    the values in the quant vector). in map type 2, all the values came
    in in an explicit list.  Both value lists must be unpacked */
-float *_book_unquantize(const static_codebook *b){
-  long j,k;
+float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
+  long j,k,count=0;
   if(b->maptype==1 || b->maptype==2){
     int quantvals;
     float mindel=_float32_unpack(b->q_min);
     float delta=_float32_unpack(b->q_delta);
-    float *r=_ogg_calloc(b->entries*b->dim,sizeof(*r));
+    float *r=_ogg_calloc(n*b->dim,sizeof(*r));
 
     /* maptype 1 and 2 both use a quantized value vector, but
        different sizes */
@@ -250,26 +197,40 @@
          that */
       quantvals=_book_maptype1_quantvals(b);
       for(j=0;j<b->entries;j++){
-	float last=0.f;
-	int indexdiv=1;
-	for(k=0;k<b->dim;k++){
-	  int index= (j/indexdiv)%quantvals;
-	  float val=b->quantlist[index];
-	  val=fabs(val)*delta+mindel+last;
-	  if(b->q_sequencep)last=val;	  
-	  r[j*b->dim+k]=val;
-	  indexdiv*=quantvals;
+	if((sparsemap && b->lengthlist[j]) || !sparsemap){
+	  float last=0.f;
+	  int indexdiv=1;
+	  for(k=0;k<b->dim;k++){
+	    int index= (j/indexdiv)%quantvals;
+	    float val=b->quantlist[index];
+	    val=fabs(val)*delta+mindel+last;
+	    if(b->q_sequencep)last=val;	  
+	    if(sparsemap)
+	      r[sparsemap[count]*b->dim+k]=val;
+	    else
+	      r[count*b->dim+k]=val;
+	    indexdiv*=quantvals;
+	  }
+	  count++;
         }
+
       }
       break;
     case 2:
       for(j=0;j<b->entries;j++){
-	float last=0.f;
-	for(k=0;k<b->dim;k++){
-	  float val=b->quantlist[j*b->dim+k];
-	  val=fabs(val)*delta+mindel+last;
-	  if(b->q_sequencep)last=val;	  
-	  r[j*b->dim+k]=val;
+	if((sparsemap && b->lengthlist[j]) || !sparsemap){
+	  float last=0.f;
+	  
+	  for(k=0;k<b->dim;k++){
+	    float val=b->quantlist[j*b->dim+k];
+	    val=fabs(val)*delta+mindel+last;
+	    if(b->q_sequencep)last=val;	  
+	    if(sparsemap)
+	      r[sparsemap[count]*b->dim+k]=val;
+	    else
+	      r[count*b->dim+k]=val;
+	  }
+	  count++;
         }
       }
       break;
@@ -313,56 +274,125 @@
 void vorbis_book_clear(codebook *b){
   /* static book is not cleared; we're likely called on the lookup and
      the static codebook belongs to the info struct */
-  if(b->decode_tree){
-    _ogg_free(b->decode_tree->tab);
-    _ogg_free(b->decode_tree->tabl);
-
-    _ogg_free(b->decode_tree->ptr0);
-    _ogg_free(b->decode_tree->ptr1);
-    memset(b->decode_tree,0,sizeof(*b->decode_tree));
-    _ogg_free(b->decode_tree);
-  }
   if(b->valuelist)_ogg_free(b->valuelist);
   if(b->codelist)_ogg_free(b->codelist);
+
+  if(b->dec_index)_ogg_free(b->dec_index);
+  if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
+  if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
+
   memset(b,0,sizeof(*b));
 }
 
 int vorbis_book_init_encode(codebook *c,const static_codebook *s){
-  long j,k;
+
   memset(c,0,sizeof(*c));
   c->c=s;
   c->entries=s->entries;
+  c->used_entries=s->entries;
   c->dim=s->dim;
-  c->codelist=_make_words(s->lengthlist,s->entries);
-  c->valuelist=_book_unquantize(s);
+  c->codelist=_make_words(s->lengthlist,s->entries,0);
+  c->valuelist=_book_unquantize(s,s->entries,NULL);
 
-  /* set the 'zero entry' */
-  c->zeroentry=-1;
-  if(c->valuelist){
-    for(j=0;j<s->entries;j++){
-      int flag=1;
-      for(k=0;k<s->dim;k++){
-	if(fabs(c->valuelist[j*s->dim+k])>1e-12f){
-	  flag=0;
-	  break;
-	}
-      }
-      if(flag)
-	c->zeroentry=j;
-    }
-  }
-
   return(0);
 }
 
+static ogg_uint32_t bitreverse(ogg_uint32_t x){
+  x=    ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
+  x=    ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
+  x=    ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
+  x=    ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
+  return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
+}
+
+static int sort32a(const void *a,const void *b){
+  return ( (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)<<1)-1;
+}
+
+
+/* decode codebook arrangement is more heavily optimized than encode */
 int vorbis_book_init_decode(codebook *c,const static_codebook *s){
+  int i,j,n=0,tabn;
+  int *sortindex;
   memset(c,0,sizeof(*c));
-  c->c=s;
+  
+  /* count actually used entries */
+  for(i=0;i<s->entries;i++)
+    if(s->lengthlist[i]>0)
+      n++;
+
   c->entries=s->entries;
+  c->used_entries=n;
   c->dim=s->dim;
-  c->valuelist=_book_unquantize(s);
-  c->decode_tree=_make_decode_tree(c);
-  if(c->decode_tree==NULL)goto err_out;
+
+  /* two different remappings go on here.  
+
+     First, we collapse the likely sparse codebook down only to
+     actually represented values/words.  This collapsing needs to be
+     indexed as map-valueless books are used to encode original entry
+     positions as integers.
+
+     Second, we reorder all vectors, including the entry index above,
+     by sorted bitreversed codeword to allow treeless decode. */
+
+  {
+    /* perform sort */
+    ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
+    ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
+    
+    if(codes==NULL)goto err_out;
+
+    for(i=0;i<n;i++){
+      codes[i]=bitreverse(codes[i]);
+      codep[i]=codes+i;
+    }
+
+    qsort(codep,n,sizeof(*codep),sort32a);
+
+    sortindex=alloca(n*sizeof(*sortindex));
+    c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
+    /* the index is a reverse index */
+    for(i=0;i<n;i++){
+      int position=codep[i]-codes;
+      sortindex[position]=i;
+    }
+
+    for(i=0;i<n;i++)
+      c->codelist[sortindex[i]]=codes[i];
+    _ogg_free(codes);
+  }
+
+  c->valuelist=_book_unquantize(s,n,sortindex);
+  c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
+
+  for(n=0,i=0;i<s->entries;i++)
+    if(s->lengthlist[i]>0)
+      c->dec_index[sortindex[n++]]=i;
+  
+  c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
+  for(n=0,i=0;i<s->entries;i++)
+    if(s->lengthlist[i]>0)
+      c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
+
+  c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
+  if(c->dec_firsttablen<5)c->dec_firsttablen=5;
+  if(c->dec_firsttablen>8)c->dec_firsttablen=8;
+
+  tabn=1<<c->dec_firsttablen;
+  c->dec_firsttable=_ogg_malloc(tabn*sizeof(*c->dec_firsttable));
+  for(i=0;i<tabn;i++)c->dec_firsttable[i]=-1;
+  c->dec_maxlength=0;
+
+  for(i=0;i<n;i++){
+    if(c->dec_maxlength<c->dec_codelengths[i])
+      c->dec_maxlength=c->dec_codelengths[i];
+    if(c->dec_codelengths[i]<=c->dec_firsttablen){
+      ogg_uint32_t orig=bitreverse(c->codelist[i]);
+      for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
+	c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i;
+    }
+  }
+
   return(0);
  err_out:
   vorbis_book_clear(c);
@@ -531,11 +561,17 @@
 }
 
 long vorbis_book_codeword(codebook *book,int entry){
-  return book->codelist[entry];
+  if(book->c) /* only use with encode; decode optimizations are
+                 allowed to break this */
+    return book->codelist[entry];
+  return -1;
 }
 
 long vorbis_book_codelen(codebook *book,int entry){
-  return book->c->lengthlist[entry];
+  if(book->c) /* only use with encode; decode optimizations are
+                 allowed to break this */
+    return book->c->lengthlist[entry];
+  return -1;
 }
 
 #ifdef _V_SELFTEST
@@ -631,7 +667,7 @@
                               -3,-4,-5, 4, 3, 2, -1,-2,-3};
 
 void run_test(static_codebook *b,float *comp){
-  float *out=_book_unquantize(b);
+  float *out=_book_unquantize(b,b->entries,NULL);
   int i;
 
   if(comp){

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list