First merge of new psychoacoustics. Have some unused codebooks to
[platform/upstream/libvorbis.git] / vq / latticebuild.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 lattice descriptions
15  last mod: $Id: latticebuild.c,v 1.2 2000/05/08 20:49:50 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 /* The purpose of this util is actually just to count hits and finish
29    packaging the description into a static codebook.
30
31    command line:
32    vqlattice description.vql datafile.vqd 
33
34    the lattice description file contains five lines:
35
36    <n> <dim> <multiplicitavep>
37    <value_0> <value_1> <value_2> ... <value_n-1>
38    <m>
39    <thresh_0> <thresh_1> <thresh_2> ... <thresh_m-2>
40    <map_0> <map_1> <map_2> ... <map_m-1>
41
42    vqlattice sends residual data (for the next stage) to stdout, and
43    produces description.vqh */
44
45 static int ilog(unsigned int v){
46   int ret=0;
47   while(v){
48     ret++;
49     v>>=1;
50   }
51   return(ret);
52 }
53
54 int main(int argc,char *argv[]){
55   codebook b;
56   static_codebook c;
57   encode_aux_threshmatch t;
58   double *quantlist;
59   long *hits;
60
61   int entries=-1,dim=-1,quantvals=-1,addmul=-1,threshvals=-1;
62   FILE *out=NULL;
63   FILE *in=NULL;
64   char *line,*name;
65   long j,k;
66
67   memset(&b,0,sizeof(b));
68   memset(&c,0,sizeof(c));
69   memset(&t,0,sizeof(t));
70
71   if(argv[1]==NULL){
72     fprintf(stderr,"Need a lattice description file on the command line.\n");
73     exit(1);
74   }
75
76   {
77     char *ptr;
78     char *filename=calloc(strlen(argv[1])+4,1);
79
80     strcpy(filename,argv[1]);
81     in=fopen(filename,"r");
82     if(!in){
83       fprintf(stderr,"Could not open input file %s\n",filename);
84       exit(1);
85     }
86     
87     ptr=strrchr(filename,'.');
88     if(ptr){
89       *ptr='\0';
90       name=strdup(filename);
91       sprintf(ptr,".vqh");
92     }else{
93       name=strdup(filename);
94       strcat(filename,".vqh");
95     }
96
97     out=fopen(filename,"w");
98     if(out==NULL){
99       fprintf(stderr,"Unable to open %s for writing\n",filename);
100       exit(1);
101     }
102   }
103   
104   /* read the description */
105   line=get_line(in);
106   if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
107     fprintf(stderr,"Syntax error reading book file (line 1)\n");
108     exit(1);
109   }
110   entries=pow(quantvals,dim);
111   c.thresh_tree=&t;
112   c.dim=dim;
113   c.entries=entries;
114   c.lengthlist=malloc(entries*sizeof(long));
115   c.maptype=1;
116   c.q_sequencep=0;
117   c.quantlist=calloc(quantvals,sizeof(long));
118
119   quantlist=malloc(sizeof(long)*c.dim*c.entries);
120   hits=malloc(c.entries*sizeof(long));
121   for(j=0;j<entries;j++)hits[j]=1;
122   for(j=0;j<entries;j++)c.lengthlist[j]=1;
123
124   reset_next_value();
125   setup_line(in);
126   for(j=0;j<quantvals;j++){  
127     if(get_line_value(in,quantlist+j)==-1){
128       fprintf(stderr,"Ran out of data on line 2 of description file\n");
129       exit(1);
130     }
131   }
132
133   line=setup_line(in);
134   if(sscanf(line,"%d",&threshvals)!=1){
135     fprintf(stderr,"Syntax error reading book file (line 3)\n");
136     exit(1);
137   }
138   
139   t.quantthresh=calloc(threshvals-1,sizeof(double));
140   t.quantmap=calloc(threshvals,sizeof(int));
141   t.threshvals=threshvals;
142   t.quantvals=quantvals;
143
144   setup_line(in);
145   for(j=0;j<threshvals-1;j++){  
146     if(get_line_value(in,t.quantthresh+j)==-1){
147       fprintf(stderr,"Ran out of data on line 4 of description file\n");
148       exit(1);
149     }
150   }
151
152   setup_line(in);
153   for(j=0;j<threshvals;j++){  
154     if(get_next_ivalue(in,t.quantmap+j)==-1){
155       fprintf(stderr,"Ran out of data on line 5 of description file\n");
156       exit(1);
157     }
158   }
159
160   /* gen a real quant list from the more easily human-grokked input */
161   {
162     double min=quantlist[0];
163     double mindel=1;
164     for(j=1;j<quantvals;j++){  
165       if(quantlist[j]<min)min=quantlist[j];
166       for(k=0;k<j;k++){
167         double del=quantlist[k]-min;
168         /* really underpowered :-P know that this will only factor
169            powers of two (duh) */
170         while((int)(del/mindel)+.01<del/mindel){mindel/=2;}
171       }
172     }
173     c.q_min=_float32_pack(min);
174     c.q_delta=_float32_pack(mindel);
175     c.q_quant=0;
176
177     min=_float32_unpack(c.q_min);
178     mindel=_float32_unpack(c.q_delta);
179     for(j=0;j<quantvals;j++){
180       c.quantlist[j]=rint((quantlist[j]-min)/mindel);
181       if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]);
182     }
183   }
184   
185   vorbis_book_init_encode(&b,&c);
186   fclose(in);
187
188   /* at this point, we have enough to do best entry matching.  We
189      don't have counts yet, but that's OK; match, write residual data,
190      and track hits.  The build word lengths when we're done */
191
192   /* we have to do our own de-interleave */
193   if(argv[2]==NULL){
194     fprintf(stderr,"Need a data file on the command line.\n");
195     exit(1);
196   }
197   in=fopen(argv[2],"r");
198   if(!in){
199     fprintf(stderr,"Could not open input file %s\n",argv[2]);
200     exit(1);
201   }
202
203   {
204     int cols=0;
205     long lines=0;
206     double *vec;
207     int interleaved;
208     line=setup_line(in);
209     /* count cols before we start reading */
210     {
211       char *temp=line;
212       while(*temp==' ')temp++;
213       for(cols=0;*temp;cols++){
214         while(*temp>32)temp++;
215         while(*temp==' ')temp++;
216       }
217     }
218     vec=alloca(cols*sizeof(double));
219     interleaved=cols/dim;
220
221     while(line){
222       lines++;
223
224       if(!(lines&0xff))spinnit("lines so far...",lines);
225
226       /* don't need to deinterleave; besterror does that for us */
227       for(j=0;j<cols;j++)
228         if(get_line_value(in,vec+j)){
229           fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
230           exit(1);
231         }
232
233       /* process */
234       for(j=0;j<interleaved;j++)
235         hits[vorbis_book_besterror(&b,vec+j,interleaved,addmul)]++;
236         
237       /* write */
238       for(j=0;j<cols;j++)
239         fprintf(stdout,"%g, ",vec[j]);
240       fprintf(stdout,"\n");
241
242       line=setup_line(in);
243     }
244   }
245   fclose(in);
246
247   /* build the codeword lengths */
248   memset(c.lengthlist,0,sizeof(long)*entries);
249   build_tree_from_lengths(entries,hits,c.lengthlist);
250
251   /* save the book in C header form */
252   fprintf(out,
253  "/********************************************************************\n"
254  " *                                                                  *\n"
255  " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *\n"
256  " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
257  " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *\n"
258  " * PLEASE READ THESE TERMS DISTRIBUTING.                            *\n"
259  " *                                                                  *\n"
260  " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *\n"
261  " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *\n"
262  " * http://www.xiph.org/                                             *\n"
263  " *                                                                  *\n"
264  " ********************************************************************\n"
265  "\n"
266  " function: static codebook autogenerated by vq/latticebuild\n"
267  "\n"
268  " ********************************************************************/\n\n");
269
270   fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
271   fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
272
273   /* first, the static vectors, then the book structure to tie it together. */
274   /* quantlist */
275   fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
276   for(j=0;j<_book_maptype1_quantvals(&c);j++){
277     fprintf(out,"\t%ld,\n",c.quantlist[j]);
278   }
279   fprintf(out,"};\n\n");
280
281   /* lengthlist */
282   fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
283   for(j=0;j<c.entries;){
284     fprintf(out,"\t");
285     for(k=0;k<16 && j<c.entries;k++,j++)
286       fprintf(out,"%2ld,",c.lengthlist[j]);
287     fprintf(out,"\n");
288   }
289   fprintf(out,"};\n\n");
290
291   /* quantthresh */
292   fprintf(out,"static double _vq_quantthresh_%s[] = {\n",name);
293   for(j=0;j<t.threshvals-1;){
294     fprintf(out,"\t");
295     for(k=0;k<8 && j<t.threshvals-1;k++,j++)
296       fprintf(out,"%.5g, ",t.quantthresh[j]);
297     fprintf(out,"\n");
298   }
299   fprintf(out,"};\n\n");
300
301   /* quantmap */
302   fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
303   for(j=0;j<t.threshvals;){
304     fprintf(out,"\t");
305     for(k=0;k<8 && j<t.threshvals;k++,j++)
306       fprintf(out,"%5ld,",t.quantmap[j]);
307     fprintf(out,"\n");
308   }
309   fprintf(out,"};\n\n");  
310
311   /* tie it all together */
312   
313   fprintf(out,"static encode_aux_threshmatch _vq_aux_%s = {\n",name);
314   fprintf(out,"\t_vq_quantthresh_%s,\n",name);
315   fprintf(out,"\t_vq_quantmap_%s,\n",name);
316   fprintf(out,"\t%d,\n",t.quantvals);
317   fprintf(out,"\t%d\n};\n\n",t.threshvals);
318   
319   fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
320   
321   fprintf(out,"\t%ld, %ld,\n",c.dim,c.entries);
322   fprintf(out,"\t_vq_lengthlist_%s,\n",name);
323   fprintf(out,"\t1, %ld, %ld, %d, %d,\n",
324           c.q_min,c.q_delta,c.q_quant,c.q_sequencep);
325   fprintf(out,"\t_vq_quantlist_%s,\n",name);
326   fprintf(out,"\tNULL,\n");
327   fprintf(out,"\t&_vq_aux_%s\n",name);
328   fprintf(out,"};\n\n");
329
330   fprintf(out,"\n#endif\n");
331   fclose(out);
332
333   fprintf(stderr,"\r                                                     "
334           "\nDone.\n");
335   exit(0);
336 }