18e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/********************************************************************
28e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
38e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
48e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
58e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
68e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
78e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
88e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
98e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * by the Xiph.Org Foundation http://www.xiph.org/                  *
108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************
128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels function: utility functions for loading .vqh and .vqd files
148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels last mod: $Id: bookutil.c 16959 2010-03-10 16:03:11Z xiphmont $
158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************/
178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdlib.h>
198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdio.h>
208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <math.h>
218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <string.h>
228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <errno.h>
238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "bookutil.h"
248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint _best(codebook *book, float *a, int step){
268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int dim=book->dim;
288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j,o;
298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int minval=book->minval;
308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int del=book->delta;
318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int qv=book->quantvals;
328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int ze=(qv>>1);
338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int index=0;
348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(del!=1){
378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0,o=step*(dim-1);i<dim;i++,o-=step){
388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int v = ((int)rint(a[o])-minval+(del>>1))/del;
398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }else{
438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0,o=step*(dim-1);i<dim;i++,o-=step){
448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int v = (int)rint(a[o])-minval;
458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(book->c->lengthlist[index]<=0){
518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    const static_codebook *c=book->c;
528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int best=-1;
538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int e[8]={0,0,0,0,0,0,0,0};
558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int maxval = book->minval + book->delta*(book->quantvals-1);
568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0;i<book->entries;i++){
578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(c->lengthlist[i]>0){
588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        float this=0;
598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        for(j=0;j<dim;j++){
608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          float val=(e[j]-a[j*step]);
618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          this+=val*val;
628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(best==-1 || this<best){
648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          best=this;
658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          index=i;
668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* assumes the value patterning created by the tools in vq/ */
698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      j=0;
708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      while(e[j]>=maxval)
718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        e[j++]=0;
728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(e[j]>=0)
738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        e[j]+=book->delta;
748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      e[j]= -e[j];
758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return index;
798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* A few little utils for reading files */
828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* read a line.  Use global, persistent buffering */
838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic char *linebuffer=NULL;
848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic int  lbufsize=0;
858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelschar *get_line(FILE *in){
868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long sofar=0;
878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(feof(in))return NULL;
888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(1){
908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int gotline=0;
918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    while(!gotline){
938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(sofar+1>=lbufsize){
948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(!lbufsize){
958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          lbufsize=1024;
968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          linebuffer=_ogg_malloc(lbufsize);
978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }else{
988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          lbufsize*=2;
998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          linebuffer=_ogg_realloc(linebuffer,lbufsize);
1008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
1018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      {
1038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        long c=fgetc(in);
1048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        switch(c){
1058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        case EOF:
1068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(sofar==0)return(NULL);
1078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          /* fallthrough correct */
1088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        case '\n':
1098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          linebuffer[sofar]='\0';
1108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          gotline=1;
1118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          break;
1128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        default:
1138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          linebuffer[sofar++]=c;
1148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          linebuffer[sofar]='\0';
1158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          break;
1168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
1178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(linebuffer[0]=='#'){
1218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      sofar=0;
1228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else{
1238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      return(linebuffer);
1248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
1268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* read the next numerical value from the given file */
1298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic char *value_line_buff=NULL;
1308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint get_line_value(FILE *in,float *value){
1328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  char *next;
1338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(!value_line_buff)return(-1);
1358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  *value=strtod(value_line_buff, &next);
1378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(next==value_line_buff){
1388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    value_line_buff=NULL;
1398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    return(-1);
1408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }else{
1418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    value_line_buff=next;
1428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    while(*value_line_buff>44)value_line_buff++;
1438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(*value_line_buff==44)value_line_buff++;
1448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    return(0);
1458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
1468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint get_next_value(FILE *in,float *value){
1498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(1){
1508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(get_line_value(in,value)){
1518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      value_line_buff=get_line(in);
1528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(!value_line_buff)return(-1);
1538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else{
1548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      return(0);
1558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
1578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint get_next_ivalue(FILE *in,long *ivalue){
1608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  float value;
1618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int ret=get_next_value(in,&value);
1628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  *ivalue=value;
1638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(ret);
1648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic float sequence_base=0.f;
1678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsstatic int v_sofar=0;
1688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid reset_next_value(void){
1698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  value_line_buff=NULL;
1708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  sequence_base=0.f;
1718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  v_sofar=0;
1728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelschar *setup_line(FILE *in){
1758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  reset_next_value();
1768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  value_line_buff=get_line(in);
1778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(value_line_buff);
1788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint get_vector(codebook *b,FILE *in,int start, int n,float *a){
1828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
1838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  const static_codebook *c=b->c;
1848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(1){
1868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(v_sofar==n || get_line_value(in,a)){
1888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      reset_next_value();
1898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(get_next_value(in,a))
1908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        break;
1918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(i=0;i<start;i++){
1928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        sequence_base=*a;
1938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        get_line_value(in,a);
1948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=1;i<c->dim;i++)
1988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(get_line_value(in,a+i))
1998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        break;
2008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(i==c->dim){
2028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      float temp=a[c->dim-1];
2038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(i=0;i<c->dim;i++)a[i]-=sequence_base;
2048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(c->q_sequencep)sequence_base=temp;
2058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      v_sofar++;
2068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      return(0);
2078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
2088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    sequence_base=0.f;
2098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(-1);
2128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
2138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* read lines fromt he beginning until we find one containing the
2158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   specified string */
2168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelschar *find_seek_to(FILE *in,char *s){
2178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  rewind(in);
2188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(1){
2198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    char *line=get_line(in);
2208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(line){
2218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(strstr(line,s))
2228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        return(line);
2238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else
2248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      return(NULL);
2258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
2278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* this reads the format as written by vqbuild/latticebuild; innocent
2308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   (legal) tweaking of the file that would not affect its valid
2318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   header-ness will break this routine */
2328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelscodebook *codebook_load(char *filename){
2348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  codebook *b=_ogg_calloc(1,sizeof(codebook));
2358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook)));
2368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int quant_to_read=0;
2378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  FILE *in=fopen(filename,"r");
2388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  char *line;
2398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long i;
2408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(in==NULL){
2428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(stderr,"Couldn't open codebook %s\n",filename);
2438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    exit(1);
2448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* find the codebook struct */
2478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  find_seek_to(in,"static const static_codebook ");
2488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* get the major important values */
2508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  line=get_line(in);
2518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(sscanf(line,"%ld, %ld,",
2528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            &(c->dim),&(c->entries))!=2){
2538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
2548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    exit(1);
2558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  line=get_line(in);
2578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  line=get_line(in);
2588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(sscanf(line,"%d, %ld, %ld, %d, %d,",
2598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant),
2608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            &(c->q_sequencep))!=5){
2618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
2628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    exit(1);
2638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  switch(c->maptype){
2668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  case 0:
2678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    quant_to_read=0;
2688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    break;
2698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  case 1:
2708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    quant_to_read=_book_maptype1_quantvals(c);
2718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    break;
2728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  case 2:
2738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    quant_to_read=c->entries*c->dim;
2748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    break;
2758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
2768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* load the quantized entries */
2788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  find_seek_to(in,"static const long _vq_quantlist_");
2798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  reset_next_value();
2808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read);
2818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<quant_to_read;i++)
2828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(get_next_ivalue(in,c->quantlist+i)){
2838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"out of data while reading codebook %s\n",filename);
2848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
2858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
2868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* load the lengthlist */
2888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  find_seek_to(in,"_lengthlist");
2898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  reset_next_value();
2908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  c->lengthlist=_ogg_malloc(sizeof(long)*c->entries);
2918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<c->entries;i++)
2928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(get_next_ivalue(in,c->lengthlist+i)){
2938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"out of data while reading codebook %s\n",filename);
2948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
2958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
2968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* got it all */
2988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fclose(in);
2998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_book_init_encode(b,c);
3018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  b->valuelist=_book_unquantize(c,c->entries,NULL);
3028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(b);
3048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid spinnit(char *s,int n){
3078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  static int p=0;
3088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  static long lasttime=0;
3098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long test;
3108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  struct timeval thistime;
3118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  gettimeofday(&thistime,NULL);
3138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  test=thistime.tv_sec*10+thistime.tv_usec/100000;
3148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(lasttime!=test){
3158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    lasttime=test;
3168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(stderr,"%s%d ",s,n);
3188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    p++;if(p>3)p=0;
3208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    switch(p){
3218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    case 0:
3228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"|    \r");
3238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      break;
3248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    case 1:
3258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"/    \r");
3268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      break;
3278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    case 2:
3288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"-    \r");
3298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      break;
3308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    case 3:
3318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"\\    \r");
3328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      break;
3338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fflush(stderr);
3358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid build_tree_from_lengths(int vals, long *hist, long *lengths){
3398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j;
3408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long *membership=_ogg_malloc(vals*sizeof(long));
3418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long *histsave=alloca(vals*sizeof(long));
3428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  memcpy(histsave,hist,vals*sizeof(long));
3438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<vals;i++)membership[i]=i;
3458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* find codeword lengths */
3478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* much more elegant means exist.  Brute force n^2, minimum thought */
3488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=vals;i>1;i--){
3498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int first=-1,second=-1;
3508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long least=-1;
3518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    spinnit("building... ",i);
3538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* find the two nodes to join */
3558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<vals;j++)
3568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(least==-1 || hist[j]<=least){
3578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        least=hist[j];
3588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        first=membership[j];
3598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    least=-1;
3618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<vals;j++)
3628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if((least==-1 || hist[j]<=least) && membership[j]!=first){
3638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        least=hist[j];
3648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        second=membership[j];
3658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(first==-1 || second==-1){
3678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"huffman fault; no free branch\n");
3688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
3698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* join them */
3728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    least=hist[first]+hist[second];
3738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<vals;j++)
3748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(membership[j]==first || membership[j]==second){
3758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        membership[j]=first;
3768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        hist[j]=least;
3778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        lengths[j]++;
3788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
3798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<vals-1;i++)
3818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(membership[i]!=membership[i+1]){
3828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"huffman fault; failed to build single tree\n");
3838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
3848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* for sanity check purposes: how many bits would it have taken to
3878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     encode the training set? */
3888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
3898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long bitsum=0;
3908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long samples=0;
3918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0;i<vals;i++){
3928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      bitsum+=(histsave[i]-1)*lengths[i];
3938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      samples+=histsave[i]-1;
3948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(samples){
3978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"\rTotal samples in training set: %ld      \n",samples);
3988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"\rTotal bits used to represent training set: %ld\n",
3998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              bitsum);
4008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  free(membership);
4048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
4058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* wrap build_tree_from_lengths to allow zero entries in the histogram */
4078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid build_tree_from_lengths0(int vals, long *hist, long *lengths){
4088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* pack the 'sparse' hit list into a dense list, then unpack
4108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     the lengths after the build */
4118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int upper=0,i;
4138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long *lengthlist=_ogg_calloc(vals,sizeof(long));
4148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  long *newhist=alloca(vals*sizeof(long));
4158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<vals;i++)
4178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(hist[i]>0)
4188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      newhist[upper++]=hist[i];
4198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(upper != vals){
4218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n",
4228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            vals-upper,upper);
4238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  build_tree_from_lengths(upper,newhist,lengthlist);
4268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  upper=0;
4288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<vals;i++)
4298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(hist[i]>0)
4308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      lengths[i]=lengthlist[upper++];
4318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    else
4328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      lengths[i]=0;
4338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  free(lengthlist);
4358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
4368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid write_codebook(FILE *out,char *name,const static_codebook *c){
4388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j,k;
4398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* save the book in C header form */
4418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* first, the static vectors, then the book structure to tie it together. */
4438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* quantlist */
4448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(c->quantlist){
4458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim);
4468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"static const long _vq_quantlist_%s[] = {\n",name);
4478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<vals;j++){
4488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(out,"\t%ld,\n",c->quantlist[j]);
4498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
4508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"};\n\n");
4518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* lengthlist */
4548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"static const long _vq_lengthlist_%s[] = {\n",name);
4558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(j=0;j<c->entries;){
4568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"\t");
4578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(k=0;k<16 && j<c->entries;k++,j++)
4588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(out,"%2ld,",c->lengthlist[j]);
4598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"\n");
4608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"};\n\n");
4628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* tie it all together */
4648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"static const static_codebook %s = {\n",name);
4668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
4688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"\t(long *)_vq_lengthlist_%s,\n",name);
4698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"\t%d, %ld, %ld, %d, %d,\n",
4708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep);
4718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(c->quantlist)
4728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"\t(long *)_vq_quantlist_%s,\n",name);
4738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  else
4748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    fprintf(out,"\tNULL,\n");
4758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(out,"\t0\n};\n\n");
4778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
478