Minor optimization to align p and q indexes in .vqh files.
[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.10 2000/02/07 19:39:45 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   static_codebook c;
78   codebook b;
79   quant_meta q;
80
81   long *quantlist=NULL;
82   int entries=-1,dim=-1,aux=-1;
83   FILE *out=NULL;
84   FILE *in=NULL;
85   char *line,*name;
86   long i,j,k;
87
88   b.c=&c;
89
90   if(argv[1]==NULL){
91     fprintf(stderr,"Need a trained data set on the command line.\n");
92     exit(1);
93   }
94
95   {
96     char *ptr;
97     char *filename=strdup(argv[1]);
98
99     in=fopen(filename,"r");
100     if(!in){
101       fprintf(stderr,"Could not open input file %s\n",filename);
102       exit(1);
103     }
104     
105     ptr=strrchr(filename,'-');
106     if(ptr){
107       *ptr='\0';
108       name=strdup(filename);
109       sprintf(ptr,".vqh");
110     }else{
111       name=strdup(filename);
112       strcat(filename,".vqh");
113     }
114
115     out=fopen(filename,"w");
116     if(out==NULL){
117       fprintf(stderr,"Unable to open %s for writing\n",filename);
118       exit(1);
119     }
120   }
121
122   /* suck in the trained book */
123
124   /* read book type, but it doesn't matter */
125   line=rline(in,out);
126   
127   line=rline(in,out);
128   if(sscanf(line,"%d %d %d",&entries,&dim,&aux)!=3){
129     fprintf(stderr,"Syntax error reading book file\n");
130     exit(1);
131   }
132   
133   /* just use it to allocate mem */
134   vqgen_init(&v,dim,0,entries,NULL,NULL);
135   
136   /* quant */
137   line=rline(in,out);
138   if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta,
139             &q.quant,&q.sequencep)!=4){
140     fprintf(stderr,"Syntax error reading book file\n");
141     exit(1);
142   }
143   
144   /* quantized entries */
145   /* save quant data; we don't want to requantize later as our method
146      is currently imperfect wrt repeated application */
147   i=0;
148   quantlist=malloc(sizeof(long)*v.elements*v.entries);
149   for(j=0;j<entries;j++){
150     double a;
151     for(k=0;k<dim;k++){
152       line=rline(in,out);
153       sscanf(line,"%lf",&a);
154       v.entrylist[i]=a;
155       quantlist[i++]=rint(a);
156     }
157   }    
158   
159   /* ignore bias */
160   for(j=0;j<entries;j++)line=rline(in,out);
161   free(v.bias);
162   v.bias=NULL;
163   
164   /* training points */
165   {
166     double *b=alloca(sizeof(double)*(dim+aux));
167     i=0;
168     v.entries=0; /* hack to avoid reseeding */
169     while(1){
170       for(k=0;k<dim+aux;k++){
171         line=rline(in,out);
172         if(!line)break;
173         sscanf(line,"%lf",b+k);
174       }
175       if(feof(in))break;
176       vqgen_addpoint(&v,b,NULL);
177     }
178     v.entries=entries;
179   }
180   
181   fclose(in);
182   vqgen_unquantize(&v,&q);
183
184   /* build the book */
185   vqsp_book(&v,&b,quantlist);
186
187   /* save the book in C header form */
188   fprintf(out,
189  "/********************************************************************\n"
190  " *                                                                  *\n"
191  " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *\n"
192  " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
193  " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *\n"
194  " * PLEASE READ THESE TERMS DISTRIBUTING.                            *\n"
195  " *                                                                  *\n"
196  " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *\n"
197  " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *\n"
198  " * http://www.xiph.org/                                             *\n"
199  " *                                                                  *\n"
200  " ********************************************************************\n"
201  "\n"
202  " function: static codebook autogenerated by vq/vqbuild\n"
203  "\n"
204  " ********************************************************************/\n\n");
205
206   fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
207   fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
208
209   /* first, the static vectors, then the book structure to tie it together. */
210   /* quantlist */
211   fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
212   i=0;
213   for(j=0;j<entries;j++){
214     fprintf(out,"\t");
215     for(k=0;k<dim;k++)
216       fprintf(out,"%5ld, ",c.quantlist[i++]);
217     fprintf(out,"\n");
218   }
219   fprintf(out,"};\n\n");
220
221   /* lengthlist */
222   fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
223   for(j=0;j<entries;){
224     fprintf(out,"\t");
225     for(k=0;k<16 && j<entries;k++,j++)
226       fprintf(out,"%2ld,",c.lengthlist[j]);
227     fprintf(out,"\n");
228   }
229   fprintf(out,"};\n\n");
230
231   /* ptr0 */
232   fprintf(out,"static long _vq_ptr0_%s[] = {\n",name);
233   for(j=0;j<c.encode_tree->aux;){
234     fprintf(out,"\t");
235     for(k=0;k<8 && j<c.encode_tree->aux;k++,j++)
236       fprintf(out,"%6ld,",c.encode_tree->ptr0[j]);
237     fprintf(out,"\n");
238   }
239   fprintf(out,"};\n\n");
240
241   /* ptr1 */
242   fprintf(out,"static long _vq_ptr1_%s[] = {\n",name);
243   for(j=0;j<c.encode_tree->aux;){
244     fprintf(out,"\t");
245     for(k=0;k<8 && j<c.encode_tree->aux;k++,j++)
246       fprintf(out,"%6ld,",c.encode_tree->ptr1[j]);
247     fprintf(out,"\n");
248   }
249   fprintf(out,"};\n\n");
250
251   /* p */
252   fprintf(out,"static long _vq_p_%s[] = {\n",name);
253   for(j=0;j<c.encode_tree->aux;){
254     fprintf(out,"\t");
255     for(k=0;k<8 && j<c.encode_tree->aux;k++,j++)
256       fprintf(out,"%6ld,",c.encode_tree->p[j]*c.elements);
257     fprintf(out,"\n");
258   }
259   fprintf(out,"};\n\n");
260
261   /* q */
262   fprintf(out,"static long _vq_q_%s[] = {\n",name);
263   for(j=0;j<c.encode_tree->aux;){
264     fprintf(out,"\t");
265     for(k=0;k<8 && j<c.encode_tree->aux;k++,j++)
266       fprintf(out,"%6ld,",c.encode_tree->q[j]*c.elements);
267     fprintf(out,"\n");
268   }
269   fprintf(out,"};\n\n");
270
271   /* tie it all together */
272
273   fprintf(out,"static encode_aux _vq_aux_%s = {\n",name);
274   fprintf(out,"\t_vq_ptr0_%s,\n",name);
275   fprintf(out,"\t_vq_ptr1_%s,\n",name);
276   fprintf(out,"\t_vq_p_%s,\n",name);
277   fprintf(out,"\t_vq_q_%s,\n",name);
278   fprintf(out,"\t%ld, %ld\n};\n\n",c.encode_tree->aux,c.encode_tree->aux);
279
280   fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
281   fprintf(out,"\t%ld, %ld, %ld, %ld, %d, %d,\n",
282           c.dim,c.entries,q.min,q.delta,q.quant,q.sequencep);
283   fprintf(out,"\t_vq_quantlist_%s,\n",name);
284   fprintf(out,"\t_vq_lengthlist_%s,\n",name);
285   fprintf(out,"\t&_vq_aux_%s,\n",name);
286   fprintf(out,"};\n\n");
287
288   fprintf(out,"\n#endif\n");
289   fclose(out);
290   exit(0);
291 }