/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * 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 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: hufftree builder last mod: $Id: huffbuild.c 16959 2010-03-10 16:03:11Z xiphmont $ ********************************************************************/ #include <stdlib.h> #include <string.h> #include <math.h> #include <stdio.h> #include "bookutil.h" static int nsofar=0; static int getval(FILE *in,int begin,int n,int group,int max){ float v; int i; long val=0; if(nsofar>=n || get_line_value(in,&v)){ reset_next_value(); nsofar=0; if(get_next_value(in,&v)) return(-1); for(i=1;i<=begin;i++) get_line_value(in,&v); } val=(int)v; nsofar++; for(i=1;i<group;i++,nsofar++) if(nsofar>=n || get_line_value(in,&v)) return(getval(in,begin,n,group,max)); else val = val*max+(int)v; return(val); } static void usage(){ fprintf(stderr, "usage:\n" "huffbuild <input>.vqd <begin,n,group>|<lorange-hirange> [noguard]\n" " where begin,n,group is first scalar, \n" " number of scalars of each in line,\n" " number of scalars in a group\n" "eg: huffbuild reslongaux.vqd 0,1024,4\n" "produces reslongaux.vqh\n\n"); exit(1); } int main(int argc, char *argv[]){ char *base; char *infile; int i,j,k,begin,n,subn,guard=1; FILE *file; int maxval=0; int loval=0; if(argc<3)usage(); if(argc==4)guard=0; infile=strdup(argv[1]); base=strdup(infile); if(strrchr(base,'.')) strrchr(base,'.')[0]='\0'; { char *pos=strchr(argv[2],','); char *dpos=strchr(argv[2],'-'); if(dpos){ loval=atoi(argv[2]); maxval=atoi(dpos+1); subn=1; begin=0; }else{ begin=atoi(argv[2]); if(!pos) usage(); else n=atoi(pos+1); pos=strchr(pos+1,','); if(!pos) usage(); else subn=atoi(pos+1); if(n/subn*subn != n){ fprintf(stderr,"n must be divisible by group\n"); exit(1); } } } /* scan the file for maximum value */ file=fopen(infile,"r"); if(!file){ fprintf(stderr,"Could not open file %s\n",infile); if(!maxval) exit(1); else fprintf(stderr," making untrained books.\n"); } if(!maxval){ i=0; while(1){ long v; if(get_next_ivalue(file,&v))break; if(v>maxval)maxval=v; if(!(i++&0xff))spinnit("loading... ",i); } rewind(file); maxval++; } { long vals=pow(maxval,subn); long *hist=_ogg_calloc(vals,sizeof(long)); long *lengths=_ogg_calloc(vals,sizeof(long)); for(j=loval;j<vals;j++)hist[j]=guard; if(file){ reset_next_value(); i/=subn; while(!feof(file)){ long val=getval(file,begin,n,subn,maxval); if(val==-1 || val>=vals)break; hist[val]++; if(!(i--&0xff))spinnit("loading... ",i*subn); } fclose(file); } /* we have the probabilities, build the tree */ fprintf(stderr,"Building tree for %ld entries\n",vals); build_tree_from_lengths0(vals,hist,lengths); /* save the book */ { char *buffer=alloca(strlen(base)+5); strcpy(buffer,base); strcat(buffer,".vqh"); file=fopen(buffer,"w"); if(!file){ fprintf(stderr,"Could not open file %s\n",buffer); exit(1); } } /* first, the static vectors, then the book structure to tie it together. */ /* lengthlist */ fprintf(file,"static const long _huff_lengthlist_%s[] = {\n",base); for(j=0;j<vals;){ fprintf(file,"\t"); for(k=0;k<16 && j<vals;k++,j++) fprintf(file,"%2ld,",lengths[j]); fprintf(file,"\n"); } fprintf(file,"};\n\n"); /* the toplevel book */ fprintf(file,"static const static_codebook _huff_book_%s = {\n",base); fprintf(file,"\t%d, %ld,\n",subn,vals); fprintf(file,"\t(long *)_huff_lengthlist_%s,\n",base); fprintf(file,"\t0, 0, 0, 0, 0,\n"); fprintf(file,"\tNULL,\n"); fprintf(file,"\t0\n};\n\n"); fclose(file); fprintf(stderr,"Done. \n\n"); } exit(0); }