Allow cascade and metric utilities to take more than one codebook
[platform/upstream/libvorbis.git] / vq / build.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: utility main for building codebooks from training sets
15  last mod: $Id: build.c,v 1.8 2000/01/05 10:14:54 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <string.h>
23 #include <errno.h>
24 #include "vorbis/codebook.h"
25
26 #include "vqgen.h"
27 #include "vqsplit.h"
28
29 static char *linebuffer=NULL;
30 static int  lbufsize=0;
31 static char *rline(FILE *in,FILE *out){
32   long sofar=0;
33   if(feof(in))return NULL;
34
35   while(1){
36     int gotline=0;
37
38     while(!gotline){
39       if(sofar>=lbufsize){
40         if(!lbufsize){  
41           lbufsize=1024;
42           linebuffer=malloc(lbufsize);
43         }else{
44           lbufsize*=2;
45           linebuffer=realloc(linebuffer,lbufsize);
46         }
47       }
48       {
49         long c=fgetc(in);
50         switch(c){
51         case '\n':
52         case EOF:
53           gotline=1;
54           break;
55         default:
56           linebuffer[sofar++]=c;
57           linebuffer[sofar]='\0';
58           break;
59         }
60       }
61     }
62     
63     if(linebuffer[0]=='#'){
64       sofar=0;
65     }else{
66       return(linebuffer);
67     }
68   }
69 }
70
71 /* command line:
72    buildvq file
73 */
74
75 int main(int argc,char *argv[]){
76   vqgen v;
77   codebook b;
78   quant_meta q;
79
80   long *quantlist=NULL;
81   int entries=-1,dim=-1,aux=-1;
82   FILE *out=NULL;
83   FILE *in=NULL;
84   char *line,*name;
85   long i,j,k;
86
87   if(argv[1]==NULL){
88     fprintf(stderr,"Need a trained data set on the command line.\n");
89     exit(1);
90   }
91
92   {
93     char *ptr;
94     char *filename=strdup(argv[1]);
95
96     in=fopen(filename,"r");
97     if(!in){
98       fprintf(stderr,"Could not open input file %s\n",filename);
99       exit(1);
100     }
101     
102     ptr=strrchr(filename,'-');
103     if(ptr){
104       *ptr='\0';
105       name=strdup(filename);
106       sprintf(ptr,".vqh");
107     }else{
108       name=strdup(filename);
109       strcat(filename,".vqh");
110     }
111
112     out=fopen(filename,"w");
113     if(out==NULL){
114       fprintf(stderr,"Unable to open %s for writing\n",filename);
115       exit(1);
116     }
117   }
118
119   /* suck in the trained book */
120
121   /* read book type, but it doesn't matter */
122   line=rline(in,out);
123   
124   line=rline(in,out);
125   if(sscanf(line,"%d %d %d",&entries,&dim,&aux)!=3){
126     fprintf(stderr,"Syntax error reading book file\n");
127     exit(1);
128   }
129   
130   /* just use it to allocate mem */
131   vqgen_init(&v,dim,0,entries,NULL,NULL);
132   
133   /* quant */
134   line=rline(in,out);
135   if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta,
136             &q.quant,&q.sequencep)!=4){
137     fprintf(stderr,"Syntax error reading book file\n");
138     exit(1);
139   }
140   
141   /* quantized entries */
142   /* save quant data; we don't want to requantize later as our method
143      is currently imperfect wrt repeated application */
144   i=0;
145   quantlist=malloc(sizeof(long)*v.elements*v.entries);
146   for(j=0;j<entries;j++){
147     double a;
148     for(k=0;k<dim;k++){
149       line=rline(in,out);
150       sscanf(line,"%lf",&a);
151       v.entrylist[i]=a;
152       quantlist[i++]=rint(a);
153     }
154   }    
155   
156   /* ignore bias */
157   for(j=0;j<entries;j++)line=rline(in,out);
158   free(v.bias);
159   v.bias=NULL;
160   
161   /* training points */
162   {
163     double *b=alloca(sizeof(double)*(dim+aux));
164     i=0;
165     v.entries=0; /* hack to avoid reseeding */
166     while(1){
167       for(k=0;k<dim+aux;k++){
168         line=rline(in,out);
169         if(!line)break;
170         sscanf(line,"%lf",b+k);
171       }
172       if(feof(in))break;
173       vqgen_addpoint(&v,b,NULL);
174     }
175     v.entries=entries;
176   }
177   
178   fclose(in);
179   vqgen_unquantize(&v,&q);
180
181   /* build the book */
182   vqsp_book(&v,&b,quantlist);
183
184   /* save the book in C header form */
185   fprintf(out,
186  "/********************************************************************\n"
187  " *                                                                  *\n"
188  " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *\n"
189  " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
190  " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *\n"
191  " * PLEASE READ THESE TERMS DISTRIBUTING.                            *\n"
192  " *                                                                  *\n"
193  " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *\n"
194  " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *\n"
195  " * http://www.xiph.org/                                             *\n"
196  " *                                                                  *\n"
197  " ********************************************************************\n"
198  "\n"
199  " function: static codebook autogenerated by vq/vqbuild\n"
200  "\n"
201  " ********************************************************************/\n\n");
202
203   fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
204   fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
205
206   /* first, the static vectors, then the book structure to tie it together. */
207   /* quantlist */
208   fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
209   i=0;
210   for(j=0;j<entries;j++){
211     fprintf(out,"\t");
212     for(k=0;k<dim;k++)
213       fprintf(out,"%5ld, ",b.quantlist[i++]);
214     fprintf(out,"\n");
215   }
216   fprintf(out,"};\n\n");
217
218   /* codelist */
219   fprintf(out,"static long _vq_codelist_%s[] = {\n",name);
220   for(j=0;j<entries;){
221     fprintf(out,"\t");
222     for(k=0;k<8 && j<entries;k++,j++)
223       fprintf(out,"%ld,",b.codelist[j]);
224     fprintf(out,"\n");
225   }
226   fprintf(out,"};\n\n");
227
228   /* lengthlist */
229   fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
230   for(j=0;j<entries;){
231     fprintf(out,"\t");
232     for(k=0;k<16 && j<entries;k++,j++)
233       fprintf(out,"%2ld,",b.lengthlist[j]);
234     fprintf(out,"\n");
235   }
236   fprintf(out,"};\n\n");
237
238   /* ptr0 */
239   fprintf(out,"static long _vq_ptr0_%s[] = {\n",name);
240   for(j=0;j<b.encode_tree->aux;){
241     fprintf(out,"\t");
242     for(k=0;k<8 && j<b.encode_tree->aux;k++,j++)
243       fprintf(out,"%6ld,",b.encode_tree->ptr0[j]);
244     fprintf(out,"\n");
245   }
246   fprintf(out,"};\n\n");
247
248   /* ptr1 */
249   fprintf(out,"static long _vq_ptr1_%s[] = {\n",name);
250   for(j=0;j<b.encode_tree->aux;){
251     fprintf(out,"\t");
252     for(k=0;k<8 && j<b.encode_tree->aux;k++,j++)
253       fprintf(out,"%6ld,",b.encode_tree->ptr1[j]);
254     fprintf(out,"\n");
255   }
256   fprintf(out,"};\n\n");
257
258   /* p */
259   fprintf(out,"static long _vq_p_%s[] = {\n",name);
260   for(j=0;j<b.encode_tree->aux;){
261     fprintf(out,"\t");
262     for(k=0;k<8 && j<b.encode_tree->aux;k++,j++)
263       fprintf(out,"%6ld,",b.encode_tree->p[j]);
264     fprintf(out,"\n");
265   }
266   fprintf(out,"};\n\n");
267
268   /* q */
269   fprintf(out,"static long _vq_q_%s[] = {\n",name);
270   for(j=0;j<b.encode_tree->aux;){
271     fprintf(out,"\t");
272     for(k=0;k<8 && j<b.encode_tree->aux;k++,j++)
273       fprintf(out,"%6ld,",b.encode_tree->q[j]);
274     fprintf(out,"\n");
275   }
276   fprintf(out,"};\n\n");
277
278   /* tie it all together */
279
280   fprintf(out,"static encode_aux _vq_aux_%s = {\n",name);
281   fprintf(out,"\t_vq_ptr0_%s,\n",name);
282   fprintf(out,"\t_vq_ptr1_%s,\n",name);
283   fprintf(out,"\t0,\n");
284   fprintf(out,"\t0,\n");
285   fprintf(out,"\t_vq_p_%s,\n",name);
286   fprintf(out,"\t_vq_q_%s,\n",name);
287   fprintf(out,"\t%ld, %ld\n};\n\n",b.encode_tree->aux,b.encode_tree->aux);
288
289   fprintf(out,"static codebook _vq_book_%s = {\n",name);
290   fprintf(out,"\t%ld, %ld, %ld, %ld, %d, %d,\n",
291           b.dim,b.entries,q.min,q.delta,q.quant,q.sequencep);
292   fprintf(out,"\t0,\n"); /* valuelist */
293   fprintf(out,"\t_vq_quantlist_%s,\n",name);
294   fprintf(out,"\t_vq_codelist_%s,\n",name);
295   fprintf(out,"\t_vq_lengthlist_%s,\n",name);
296   fprintf(out,"\t&_vq_aux_%s,\n",name);
297   fprintf(out,"\t0\n");
298   fprintf(out,"};\n\n");
299
300   fprintf(out,"\n#endif\n");
301   fclose(out);
302   exit(0);
303 }