quant fix
[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-1999             *
9  * by 1999 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  author: Monty <xiphmont@mit.edu>
16  modifications by: Monty
17  last modification date: Dec 14 1999
18
19  ********************************************************************/
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <signal.h>
27 #include "vqgen.h"
28
29 static int rline(FILE *in,FILE *out,char *line,int max,int pass){
30   while(fgets(line,160,in)){
31     if(line[0]=='#'){
32       if(pass)fprintf(out,"%s",line);
33     }else{
34       return(1);
35     }
36   }
37   return(0);
38 }
39
40 /* command line:
41    buildvq vq=file out=file quant=n
42 */
43
44 int exiting=0;
45 void setexit(int dummy){
46   fprintf(stderr,"\nexiting... please wait to finish this iteration\n");
47   exiting=1;
48 }
49
50 int main(int argc,char *argv[]){
51   vqgen v;
52   int entries=-1,dim=-1;
53   char line[1024];
54   long i,j,k;
55
56   int init=0;
57   while(*argv){
58
59     /* load the trained data */
60     if(!strncmp(*argv,"vq=",3)){
61       FILE *in=NULL;
62       char filename[80],*ptr;
63       if(sscanf(*argv,"vq=%70s",filename)!=1){
64         fprintf(stderr,"Syntax error in argument '%s'\n",*argv);
65         exit(1);
66       }
67
68       in=fopen(filename,"r");
69       ptr=strrchr(filename,'-');
70       if(ptr){
71         int num;
72         ptr++;
73         num=atoi(ptr);
74         sprintf(ptr,"%d.vqi",num+1);
75       }else
76         strcat(filename,"-0.vqi");
77       
78       out=fopen(filename,"w");
79       if(out==NULL){
80         fprintf(stderr,"Unable to open %s for writing\n",filename);
81         exit(1);
82       }
83       fprintf(out,"# OggVorbis VQ codebook trainer, intermediate file\n");
84
85       if(in){
86         /* we wish to suck in a preexisting book and continue to train it */
87         double a;
88             
89         rline(in,out,line,160,1);
90         if(sscanf(line,"%d %d %d",&entries,&dim,&met)!=3){
91           fprintf(stderr,"Syntax error reading book file\n");
92           exit(1);
93         }
94
95         metric=set_metric(met);
96         vqgen_init(&v,dim,entries,metric,0.);
97         init=1;
98
99         /* entries, bias, points */
100         i=0;
101         for(j=0;j<entries;j++){
102           for(k=0;k<dim;k++){
103             rline(in,out,line,160,0);
104             sscanf(line,"%lf",&a);
105             v.entrylist[i++]=a;
106           }
107         }
108
109         i=0;
110         for(j=0;j<entries;j++){
111           rline(in,out,line,160,0);
112           sscanf(line,"%lf",&a);
113           v.bias[i++]=a;
114         }
115
116         {
117           double b[80];
118           i=0;
119           v.entries=0; /* hack to avoid reseeding */
120           while(1){
121             for(k=0;k<dim && k<80;k++){
122               rline(in,out,line,160,0);
123               sscanf(line,"%lf",b+k);
124             }
125             if(feof(in))break;
126             vqgen_addpoint(&v,b);
127           }
128           v.entries=entries;
129         }
130
131         fclose(in);
132       }
133     }
134
135     /* set parameters if we're not loading a pre book */
136     if(!strncmp(*argv,"entries=",8)){
137       sscanf(*argv,"entries=%d",&entries);
138     }
139     if(!strncmp(*argv,"desired=",8)){
140       sscanf(*argv,"desired=%lf",&desired);
141     }
142     if(!strncmp(*argv,"dim=",4)){
143       sscanf(*argv,"dim=%d",&dim);
144     }
145
146     /* which error metric (0==euclidian distance default) */
147     if(!strncmp(*argv,"met=",4)){
148       sscanf(*argv,"met=%d",&met);
149       metric=set_metric(met);
150     }
151
152     if(!strncmp(*argv,"in=",3)){
153       int start;
154       char file[80];
155       FILE *in;
156
157       if(sscanf(*argv,"in=%79[^,],%d",file,&start)!=2)goto syner;
158       if(!out){
159         fprintf(stderr,"vq= must preceed in= arguments\n");
160         exit(1);
161       }
162       if(!init){
163         if(dim==-1 || entries==-1){
164           fprintf(stderr,"Must specify dimensionality and entries before"
165                   " first input file\n");
166           exit(1);
167         }
168         vqgen_init(&v,dim,entries,metric,0.);
169         init=1;
170       }
171
172       in=fopen(file,"r");
173       if(in==NULL){
174         fprintf(stderr,"Could not open input file %s\n",file);
175         exit(1);
176       }
177       fprintf(out,"# training file entry: %s\n",file);
178
179       while(rline(in,out,line,1024,1)){
180         double b[16];
181         int n=sscanf(line,"%lf %lf %lf %lf %lf %lf %lf %lf "
182                      "%lf %lf %lf %lf %lf %lf %lf %lf",
183                      b,b+1,b+2,b+3,b+4,b+5,b+6,b+7,b+8,b+9,b+10,b+11,b+12,b+13,
184                      b+14,b+15);
185         if(start+dim>n){
186           fprintf(stderr,"ran out of columns reading %s\n",file);
187           exit(1);
188         }
189         vqgen_addpoint(&v,b+start);
190       }
191
192       fclose(in);
193     }
194     argv++;
195   }
196
197   /* train the book */
198   signal(SIGTERM,setexit);
199   signal(SIGINT,setexit);
200
201   for(i=0;i<iter && !exiting;i++){
202     if(vqgen_iterate(&v)<desired)break;
203   }
204
205   /* save the book */
206
207   fprintf(out,"%d %d %d\n",entries,dim,met);
208
209   i=0;
210   for(j=0;j<entries;j++)
211     for(k=0;k<dim;k++)
212       fprintf(out,"%f\n",v.entrylist[i++]);
213   
214   fprintf(out,"# biases---\n");
215   i=0;
216   for(j=0;j<entries;j++)
217     fprintf(out,"%f\n",v.bias[i++]);
218
219   fprintf(out,"# points---\n");
220   i=0;
221   for(j=0;j<v.points;j++)
222     for(k=0;k<dim && k<80;k++)
223       fprintf(out,"%f\n",v.pointlist[i++]);
224
225   fclose(out);
226   exit(0);
227
228   syner:
229     fprintf(stderr,"Syntax error in argument '%s'\n",*argv);
230     exit(1);
231 }