1 /********************************************************************
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. *
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/ *
12 ********************************************************************
14 function: utility main for training codebooks
15 author: Monty <xiphmont@mit.edu>
16 modifications by: Monty
17 last modification date: Dec 15 1999
19 ********************************************************************/
30 static char *linebuffer=NULL;
31 static int lbufsize=0;
32 static char *rline(FILE *in,FILE *out,int pass){
34 if(feof(in))return NULL;
40 if(sofar+1>=lbufsize){
43 linebuffer=malloc(lbufsize);
46 linebuffer=realloc(linebuffer,lbufsize);
57 linebuffer[sofar++]=c;
58 linebuffer[sofar]='\0';
64 if(linebuffer[0]=='#'){
65 if(pass)fprintf(out,"%s",linebuffer);
74 trainvq vqfile [options] trainfile [trainfile]
76 options: -params entries,dim,quant
77 -subvector start[,num]
79 -iterations iterations
82 static void usage(void){
83 fprintf(stderr, "\nOggVorbis %s VQ codebook trainer\n\n"
84 "<foo>vqtrain vqfile [options] [datasetfile] [datasetfile]\n"
85 "options: -p[arams] <entries,dim,quant>\n"
86 " -s[ubvector] <start[,num]>\n"
87 " -e[rror] <desired_error>\n"
88 " -i[terations] <maxiterations>\n\n"
90 " train a new codebook to 1%% tolerance on datafile 'foo':\n"
91 " xxxvqtrain book -p 256,6,8 -e .01 foo\n"
92 " (produces a trained set in book-0.vqi)\n\n"
93 " continue training 'book-0.vqi' (produces book-1.vqi):\n"
94 " xxxvqtrain book-0.vqi\n\n"
95 " add subvector from element 1 to <dimension> from files\n"
96 " data*.m to the training in progress, prodicing book-1.vqi:\n"
97 " xxxvqtrain book-0.vqi -s 1,1 data*.m\n\n",vqext_booktype);
101 void setexit(int dummy){
102 fprintf(stderr,"\nexiting... please wait to finish this iteration\n");
106 int main(int argc,char *argv[]){
110 int entries=-1,dim=-1,quant=-1;
126 /* get the book name, a preexisting book to continue training */
129 char *filename=alloca(strlen(*argv)+30),*ptr;
131 strcpy(filename,*argv);
132 in=fopen(filename,"r");
133 ptr=strrchr(filename,'-');
138 sprintf(ptr,"%d.vqi",num+1);
140 strcat(filename,"-0.vqi");
142 out=fopen(filename,"w");
144 fprintf(stderr,"Unable to open %s for writing\n",filename);
149 /* we wish to suck in a preexisting book and continue to train it */
152 line=rline(in,out,1);
153 if(strcmp(line,vqext_booktype)){
154 fprintf(stderr,"wrong book type; %s!=%s\n",line,vqext_booktype);
158 line=rline(in,out,1);
159 if(sscanf(line,"%d %d",&entries,&dim)!=2){
160 fprintf(stderr,"Syntax error reading book file\n");
164 vqgen_init(&v,dim,entries,vqext_metric);
168 line=rline(in,out,1);
169 if(sscanf(line,"%lf %lf %d %d",&q.minval,&q.delt,
170 &q.addtoquant,&quant)!=4){
171 fprintf(stderr,"Syntax error reading book file\n");
175 /* quantized entries */
176 for(j=0;j<entries;j++)
178 line=rline(in,out,0);
180 /* unquantized entries */
182 for(j=0;j<entries;j++){
184 line=rline(in,out,0);
185 sscanf(line,"%lf",&a);
192 for(j=0;j<entries;j++){
193 line=rline(in,out,0);
194 sscanf(line,"%lf",&a);
201 v.entries=0; /* hack to avoid reseeding */
203 for(k=0;k<dim && k<80;k++){
204 line=rline(in,out,0);
206 sscanf(line,"%lf",b+k);
209 vqgen_addpoint(&v,b);
218 /* get the rest... */
224 fprintf(stderr,"Option %s missing argument.\n",argv[0]);
229 if(sscanf(argv[1],"%d,%d,%d",&entries,&dim,&quant)!=3)
233 if(sscanf(argv[1],"%d,%d",&start,&num)!=2){
235 if(sscanf(argv[1],"%d",&start)!=1)
240 if(sscanf(argv[1],"%lf",&desired)!=1)
244 if(sscanf(argv[1],"%d",&iter)!=1)
248 fprintf(stderr,"Unknown option %s\n",argv[0]);
253 /* it's an input file */
254 char *file=strdup(*argv++);
259 if(dim==-1 || entries==-1 || quant==-1){
260 fprintf(stderr,"-p required when training a new set\n");
263 vqgen_init(&v,dim,entries,vqext_metric);
269 fprintf(stderr,"Could not open input file %s\n",file);
272 fprintf(out,"# training file entry: %s\n",file);
274 while((line=rline(in,out,0))){
277 while(*temp==' ')temp++;
278 for(cols=0;*temp;cols++){
279 while(*temp>32)temp++;
280 while(*temp==' ')temp++;
285 double *b=malloc(cols*sizeof(double));
286 if(start*num+dim>cols){
287 fprintf(stderr,"ran out of columns reading %s\n",file);
290 while(*line==' ')line++;
293 /* static length buffer bug workaround */
296 while(*temp>32)temp++;
303 while(*line>32)line++;
304 while(*line==' ')line++;
306 if(num<=0)num=(cols-start)/dim;
308 vqext_adjdata(b,start+i*dim,dim);
309 vqgen_addpoint(&v,b+start+i*dim);
319 fprintf(stderr,"No input files!\n");
324 signal(SIGTERM,setexit);
325 signal(SIGINT,setexit);
327 for(i=0;i<iter && !exiting;i++){
329 if(i!=0)vqext_unquantize(&v,&q);
330 result=vqgen_iterate(&v);
331 q=vqext_quantize(&v,quant);
332 if(result<desired)break;
337 fprintf(out,"# OggVorbis VQ codebook trainer, intermediate file\n");
338 fprintf(out,"%s\n",vqext_booktype);
339 fprintf(out,"%d %d\n",entries,dim);
340 fprintf(out,"%g %g %d %d\n",q.minval,q.delt,q.addtoquant,quant);
342 /* quantized entries */
343 fprintf(out,"# quantized entries---\n");
345 for(j=0;j<entries;j++)
347 fprintf(out,"%d\n",(int)(rint(v.entrylist[i++])));
350 vqext_unquantize(&v,&q);
352 fprintf(out,"# unquantized entries---\n");
354 for(j=0;j<entries;j++)
356 fprintf(out,"%f\n",v.entrylist[i++]);
358 /* unquantized entries */
360 fprintf(out,"# biases---\n");
362 for(j=0;j<entries;j++)
363 fprintf(out,"%f\n",v.bias[i++]);
365 fprintf(out,"# points---\n");
367 for(j=0;j<v.points;j++)
368 for(k=0;k<dim && k<80;k++)
369 fprintf(out,"%f\n",v.pointlist[i++]);
375 fprintf(stderr,"Syntax error in argument '%s'\n",*argv);