Fixes for codebook geenration (keeping up to date)
[platform/upstream/libvorbis.git] / vq / build.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH    *
6  * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.        *
7  *                                                                  *
8  * THE OggVorbis 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.17 2000/11/08 03:23:23 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 "bookutil.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=_ogg_malloc(lbufsize);
43         }else{
44           lbufsize*=2;
45           linebuffer=_ogg_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,0.,NULL,NULL,0);
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=_ogg_malloc(sizeof(long)*v.elements*v.entries);
149   for(j=0;j<entries;j++){
150     float a;
151     for(k=0;k<dim;k++){
152       line=rline(in,out);
153       sscanf(line,"%f",&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     float *b=alloca(sizeof(float)*(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,"%f",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   c.q_min=q.min;
187   c.q_delta=q.delta;
188   c.q_quant=q.quant;
189   c.q_sequencep=q.sequencep;
190
191   /* save the book in C header form */
192   write_codebook(out,name,b.c);
193
194   fclose(out);
195   exit(0);
196 }