Blame lib/codebook.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: basic codebook pack/unpack/code/decode operations
Packit 06404a
 last mod: $Id: codebook.c 19457 2015-03-03 00:15:29Z giles $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <ogg/ogg.h>
Packit 06404a
#include "vorbis/codec.h"
Packit 06404a
#include "codebook.h"
Packit 06404a
#include "scales.h"
Packit 06404a
#include "misc.h"
Packit 06404a
#include "os.h"
Packit 06404a
Packit 06404a
/* packs the given codebook into the bitstream **************************/
Packit 06404a
Packit 06404a
int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
Packit 06404a
  long i,j;
Packit 06404a
  int ordered=0;
Packit 06404a
Packit 06404a
  /* first the basic parameters */
Packit 06404a
  oggpack_write(opb,0x564342,24);
Packit 06404a
  oggpack_write(opb,c->dim,16);
Packit 06404a
  oggpack_write(opb,c->entries,24);
Packit 06404a
Packit 06404a
  /* pack the codewords.  There are two packings; length ordered and
Packit 06404a
     length random.  Decide between the two now. */
Packit 06404a
Packit 06404a
  for(i=1;i<c->entries;i++)
Packit 06404a
    if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break;
Packit 06404a
  if(i==c->entries)ordered=1;
Packit 06404a
Packit 06404a
  if(ordered){
Packit 06404a
    /* length ordered.  We only need to say how many codewords of
Packit 06404a
       each length.  The actual codewords are generated
Packit 06404a
       deterministically */
Packit 06404a
Packit 06404a
    long count=0;
Packit 06404a
    oggpack_write(opb,1,1);  /* ordered */
Packit 06404a
    oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
Packit 06404a
Packit 06404a
    for(i=1;i<c->entries;i++){
Packit 06404a
      char this=c->lengthlist[i];
Packit 06404a
      char last=c->lengthlist[i-1];
Packit 06404a
      if(this>last){
Packit 06404a
        for(j=last;j
Packit 06404a
          oggpack_write(opb,i-count,ov_ilog(c->entries-count));
Packit 06404a
          count=i;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
    oggpack_write(opb,i-count,ov_ilog(c->entries-count));
Packit 06404a
Packit 06404a
  }else{
Packit 06404a
    /* length random.  Again, we don't code the codeword itself, just
Packit 06404a
       the length.  This time, though, we have to encode each length */
Packit 06404a
    oggpack_write(opb,0,1);   /* unordered */
Packit 06404a
Packit 06404a
    /* algortihmic mapping has use for 'unused entries', which we tag
Packit 06404a
       here.  The algorithmic mapping happens as usual, but the unused
Packit 06404a
       entry has no codeword. */
Packit 06404a
    for(i=0;i<c->entries;i++)
Packit 06404a
      if(c->lengthlist[i]==0)break;
Packit 06404a
Packit 06404a
    if(i==c->entries){
Packit 06404a
      oggpack_write(opb,0,1); /* no unused entries */
Packit 06404a
      for(i=0;i<c->entries;i++)
Packit 06404a
        oggpack_write(opb,c->lengthlist[i]-1,5);
Packit 06404a
    }else{
Packit 06404a
      oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
Packit 06404a
      for(i=0;i<c->entries;i++){
Packit 06404a
        if(c->lengthlist[i]==0){
Packit 06404a
          oggpack_write(opb,0,1);
Packit 06404a
        }else{
Packit 06404a
          oggpack_write(opb,1,1);
Packit 06404a
          oggpack_write(opb,c->lengthlist[i]-1,5);
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* is the entry number the desired return value, or do we have a
Packit 06404a
     mapping? If we have a mapping, what type? */
Packit 06404a
  oggpack_write(opb,c->maptype,4);
Packit 06404a
  switch(c->maptype){
Packit 06404a
  case 0:
Packit 06404a
    /* no mapping */
Packit 06404a
    break;
Packit 06404a
  case 1:case 2:
Packit 06404a
    /* implicitly populated value mapping */
Packit 06404a
    /* explicitly populated value mapping */
Packit 06404a
Packit 06404a
    if(!c->quantlist){
Packit 06404a
      /* no quantlist?  error */
Packit 06404a
      return(-1);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* values that define the dequantization */
Packit 06404a
    oggpack_write(opb,c->q_min,32);
Packit 06404a
    oggpack_write(opb,c->q_delta,32);
Packit 06404a
    oggpack_write(opb,c->q_quant-1,4);
Packit 06404a
    oggpack_write(opb,c->q_sequencep,1);
Packit 06404a
Packit 06404a
    {
Packit 06404a
      int quantvals;
Packit 06404a
      switch(c->maptype){
Packit 06404a
      case 1:
Packit 06404a
        /* a single column of (c->entries/c->dim) quantized values for
Packit 06404a
           building a full value list algorithmically (square lattice) */
Packit 06404a
        quantvals=_book_maptype1_quantvals(c);
Packit 06404a
        break;
Packit 06404a
      case 2:
Packit 06404a
        /* every value (c->entries*c->dim total) specified explicitly */
Packit 06404a
        quantvals=c->entries*c->dim;
Packit 06404a
        break;
Packit 06404a
      default: /* NOT_REACHABLE */
Packit 06404a
        quantvals=-1;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* quantized values */
Packit 06404a
      for(i=0;i
Packit 06404a
        oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
Packit 06404a
Packit 06404a
    }
Packit 06404a
    break;
Packit 06404a
  default:
Packit 06404a
    /* error case; we don't have any other map types now */
Packit 06404a
    return(-1);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* unpacks a codebook from the packet buffer into the codebook struct,
Packit 06404a
   readies the codebook auxiliary structures for decode *************/
Packit 06404a
static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
Packit 06404a
  long i,j;
Packit 06404a
  static_codebook *s=_ogg_calloc(1,sizeof(*s));
Packit 06404a
  s->allocedp=1;
Packit 06404a
Packit 06404a
  /* make sure alignment is correct */
Packit 06404a
  if(oggpack_read(opb,24)!=0x564342)goto _eofout;
Packit 06404a
Packit 06404a
  /* first the basic parameters */
Packit 06404a
  s->dim=oggpack_read(opb,16);
Packit 06404a
  s->entries=oggpack_read(opb,24);
Packit 06404a
  if(s->entries==-1)goto _eofout;
Packit 06404a
Packit 06404a
  if(ov_ilog(s->dim)+ov_ilog(s->entries)>24)goto _eofout;
Packit 06404a
Packit 06404a
  /* codeword ordering.... length ordered or unordered? */
Packit 06404a
  switch((int)oggpack_read(opb,1)){
Packit 06404a
  case 0:{
Packit 06404a
    long unused;
Packit 06404a
    /* allocated but unused entries? */
Packit 06404a
    unused=oggpack_read(opb,1);
Packit 06404a
    if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
Packit 06404a
      goto _eofout;
Packit 06404a
    /* unordered */
Packit 06404a
    s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
Packit 06404a
Packit 06404a
    /* allocated but unused entries? */
Packit 06404a
    if(unused){
Packit 06404a
      /* yes, unused entries */
Packit 06404a
Packit 06404a
      for(i=0;i<s->entries;i++){
Packit 06404a
        if(oggpack_read(opb,1)){
Packit 06404a
          long num=oggpack_read(opb,5);
Packit 06404a
          if(num==-1)goto _eofout;
Packit 06404a
          s->lengthlist[i]=num+1;
Packit 06404a
        }else
Packit 06404a
          s->lengthlist[i]=0;
Packit 06404a
      }
Packit 06404a
    }else{
Packit 06404a
      /* all entries used; no tagging */
Packit 06404a
      for(i=0;i<s->entries;i++){
Packit 06404a
        long num=oggpack_read(opb,5);
Packit 06404a
        if(num==-1)goto _eofout;
Packit 06404a
        s->lengthlist[i]=num+1;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
Packit 06404a
    break;
Packit 06404a
  }
Packit 06404a
  case 1:
Packit 06404a
    /* ordered */
Packit 06404a
    {
Packit 06404a
      long length=oggpack_read(opb,5)+1;
Packit 06404a
      if(length==0)goto _eofout;
Packit 06404a
      s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
Packit 06404a
Packit 06404a
      for(i=0;i<s->entries;){
Packit 06404a
        long num=oggpack_read(opb,ov_ilog(s->entries-i));
Packit 06404a
        if(num==-1)goto _eofout;
Packit 06404a
        if(length>32 || num>s->entries-i ||
Packit 06404a
           (num>0 && (num-1)>>(length-1)>1)){
Packit 06404a
          goto _errout;
Packit 06404a
        }
Packit 06404a
        if(length>32)goto _errout;
Packit 06404a
        for(j=0;j
Packit 06404a
          s->lengthlist[i]=length;
Packit 06404a
        length++;
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
    break;
Packit 06404a
  default:
Packit 06404a
    /* EOF */
Packit 06404a
    goto _eofout;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* Do we have a mapping to unpack? */
Packit 06404a
  switch((s->maptype=oggpack_read(opb,4))){
Packit 06404a
  case 0:
Packit 06404a
    /* no mapping */
Packit 06404a
    break;
Packit 06404a
  case 1: case 2:
Packit 06404a
    /* implicitly populated value mapping */
Packit 06404a
    /* explicitly populated value mapping */
Packit 06404a
Packit 06404a
    s->q_min=oggpack_read(opb,32);
Packit 06404a
    s->q_delta=oggpack_read(opb,32);
Packit 06404a
    s->q_quant=oggpack_read(opb,4)+1;
Packit 06404a
    s->q_sequencep=oggpack_read(opb,1);
Packit 06404a
    if(s->q_sequencep==-1)goto _eofout;
Packit 06404a
Packit 06404a
    {
Packit 06404a
      int quantvals=0;
Packit 06404a
      switch(s->maptype){
Packit 06404a
      case 1:
Packit 06404a
        quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
Packit 06404a
        break;
Packit 06404a
      case 2:
Packit 06404a
        quantvals=s->entries*s->dim;
Packit 06404a
        break;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* quantized values */
Packit 06404a
      if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb))
Packit 06404a
        goto _eofout;
Packit 06404a
      s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
Packit 06404a
      for(i=0;i
Packit 06404a
        s->quantlist[i]=oggpack_read(opb,s->q_quant);
Packit 06404a
Packit 06404a
      if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
Packit 06404a
    }
Packit 06404a
    break;
Packit 06404a
  default:
Packit 06404a
    goto _errout;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* all set */
Packit 06404a
  return(s);
Packit 06404a
Packit 06404a
 _errout:
Packit 06404a
 _eofout:
Packit 06404a
  vorbis_staticbook_destroy(s);
Packit 06404a
  return(NULL);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* returns the number of bits ************************************************/
Packit 06404a
int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
Packit 06404a
  if(a<0 || a>=book->c->entries)return(0);
Packit 06404a
  oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
Packit 06404a
  return(book->c->lengthlist[a]);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* the 'eliminate the decode tree' optimization actually requires the
Packit 06404a
   codewords to be MSb first, not LSb.  This is an annoying inelegancy
Packit 06404a
   (and one of the first places where carefully thought out design
Packit 06404a
   turned out to be wrong; Vorbis II and future Ogg codecs should go
Packit 06404a
   to an MSb bitpacker), but not actually the huge hit it appears to
Packit 06404a
   be.  The first-stage decode table catches most words so that
Packit 06404a
   bitreverse is not in the main execution path. */
Packit 06404a
Packit 06404a
static ogg_uint32_t bitreverse(ogg_uint32_t x){
Packit 06404a
  x=    ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
Packit 06404a
  x=    ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
Packit 06404a
  x=    ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
Packit 06404a
  x=    ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
Packit 06404a
  return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
Packit 06404a
}
Packit 06404a
Packit 06404a
STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
Packit 06404a
  int  read=book->dec_maxlength;
Packit 06404a
  long lo,hi;
Packit 06404a
  long lok = oggpack_look(b,book->dec_firsttablen);
Packit 06404a
Packit 06404a
  if (lok >= 0) {
Packit 06404a
    long entry = book->dec_firsttable[lok];
Packit 06404a
    if(entry&0x80000000UL){
Packit 06404a
      lo=(entry>>15)&0x7fff;
Packit 06404a
      hi=book->used_entries-(entry&0x7fff);
Packit 06404a
    }else{
Packit 06404a
      oggpack_adv(b, book->dec_codelengths[entry-1]);
Packit 06404a
      return(entry-1);
Packit 06404a
    }
Packit 06404a
  }else{
Packit 06404a
    lo=0;
Packit 06404a
    hi=book->used_entries;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* Single entry codebooks use a firsttablen of 1 and a
Packit 06404a
     dec_maxlength of 1.  If a single-entry codebook gets here (due to
Packit 06404a
     failure to read one bit above), the next look attempt will also
Packit 06404a
     fail and we'll correctly kick out instead of trying to walk the
Packit 06404a
     underformed tree */
Packit 06404a
Packit 06404a
  lok = oggpack_look(b, read);
Packit 06404a
Packit 06404a
  while(lok<0 && read>1)
Packit 06404a
    lok = oggpack_look(b, --read);
Packit 06404a
  if(lok<0)return -1;
Packit 06404a
Packit 06404a
  /* bisect search for the codeword in the ordered list */
Packit 06404a
  {
Packit 06404a
    ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
Packit 06404a
Packit 06404a
    while(hi-lo>1){
Packit 06404a
      long p=(hi-lo)>>1;
Packit 06404a
      long test=book->codelist[lo+p]>testword;
Packit 06404a
      lo+=p&(test-1);
Packit 06404a
      hi-=p&(-test);
Packit 06404a
      }
Packit 06404a
Packit 06404a
    if(book->dec_codelengths[lo]<=read){
Packit 06404a
      oggpack_adv(b, book->dec_codelengths[lo]);
Packit 06404a
      return(lo);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  oggpack_adv(b, read);
Packit 06404a
Packit 06404a
  return(-1);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* Decode side is specced and easier, because we don't need to find
Packit 06404a
   matches using different criteria; we simply read and map.  There are
Packit 06404a
   two things we need to do 'depending':
Packit 06404a
Packit 06404a
   We may need to support interleave.  We don't really, but it's
Packit 06404a
   convenient to do it here rather than rebuild the vector later.
Packit 06404a
Packit 06404a
   Cascades may be additive or multiplicitive; this is not inherent in
Packit 06404a
   the codebook, but set in the code using the codebook.  Like
Packit 06404a
   interleaving, it's easiest to do it here.
Packit 06404a
   addmul==0 -> declarative (set the value)
Packit 06404a
   addmul==1 -> additive
Packit 06404a
   addmul==2 -> multiplicitive */
Packit 06404a
Packit 06404a
/* returns the [original, not compacted] entry number or -1 on eof *********/
Packit 06404a
long vorbis_book_decode(codebook *book, oggpack_buffer *b){
Packit 06404a
  if(book->used_entries>0){
Packit 06404a
    long packed_entry=decode_packed_entry_number(book,b);
Packit 06404a
    if(packed_entry>=0)
Packit 06404a
      return(book->dec_index[packed_entry]);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* if there's no dec_index, the codebook unpacking isn't collapsed */
Packit 06404a
  return(-1);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* returns 0 on OK or -1 on eof *************************************/
Packit 06404a
/* decode vector / dim granularity gaurding is done in the upper layer */
Packit 06404a
long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
Packit 06404a
  if(book->used_entries>0){
Packit 06404a
    int step=n/book->dim;
Packit 06404a
    long *entry = alloca(sizeof(*entry)*step);
Packit 06404a
    float **t = alloca(sizeof(*t)*step);
Packit 06404a
    int i,j,o;
Packit 06404a
Packit 06404a
    for (i = 0; i < step; i++) {
Packit 06404a
      entry[i]=decode_packed_entry_number(book,b);
Packit 06404a
      if(entry[i]==-1)return(-1);
Packit 06404a
      t[i] = book->valuelist+entry[i]*book->dim;
Packit 06404a
    }
Packit 06404a
    for(i=0,o=0;i<book->dim;i++,o+=step)
Packit 06404a
      for (j=0;j
Packit 06404a
        a[o+j]+=t[j][i];
Packit 06404a
  }
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* decode vector / dim granularity gaurding is done in the upper layer */
Packit 06404a
long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
Packit 06404a
  if(book->used_entries>0){
Packit 06404a
    int i,j,entry;
Packit 06404a
    float *t;
Packit 06404a
Packit 06404a
    if(book->dim>8){
Packit 06404a
      for(i=0;i
Packit 06404a
        entry = decode_packed_entry_number(book,b);
Packit 06404a
        if(entry==-1)return(-1);
Packit 06404a
        t     = book->valuelist+entry*book->dim;
Packit 06404a
        for (j=0;j<book->dim;)
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
      }
Packit 06404a
    }else{
Packit 06404a
      for(i=0;i
Packit 06404a
        entry = decode_packed_entry_number(book,b);
Packit 06404a
        if(entry==-1)return(-1);
Packit 06404a
        t     = book->valuelist+entry*book->dim;
Packit 06404a
        j=0;
Packit 06404a
        switch((int)book->dim){
Packit 06404a
        case 8:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 7:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 6:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 5:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 4:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 3:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 2:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 1:
Packit 06404a
          a[i++]+=t[j++];
Packit 06404a
        case 0:
Packit 06404a
          break;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
/* unlike the others, we guard against n not being an integer number
Packit 06404a
   of <dim> internally rather than in the upper layer (called only by
Packit 06404a
   floor0) */
Packit 06404a
long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
Packit 06404a
  if(book->used_entries>0){
Packit 06404a
    int i,j,entry;
Packit 06404a
    float *t;
Packit 06404a
Packit 06404a
    for(i=0;i
Packit 06404a
      entry = decode_packed_entry_number(book,b);
Packit 06404a
      if(entry==-1)return(-1);
Packit 06404a
      t     = book->valuelist+entry*book->dim;
Packit 06404a
      for (j=0;i<n && j<book->dim;){
Packit 06404a
        a[i++]=t[j++];
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }else{
Packit 06404a
    int i;
Packit 06404a
Packit 06404a
    for(i=0;i
Packit 06404a
      a[i++]=0.f;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  return(0);
Packit 06404a
}
Packit 06404a
Packit 06404a
long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
Packit 06404a
                              oggpack_buffer *b,int n){
Packit 06404a
Packit 06404a
  long i,j,entry;
Packit 06404a
  int chptr=0;
Packit 06404a
  if(book->used_entries>0){
Packit 06404a
    for(i=offset/ch;i<(offset+n)/ch;){
Packit 06404a
      entry = decode_packed_entry_number(book,b);
Packit 06404a
      if(entry==-1)return(-1);
Packit 06404a
      {
Packit 06404a
        const float *t = book->valuelist+entry*book->dim;
Packit 06404a
        for (j=0;j<book->dim;j++){
Packit 06404a
          a[chptr++][i]+=t[j];
Packit 06404a
          if(chptr==ch){
Packit 06404a
            chptr=0;
Packit 06404a
            i++;
Packit 06404a
          }
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  return(0);
Packit 06404a
}