The huff builder is happy.
[platform/upstream/libvorbis.git] / vq / huffbuild.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
6  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
9  * by Monty <monty@xiph.org> and The XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: hufftree builder
15  last mod: $Id: huffbuild.c,v 1.1 2000/02/21 01:14:02 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include <stdio.h>
23 #include "../vq/bookutil.h"
24
25 static int nsofar=0;
26 static int getval(FILE *in,int begin,int n,int group,int max){
27   double v;
28   int i;
29   long val=0;
30
31   if(nsofar>=n || get_line_value(in,&v)){
32     reset_next_value();
33     nsofar=0;
34     if(get_next_value(in,&v))
35       return(-1);
36     for(i=1;i<=begin;i++)
37       get_line_value(in,&v);
38   }
39
40   val=(int)v;
41   nsofar++;
42
43   for(i=1;i<group;i++,nsofar++)
44     if(nsofar>=n || get_line_value(in,&v))
45       return(getval(in,begin,n,group,max));
46     else
47       val = val*max+(int)v;
48   return(val);
49 }
50
51 static void usage(){
52   fprintf(stderr,
53           "usage:\n" 
54           "huffbuild <input>.vqd <begin,n,group>\n"
55           "   where begin,n,group is first scalar, \n"
56           "                          number of scalars of each in line,\n"
57           "                          number of scalars in a group\n"
58           "eg: huffbuild reslongaux.vqd 0,1024,4\n"
59           "produces reslongaux.vqh\n\n");
60   exit(1);
61 }
62
63 int main(int argc, char *argv[]){
64   char *base;
65   char *infile;
66   int i,j,k,begin,n,subn;
67   FILE *file;
68   int maxval=0;
69
70   if(argc<3)usage();
71
72   infile=strdup(argv[1]);
73   base=strdup(infile);
74   if(strrchr(base,'.'))
75     strrchr(base,'.')[0]='\0';
76
77   {
78     char *pos=strchr(argv[2],',');
79     begin=atoi(argv[2]);
80     if(!pos)
81       usage();
82     else
83       n=atoi(pos+1);
84     pos=strchr(pos+1,',');
85     if(!pos)
86       usage();
87     else
88       subn=atoi(pos+1);
89     if(n/subn*subn != n){
90       fprintf(stderr,"n must be divisible by group\n");
91       exit(1);
92     }
93   }
94
95   /* scan the file for maximum value */
96   file=fopen(infile,"r");
97   if(!file){
98     fprintf(stderr,"Could not open file %s\n",infile);
99     exit(1);
100   }
101   i=0;
102   while(1){
103     long v;
104     if(get_next_ivalue(file,&v))break;
105     if(v>maxval)maxval=v;
106
107     if(!(i++&0xff))spinnit("loading... ",i);
108   }
109   rewind(file);
110   maxval++;
111
112   {
113     long vals=pow(maxval,subn);
114     long *hist=malloc(vals*sizeof(long));
115     long *lengths=malloc(vals*sizeof(long));
116     
117     for(j=0;j<vals;j++)hist[j]=1;
118     
119     reset_next_value();
120     i/=subn;
121     while(!feof(file)){
122       long val=getval(file,begin,n,subn,maxval);
123       if(val==-1)break;
124       hist[val]++;
125       if(!(i--&0xff))spinnit("loading... ",i*subn);
126     }
127     fclose(file);
128  
129     /* we have the probabilities, build the tree */
130     fprintf(stderr,"Building tree for %ld entries\n",vals);
131     build_tree_from_lengths(vals,hist,lengths);
132  
133     /* save the book */
134     {
135       char *buffer=alloca(strlen(base)+5);
136       strcpy(buffer,base);
137       strcat(buffer,".vqh");
138       file=fopen(buffer,"w");
139       if(!file){
140         fprintf(stderr,"Could not open file %s\n",buffer);
141         exit(1);
142       }
143     }
144     
145     fprintf(file,
146  "/********************************************************************\n"
147  " *                                                                  *\n"
148  " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *\n"
149  " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
150  " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *\n"
151  " * PLEASE READ THESE TERMS DISTRIBUTING.                            *\n"
152  " *                                                                  *\n"
153  " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *\n"
154  " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *\n"
155  " * http://www.xiph.org/                                             *\n"
156  " *                                                                  *\n"
157  " ********************************************************************\n"
158  "\n"
159  " function: static codebook autogenerated by huff/huffbuld\n"
160  "\n"
161  " ********************************************************************/\n\n");
162
163     fprintf(file,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",base,base);
164     fprintf(file,"#include \"vorbis/codebook.h\"\n\n");
165     
166     /* first, the static vectors, then the book structure to tie it together. */
167     /* lengthlist */
168     fprintf(file,"static long _vq_lengthlist_%s[] = {\n",base);
169     for(j=0;j<vals;){
170       fprintf(file,"\t");
171       for(k=0;k<16 && j<vals;k++,j++)
172         fprintf(file,"%2ld,",lengths[j]);
173       fprintf(file,"\n");
174     }
175     fprintf(file,"};\n\n");
176     
177     /* the toplevel book */
178     fprintf(file,"static static_codebook _vq_book_%s = {\n",base);
179     fprintf(file,"\t%d, %ld, %d, %d, %d, %d,\n",
180             subn,vals,0,0,0,0);
181     fprintf(file,"\tNULL,\n");
182     fprintf(file,"\t_vq_lengthlist_%s,\n",base);
183     fprintf(file,"\tNULL,\n");
184     fprintf(file,"};\n\n");
185     
186     fprintf(file,"\n#endif\n");
187     fclose(file);
188     fprintf(stderr,"Done.                                \n\n");
189   }
190   exit(0);
191 }
192
193