1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: utility main for training codebooks
14 last mod: $Id: train.c,v 1.23 2001/02/26 03:51:12 xiphmont Exp $
16 ********************************************************************/
28 static char *rline(FILE *in,FILE *out,int pass){
30 char *line=get_line(in);
31 if(line && line[0]=='#'){
32 if(pass)fprintf(out,"%s\n",line);
40 trainvq vqfile [options] trainfile [trainfile]
42 options: -params entries,dim,quant
43 -subvector start[,num]
45 -iterations iterations
48 static void usage(void){
49 fprintf(stderr, "\nOggVorbis %s VQ codebook trainer\n\n"
50 "<foo>vqtrain vqfile [options] [datasetfile] [datasetfile]\n"
51 "options: -p[arams] <entries,dim,quant>\n"
52 " -s[ubvector] <start[,num]>\n"
53 " -e[rror] <desired_error>\n"
54 " -i[terations] <maxiterations>\n"
55 " -d[istance] quantization mesh spacing for density limitation\n"
56 " -b <dummy> eliminate cell size biasing; use normal LBG\n\n"
57 " -c <dummy> Use centroid (not median) midpoints\n"
60 " train a new codebook to 1%% tolerance on datafile 'foo':\n"
61 " xxxvqtrain book -p 256,6,8 -e .01 foo\n"
62 " (produces a trained set in book-0.vqi)\n\n"
63 " continue training 'book-0.vqi' (produces book-1.vqi):\n"
64 " xxxvqtrain book-0.vqi\n\n"
65 " add subvector from element 1 to <dimension> from files\n"
66 " data*.m to the training in progress, prodicing book-1.vqi:\n"
67 " xxxvqtrain book-0.vqi -s 1,1 data*.m\n\n",vqext_booktype);
71 void setexit(int dummy){
72 fprintf(stderr,"\nexiting... please wait to finish this iteration\n");
76 int main(int argc,char *argv[]){
79 int entries=-1,dim=-1;
81 float desired=.05f,mindist=0.f;
98 /* get the book name, a preexisting book to continue training */
101 char *filename=alloca(strlen(*argv)+30),*ptr;
103 strcpy(filename,*argv);
104 in=fopen(filename,"r");
105 ptr=strrchr(filename,'-');
110 sprintf(ptr,"%d.vqi",num+1);
112 strcat(filename,"-0.vqi");
114 out=fopen(filename,"w");
116 fprintf(stderr,"Unable to open %s for writing\n",filename);
121 /* we wish to suck in a preexisting book and continue to train it */
124 line=rline(in,out,1);
125 if(strcmp(line,vqext_booktype)){
126 fprintf(stderr,"wrong book type; %s!=%s\n",line,vqext_booktype);
130 line=rline(in,out,1);
131 if(sscanf(line,"%d %d %d",&entries,&dim,&vqext_aux)!=3){
132 fprintf(stderr,"Syntax error reading book file\n");
136 vqgen_init(&v,dim,vqext_aux,entries,mindist,
137 vqext_metric,vqext_weight,centroid);
141 line=rline(in,out,1);
142 if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta,
143 &q.quant,&q.sequencep)!=4){
144 fprintf(stderr,"Syntax error reading book file\n");
148 /* quantized entries */
150 for(j=0;j<entries;j++){
152 line=rline(in,out,0);
153 sscanf(line,"%f",&a);
157 vqgen_unquantize(&v,&q);
161 for(j=0;j<entries;j++){
162 line=rline(in,out,0);
163 sscanf(line,"%f",&a);
169 float *b=alloca((dim+vqext_aux)*sizeof(float));
172 for(k=0;k<dim+vqext_aux;k++){
173 line=rline(in,out,0);
175 sscanf(line,"%f",b+k);
178 vqgen_addpoint(&v,b,b+dim);
186 /* get the rest... */
192 fprintf(stderr,"Option %s missing argument.\n",argv[0]);
197 if(sscanf(argv[1],"%d,%d,%d",&entries,&dim,&q.quant)!=3)
201 if(sscanf(argv[1],"%d,%d",&start,&num)!=2){
203 if(sscanf(argv[1],"%d",&start)!=1)
208 if(sscanf(argv[1],"%f",&desired)!=1)
212 if(sscanf(argv[1],"%f",&mindist)!=1)
214 if(init)v.mindist=mindist;
217 if(sscanf(argv[1],"%d",&iter)!=1)
227 fprintf(stderr,"Unknown option %s\n",argv[0]);
232 /* it's an input file */
233 char *file=strdup(*argv++);
238 if(dim==-1 || entries==-1 || q.quant==-1){
239 fprintf(stderr,"-p required when training a new set\n");
242 vqgen_init(&v,dim,vqext_aux,entries,mindist,
243 vqext_metric,vqext_weight,centroid);
249 fprintf(stderr,"Could not open input file %s\n",file);
252 fprintf(out,"# training file entry: %s\n",file);
254 while((line=rline(in,out,0))){
257 while(*temp==' ')temp++;
258 for(cols=0;*temp;cols++){
259 while(*temp>32)temp++;
260 while(*temp==' ')temp++;
263 fprintf(stderr,"%d colums per line in file %s\n",cols,file);
269 if(start+num*dim>cols){
270 fprintf(stderr,"ran out of columns reading %s\n",file);
273 while(*line==' ')line++;
276 /* static length buffer bug workaround */
279 while(*temp>32)temp++;
286 while(*line>32)line++;
287 while(*line==' ')line++;
289 if(num<=0)num=(cols-start)/dim;
291 vqext_addpoint_adj(&v,b,start+i*dim,dim,cols,num);
300 fprintf(stderr,"No input files!\n");
304 vqext_preprocess(&v);
307 signal(SIGTERM,setexit);
308 signal(SIGINT,setexit);
310 for(i=0;i<iter && !exiting;i++){
313 vqgen_unquantize(&v,&q);
314 vqgen_cellmetric(&v);
316 result=vqgen_iterate(&v,biasp);
317 vqext_quantize(&v,&q);
318 if(result<desired)break;
323 fprintf(out,"# OggVorbis VQ codebook trainer, intermediate file\n");
324 fprintf(out,"%s\n",vqext_booktype);
325 fprintf(out,"%d %d %d\n",entries,dim,vqext_aux);
326 fprintf(out,"%ld %ld %d %d\n",
327 q.min,q.delta,q.quant,q.sequencep);
329 /* quantized entries */
330 fprintf(out,"# quantized entries---\n");
332 for(j=0;j<entries;j++)
334 fprintf(out,"%d\n",(int)(rint(v.entrylist[i++])));
336 fprintf(out,"# biases---\n");
338 for(j=0;j<entries;j++)
339 fprintf(out,"%f\n",v.bias[i++]);
341 /* we may have done the density limiting mesh trick; refetch the
342 training points from the temp file */
344 rewind(v.asciipoints);
345 fprintf(out,"# points---\n");
347 /* sloppy, no error handling */
350 while((bytes=fread(buff,1,4096,v.asciipoints)))
351 while(bytes)bytes-=fwrite(buff,1,bytes,out);
355 fclose(v.asciipoints);
357 vqgen_unquantize(&v,&q);
358 vqgen_cellmetric(&v);
362 fprintf(stderr,"Syntax error in argument '%s'\n",*argv);