Blame vq/latticebuild.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-2001             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: utility main for building codebooks from lattice descriptions
Packit 06404a
 last mod: $Id: latticebuild.c 16037 2009-05-26 21:10:58Z xiphmont $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <stdio.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <errno.h>
Packit 06404a
#include "bookutil.h"
Packit 06404a
Packit 06404a
/* The purpose of this util is just to finish packaging the
Packit 06404a
   description into a static codebook.  It used to count hits for a
Packit 06404a
   histogram, but I've divorced that out to add some flexibility (it
Packit 06404a
   currently generates an equal probability codebook) 
Packit 06404a
Packit 06404a
   command line:
Packit 06404a
   latticebuild description.vql
Packit 06404a
Packit 06404a
   the lattice description file contains two lines:
Packit 06404a
Packit 06404a
   <n> <dim> <multiplicitavep> <sequentialp>
Packit 06404a
   <value_0> <value_1> <value_2> ... <value_n-1>
Packit 06404a
   
Packit 06404a
   a threshmap (or pigeonmap) struct is generated by latticehint;
Packit 06404a
   there are fun tricks one can do with the threshmap and cascades,
Packit 06404a
   but the utils don't know them...
Packit 06404a
Packit 06404a
   entropy encoding is done by feeding an entry list collected from a
Packit 06404a
   training set and feeding it to latticetune along with the book.
Packit 06404a
Packit 06404a
   latticebuild produces a codebook on stdout */
Packit 06404a
Packit 06404a
static int ilog(unsigned int v){
Packit 06404a
  int ret=0;
Packit 06404a
  while(v){
Packit 06404a
    ret++;
Packit 06404a
    v>>=1;
Packit 06404a
  }
Packit 06404a
  return(ret);
Packit 06404a
}
Packit 06404a
Packit 06404a
int main(int argc,char *argv[]){
Packit 06404a
  codebook b;
Packit 06404a
  static_codebook c;
Packit 06404a
  double *quantlist;
Packit 06404a
  long *hits;
Packit 06404a
Packit 06404a
  int entries=-1,dim=-1,quantvals=-1,addmul=-1,sequencep=0;
Packit 06404a
  FILE *in=NULL;
Packit 06404a
  char *line,*name;
Packit 06404a
  long i,j;
Packit 06404a
Packit 06404a
  memset(&b,0,sizeof(b));
Packit 06404a
  memset(&c,0,sizeof(c));
Packit 06404a
Packit 06404a
  if(argv[1]==NULL){
Packit 06404a
    fprintf(stderr,"Need a lattice description file on the command line.\n");
Packit 06404a
    exit(1);
Packit 06404a
  }
Packit 06404a
Packit 06404a
  {
Packit 06404a
    char *ptr;
Packit 06404a
    char *filename=_ogg_calloc(strlen(argv[1])+4,1);
Packit 06404a
Packit 06404a
    strcpy(filename,argv[1]);
Packit 06404a
    in=fopen(filename,"r");
Packit 06404a
    if(!in){
Packit 06404a
      fprintf(stderr,"Could not open input file %s\n",filename);
Packit 06404a
      exit(1);
Packit 06404a
    }
Packit 06404a
    
Packit 06404a
    ptr=strrchr(filename,'.');
Packit 06404a
    if(ptr){
Packit 06404a
      *ptr='\0';
Packit 06404a
      name=strdup(filename);
Packit 06404a
    }else{
Packit 06404a
      name=strdup(filename);
Packit 06404a
    }
Packit 06404a
Packit 06404a
  }
Packit 06404a
  
Packit 06404a
  /* read the description */
Packit 06404a
  line=get_line(in);
Packit 06404a
  if(sscanf(line,"%d %d %d %d",&quantvals,&dim,&addmul,&sequencep)!=4){
Packit 06404a
    if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
Packit 06404a
      fprintf(stderr,"Syntax error reading description file (line 1)\n");
Packit 06404a
      exit(1);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
  entries=pow(quantvals,dim);
Packit 06404a
  c.dim=dim;
Packit 06404a
  c.entries=entries;
Packit 06404a
  c.lengthlist=_ogg_malloc(entries*sizeof(long));
Packit 06404a
  c.maptype=1;
Packit 06404a
  c.q_sequencep=sequencep;
Packit 06404a
  c.quantlist=_ogg_calloc(quantvals,sizeof(long));
Packit 06404a
Packit 06404a
  quantlist=_ogg_malloc(sizeof(double)*c.dim*c.entries);
Packit 06404a
  hits=_ogg_malloc(c.entries*sizeof(long));
Packit 06404a
  for(j=0;j
Packit 06404a
  for(j=0;j
Packit 06404a
Packit 06404a
  reset_next_value();
Packit 06404a
  line=setup_line(in);
Packit 06404a
  for(j=0;j
Packit 06404a
    char *temp;
Packit 06404a
    if(!line || sscanf(line,"%lf",quantlist+j)!=1){
Packit 06404a
      fprintf(stderr,"Ran out of data on line 2 of description file\n");
Packit 06404a
      exit(1);
Packit 06404a
    }
Packit 06404a
    temp=strchr(line,',');
Packit 06404a
    if(!temp)temp=strchr(line,' ');
Packit 06404a
    if(temp)temp++;
Packit 06404a
    line=temp;
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* gen a real quant list from the more easily human-grokked input */
Packit 06404a
  {
Packit 06404a
    double min=quantlist[0];
Packit 06404a
    double mindel=-1;
Packit 06404a
    int fac=1;
Packit 06404a
    for(j=1;j
Packit 06404a
    for(j=0;j
Packit 06404a
      for(i=j+1;i
Packit 06404a
        if(mindel==-1 || fabs(quantlist[j]-quantlist[i])
Packit 06404a
          mindel=fabs(quantlist[j]-quantlist[i]);
Packit 06404a
Packit 06404a
    j=0;
Packit 06404a
    while(j
Packit 06404a
      for(j=0;j
Packit 06404a
        double test=fac*(quantlist[j]-min)/mindel;
Packit 06404a
        if( fabs(rint(test)-test)>.00001f) break;
Packit 06404a
      }
Packit 06404a
      if(fac>100)break;
Packit 06404a
      if(j
Packit 06404a
    }
Packit 06404a
Packit 06404a
    mindel/=fac;
Packit 06404a
    fprintf(stderr,"min=%g mindel=%g\n",min,mindel);
Packit 06404a
Packit 06404a
    c.q_min=_float32_pack(min);
Packit 06404a
    c.q_delta=_float32_pack(mindel);
Packit 06404a
    c.q_quant=0;
Packit 06404a
Packit 06404a
    min=_float32_unpack(c.q_min);
Packit 06404a
    mindel=_float32_unpack(c.q_delta);
Packit 06404a
    for(j=0;j
Packit 06404a
      c.quantlist[j]=rint((quantlist[j]-min)/mindel);
Packit 06404a
      if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]);
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* build the [default] codeword lengths */
Packit 06404a
  memset(c.lengthlist,0,sizeof(long)*entries);
Packit 06404a
  for(i=0;i
Packit 06404a
  build_tree_from_lengths(entries,hits,c.lengthlist);
Packit 06404a
Packit 06404a
  /* save the book in C header form */
Packit 06404a
  write_codebook(stdout,name,&c);
Packit 06404a
  fprintf(stderr,"\r                                                     "
Packit 06404a
          "\nDone.\n");
Packit 06404a
  exit(0);
Packit 06404a
}