Home | History | Annotate | Download | only in vq
      1 /********************************************************************
      2  *                                                                  *
      3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
      4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
      5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
      6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
      7  *                                                                  *
      8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
      9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
     10  *                                                                  *
     11  ********************************************************************
     12 
     13  function: utility main for building codebooks from lattice descriptions
     14  last mod: $Id: latticebuild.c 16037 2009-05-26 21:10:58Z xiphmont $
     15 
     16  ********************************************************************/
     17 
     18 #include <stdlib.h>
     19 #include <stdio.h>
     20 #include <math.h>
     21 #include <string.h>
     22 #include <errno.h>
     23 #include "bookutil.h"
     24 
     25 /* The purpose of this util is just to finish packaging the
     26    description into a static codebook.  It used to count hits for a
     27    histogram, but I've divorced that out to add some flexibility (it
     28    currently generates an equal probability codebook)
     29 
     30    command line:
     31    latticebuild description.vql
     32 
     33    the lattice description file contains two lines:
     34 
     35    <n> <dim> <multiplicitavep> <sequentialp>
     36    <value_0> <value_1> <value_2> ... <value_n-1>
     37 
     38    a threshmap (or pigeonmap) struct is generated by latticehint;
     39    there are fun tricks one can do with the threshmap and cascades,
     40    but the utils don't know them...
     41 
     42    entropy encoding is done by feeding an entry list collected from a
     43    training set and feeding it to latticetune along with the book.
     44 
     45    latticebuild produces a codebook on stdout */
     46 
     47 static int ilog(unsigned int v){
     48   int ret=0;
     49   while(v){
     50     ret++;
     51     v>>=1;
     52   }
     53   return(ret);
     54 }
     55 
     56 int main(int argc,char *argv[]){
     57   codebook b;
     58   static_codebook c;
     59   double *quantlist;
     60   long *hits;
     61 
     62   int entries=-1,dim=-1,quantvals=-1,addmul=-1,sequencep=0;
     63   FILE *in=NULL;
     64   char *line,*name;
     65   long i,j;
     66 
     67   memset(&b,0,sizeof(b));
     68   memset(&c,0,sizeof(c));
     69 
     70   if(argv[1]==NULL){
     71     fprintf(stderr,"Need a lattice description file on the command line.\n");
     72     exit(1);
     73   }
     74 
     75   {
     76     char *ptr;
     77     char *filename=_ogg_calloc(strlen(argv[1])+4,1);
     78 
     79     strcpy(filename,argv[1]);
     80     in=fopen(filename,"r");
     81     if(!in){
     82       fprintf(stderr,"Could not open input file %s\n",filename);
     83       exit(1);
     84     }
     85 
     86     ptr=strrchr(filename,'.');
     87     if(ptr){
     88       *ptr='\0';
     89       name=strdup(filename);
     90     }else{
     91       name=strdup(filename);
     92     }
     93 
     94   }
     95 
     96   /* read the description */
     97   line=get_line(in);
     98   if(sscanf(line,"%d %d %d %d",&quantvals,&dim,&addmul,&sequencep)!=4){
     99     if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
    100       fprintf(stderr,"Syntax error reading description file (line 1)\n");
    101       exit(1);
    102     }
    103   }
    104   entries=pow(quantvals,dim);
    105   c.dim=dim;
    106   c.entries=entries;
    107   c.lengthlist=_ogg_malloc(entries*sizeof(long));
    108   c.maptype=1;
    109   c.q_sequencep=sequencep;
    110   c.quantlist=_ogg_calloc(quantvals,sizeof(long));
    111 
    112   quantlist=_ogg_malloc(sizeof(double)*c.dim*c.entries);
    113   hits=_ogg_malloc(c.entries*sizeof(long));
    114   for(j=0;j<entries;j++)hits[j]=1;
    115   for(j=0;j<entries;j++)c.lengthlist[j]=1;
    116 
    117   reset_next_value();
    118   line=setup_line(in);
    119   for(j=0;j<quantvals;j++){
    120     char *temp;
    121     if(!line || sscanf(line,"%lf",quantlist+j)!=1){
    122       fprintf(stderr,"Ran out of data on line 2 of description file\n");
    123       exit(1);
    124     }
    125     temp=strchr(line,',');
    126     if(!temp)temp=strchr(line,' ');
    127     if(temp)temp++;
    128     line=temp;
    129   }
    130 
    131   /* gen a real quant list from the more easily human-grokked input */
    132   {
    133     double min=quantlist[0];
    134     double mindel=-1;
    135     int fac=1;
    136     for(j=1;j<quantvals;j++)if(quantlist[j]<min)min=quantlist[j];
    137     for(j=0;j<quantvals;j++)
    138       for(i=j+1;i<quantvals;i++)
    139         if(mindel==-1 || fabs(quantlist[j]-quantlist[i])<mindel)
    140           mindel=fabs(quantlist[j]-quantlist[i]);
    141 
    142     j=0;
    143     while(j<quantvals){
    144       for(j=0;j<quantvals;j++){
    145         double test=fac*(quantlist[j]-min)/mindel;
    146         if( fabs(rint(test)-test)>.00001f) break;
    147       }
    148       if(fac>100)break;
    149       if(j<quantvals)fac++;
    150     }
    151 
    152     mindel/=fac;
    153     fprintf(stderr,"min=%g mindel=%g\n",min,mindel);
    154 
    155     c.q_min=_float32_pack(min);
    156     c.q_delta=_float32_pack(mindel);
    157     c.q_quant=0;
    158 
    159     min=_float32_unpack(c.q_min);
    160     mindel=_float32_unpack(c.q_delta);
    161     for(j=0;j<quantvals;j++){
    162       c.quantlist[j]=rint((quantlist[j]-min)/mindel);
    163       if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]);
    164     }
    165   }
    166 
    167   /* build the [default] codeword lengths */
    168   memset(c.lengthlist,0,sizeof(long)*entries);
    169   for(i=0;i<entries;i++)hits[i]=1;
    170   build_tree_from_lengths(entries,hits,c.lengthlist);
    171 
    172   /* save the book in C header form */
    173   write_codebook(stdout,name,&c);
    174   fprintf(stderr,"\r                                                     "
    175           "\nDone.\n");
    176   exit(0);
    177 }
    178