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-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: utility main for training codebooks
15 last mod: $Id: train.c,v 1.11 1999/12/30 07:27:02 xiphmont Exp $
17 ********************************************************************/
28 static char *linebuffer=NULL;
29 static int lbufsize=0;
30 static char *rline(FILE *in,FILE *out,int pass){
32 if(feof(in))return NULL;
38 if(sofar+1>=lbufsize){
41 linebuffer=malloc(lbufsize);
44 linebuffer=realloc(linebuffer,lbufsize);
55 linebuffer[sofar++]=c;
56 linebuffer[sofar]='\0';
62 if(linebuffer[0]=='#'){
63 if(pass)fprintf(out,"%s\n",linebuffer);
72 trainvq vqfile [options] trainfile [trainfile]
74 options: -params entries,dim,quant
75 -subvector start[,num]
77 -iterations iterations
80 static void usage(void){
81 fprintf(stderr, "\nOggVorbis %s VQ codebook trainer\n\n"
82 "<foo>vqtrain vqfile [options] [datasetfile] [datasetfile]\n"
83 "options: -p[arams] <entries,dim,quant>\n"
84 " -s[ubvector] <start[,num]>\n"
85 " -e[rror] <desired_error>\n"
86 " -i[terations] <maxiterations>\n\n"
88 " train a new codebook to 1%% tolerance on datafile 'foo':\n"
89 " xxxvqtrain book -p 256,6,8 -e .01 foo\n"
90 " (produces a trained set in book-0.vqi)\n\n"
91 " continue training 'book-0.vqi' (produces book-1.vqi):\n"
92 " xxxvqtrain book-0.vqi\n\n"
93 " add subvector from element 1 to <dimension> from files\n"
94 " data*.m to the training in progress, prodicing book-1.vqi:\n"
95 " xxxvqtrain book-0.vqi -s 1,1 data*.m\n\n",vqext_booktype);
99 void setexit(int dummy){
100 fprintf(stderr,"\nexiting... please wait to finish this iteration\n");
104 int main(int argc,char *argv[]){
107 int entries=-1,dim=-1;
124 /* get the book name, a preexisting book to continue training */
127 char *filename=alloca(strlen(*argv)+30),*ptr;
129 strcpy(filename,*argv);
130 in=fopen(filename,"r");
131 ptr=strrchr(filename,'-');
136 sprintf(ptr,"%d.vqi",num+1);
138 strcat(filename,"-0.vqi");
140 out=fopen(filename,"w");
142 fprintf(stderr,"Unable to open %s for writing\n",filename);
147 /* we wish to suck in a preexisting book and continue to train it */
150 line=rline(in,out,1);
151 if(strcmp(line,vqext_booktype)){
152 fprintf(stderr,"wrong book type; %s!=%s\n",line,vqext_booktype);
156 line=rline(in,out,1);
157 if(sscanf(line,"%d %d %d",&entries,&dim,&vqext_aux)!=3){
158 fprintf(stderr,"Syntax error reading book file\n");
162 vqgen_init(&v,dim,vqext_aux,entries,vqext_metric,vqext_weight);
166 line=rline(in,out,1);
167 if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta,
168 &q.quant,&q.sequencep)!=4){
169 fprintf(stderr,"Syntax error reading book file\n");
173 /* quantized entries */
175 for(j=0;j<entries;j++){
177 line=rline(in,out,0);
178 sscanf(line,"%lf",&a);
182 vqgen_unquantize(&v,&q);
186 for(j=0;j<entries;j++){
187 line=rline(in,out,0);
188 sscanf(line,"%lf",&a);
193 double *b=alloca((dim+vqext_aux)*sizeof(double));
195 v.entries=0; /* hack to avoid reseeding */
197 for(k=0;k<dim+vqext_aux;k++){
198 line=rline(in,out,0);
200 sscanf(line,"%lf",b+k);
203 vqgen_addpoint(&v,b,b+dim);
212 /* get the rest... */
218 fprintf(stderr,"Option %s missing argument.\n",argv[0]);
223 if(sscanf(argv[1],"%d,%d,%d",&entries,&dim,&q.quant)!=3)
227 if(sscanf(argv[1],"%d,%d",&start,&num)!=2){
229 if(sscanf(argv[1],"%d",&start)!=1)
234 if(sscanf(argv[1],"%lf",&desired)!=1)
238 if(sscanf(argv[1],"%d",&iter)!=1)
242 fprintf(stderr,"Unknown option %s\n",argv[0]);
247 /* it's an input file */
248 char *file=strdup(*argv++);
253 if(dim==-1 || entries==-1 || q.quant==-1){
254 fprintf(stderr,"-p required when training a new set\n");
257 vqgen_init(&v,dim,vqext_aux,entries,vqext_metric,vqext_weight);
263 fprintf(stderr,"Could not open input file %s\n",file);
266 fprintf(out,"# training file entry: %s\n",file);
268 while((line=rline(in,out,0))){
271 while(*temp==' ')temp++;
272 for(cols=0;*temp;cols++){
273 while(*temp>32)temp++;
274 while(*temp==' ')temp++;
279 double *b=malloc(cols*sizeof(double));
280 if(start*num+dim>cols){
281 fprintf(stderr,"ran out of columns reading %s\n",file);
284 while(*line==' ')line++;
287 /* static length buffer bug workaround */
290 while(*temp>32)temp++;
297 while(*line>32)line++;
298 while(*line==' ')line++;
300 if(num<=0)num=(cols-start)/dim;
302 vqext_addpoint_adj(&v,b,start+i*dim,dim,cols);
312 fprintf(stderr,"No input files!\n");
316 vqext_preprocess(&v);
319 signal(SIGTERM,setexit);
320 signal(SIGINT,setexit);
322 for(i=0;i<iter && !exiting;i++){
324 if(i!=0)vqgen_unquantize(&v,&q);
325 result=vqgen_iterate(&v);
326 vqgen_quantize(&v,&q);
327 if(result<desired)break;
332 fprintf(out,"# OggVorbis VQ codebook trainer, intermediate file\n");
333 fprintf(out,"%s\n",vqext_booktype);
334 fprintf(out,"%d %d %d\n",entries,dim,vqext_aux);
335 fprintf(out,"%ld %ld %d %d\n",q.min,q.delta,q.quant,q.sequencep);
337 /* quantized entries */
338 fprintf(out,"# quantized entries---\n");
340 for(j=0;j<entries;j++)
342 fprintf(out,"%d\n",(int)(rint(v.entrylist[i++])));
344 fprintf(out,"# biases---\n");
346 for(j=0;j<entries;j++)
347 fprintf(out,"%f\n",v.bias[i++]);
349 fprintf(out,"# points---\n");
351 for(j=0;j<v.points;j++)
352 for(k=0;k<dim+vqext_aux;k++)
353 fprintf(out,"%f\n",v.pointlist[i++]);
359 fprintf(stderr,"Syntax error in argument '%s'\n",*argv);