Merging the postbeta2 branch onto the mainline.
[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-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.15 2000/10/12 03:13:01 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 "vorbis/codebook.h"
25 #include "../lib/sharedbook.h"
26 #include "bookutil.h"
27
28 #include "vqgen.h"
29 #include "vqsplit.h"
30
31 static char *linebuffer=NULL;
32 static int  lbufsize=0;
33 static char *rline(FILE *in,FILE *out){
34   long sofar=0;
35   if(feof(in))return NULL;
36
37   while(1){
38     int gotline=0;
39
40     while(!gotline){
41       if(sofar>=lbufsize){
42         if(!lbufsize){  
43           lbufsize=1024;
44           linebuffer=malloc(lbufsize);
45         }else{
46           lbufsize*=2;
47           linebuffer=realloc(linebuffer,lbufsize);
48         }
49       }
50       {
51         long c=fgetc(in);
52         switch(c){
53         case '\n':
54         case EOF:
55           gotline=1;
56           break;
57         default:
58           linebuffer[sofar++]=c;
59           linebuffer[sofar]='\0';
60           break;
61         }
62       }
63     }
64     
65     if(linebuffer[0]=='#'){
66       sofar=0;
67     }else{
68       return(linebuffer);
69     }
70   }
71 }
72
73 /* command line:
74    buildvq file
75 */
76
77 int main(int argc,char *argv[]){
78   vqgen v;
79   static_codebook c;
80   codebook b;
81   quant_meta q;
82
83   long *quantlist=NULL;
84   int entries=-1,dim=-1,aux=-1;
85   FILE *out=NULL;
86   FILE *in=NULL;
87   char *line,*name;
88   long i,j,k;
89
90   b.c=&c;
91
92   if(argv[1]==NULL){
93     fprintf(stderr,"Need a trained data set on the command line.\n");
94     exit(1);
95   }
96
97   {
98     char *ptr;
99     char *filename=strdup(argv[1]);
100
101     in=fopen(filename,"r");
102     if(!in){
103       fprintf(stderr,"Could not open input file %s\n",filename);
104       exit(1);
105     }
106     
107     ptr=strrchr(filename,'-');
108     if(ptr){
109       *ptr='\0';
110       name=strdup(filename);
111       sprintf(ptr,".vqh");
112     }else{
113       name=strdup(filename);
114       strcat(filename,".vqh");
115     }
116
117     out=fopen(filename,"w");
118     if(out==NULL){
119       fprintf(stderr,"Unable to open %s for writing\n",filename);
120       exit(1);
121     }
122   }
123
124   /* suck in the trained book */
125
126   /* read book type, but it doesn't matter */
127   line=rline(in,out);
128   
129   line=rline(in,out);
130   if(sscanf(line,"%d %d %d",&entries,&dim,&aux)!=3){
131     fprintf(stderr,"Syntax error reading book file\n");
132     exit(1);
133   }
134   
135   /* just use it to allocate mem */
136   vqgen_init(&v,dim,0,entries,0.,NULL,NULL,0);
137   
138   /* quant */
139   line=rline(in,out);
140   if(sscanf(line,"%ld %ld %d %d",&q.min,&q.delta,
141             &q.quant,&q.sequencep)!=4){
142     fprintf(stderr,"Syntax error reading book file\n");
143     exit(1);
144   }
145   
146   /* quantized entries */
147   /* save quant data; we don't want to requantize later as our method
148      is currently imperfect wrt repeated application */
149   i=0;
150   quantlist=malloc(sizeof(long)*v.elements*v.entries);
151   for(j=0;j<entries;j++){
152     float a;
153     for(k=0;k<dim;k++){
154       line=rline(in,out);
155       sscanf(line,"%lf",&a);
156       v.entrylist[i]=a;
157       quantlist[i++]=rint(a);
158     }
159   }    
160   
161   /* ignore bias */
162   for(j=0;j<entries;j++)line=rline(in,out);
163   free(v.bias);
164   v.bias=NULL;
165   
166   /* training points */
167   {
168     float *b=alloca(sizeof(float)*(dim+aux));
169     i=0;
170     v.entries=0; /* hack to avoid reseeding */
171     while(1){
172       for(k=0;k<dim+aux;k++){
173         line=rline(in,out);
174         if(!line)break;
175         sscanf(line,"%lf",b+k);
176       }
177       if(feof(in))break;
178       vqgen_addpoint(&v,b,NULL);
179     }
180     v.entries=entries;
181   }
182   
183   fclose(in);
184   vqgen_unquantize(&v,&q);
185
186   /* build the book */
187   vqsp_book(&v,&b,quantlist);
188   c.q_min=q.min;
189   c.q_delta=q.delta;
190   c.q_quant=q.quant;
191   c.q_sequencep=q.sequencep;
192
193   /* save the book in C header form */
194   write_codebook(out,name,b.c);
195
196   fclose(out);
197   exit(0);
198 }