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 building codebooks from lattice descriptions
15 last mod: $Id: latticebuild.c,v 1.2 2000/05/08 20:49:50 xiphmont Exp $
17 ********************************************************************/
24 #include "vorbis/codebook.h"
25 #include "../lib/sharedbook.h"
28 /* The purpose of this util is actually just to count hits and finish
29 packaging the description into a static codebook.
32 vqlattice description.vql datafile.vqd
34 the lattice description file contains five lines:
36 <n> <dim> <multiplicitavep>
37 <value_0> <value_1> <value_2> ... <value_n-1>
39 <thresh_0> <thresh_1> <thresh_2> ... <thresh_m-2>
40 <map_0> <map_1> <map_2> ... <map_m-1>
42 vqlattice sends residual data (for the next stage) to stdout, and
43 produces description.vqh */
45 static int ilog(unsigned int v){
54 int main(int argc,char *argv[]){
57 encode_aux_threshmatch t;
61 int entries=-1,dim=-1,quantvals=-1,addmul=-1,threshvals=-1;
67 memset(&b,0,sizeof(b));
68 memset(&c,0,sizeof(c));
69 memset(&t,0,sizeof(t));
72 fprintf(stderr,"Need a lattice description file on the command line.\n");
78 char *filename=calloc(strlen(argv[1])+4,1);
80 strcpy(filename,argv[1]);
81 in=fopen(filename,"r");
83 fprintf(stderr,"Could not open input file %s\n",filename);
87 ptr=strrchr(filename,'.');
90 name=strdup(filename);
93 name=strdup(filename);
94 strcat(filename,".vqh");
97 out=fopen(filename,"w");
99 fprintf(stderr,"Unable to open %s for writing\n",filename);
104 /* read the description */
106 if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
107 fprintf(stderr,"Syntax error reading book file (line 1)\n");
110 entries=pow(quantvals,dim);
114 c.lengthlist=malloc(entries*sizeof(long));
117 c.quantlist=calloc(quantvals,sizeof(long));
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;
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");
134 if(sscanf(line,"%d",&threshvals)!=1){
135 fprintf(stderr,"Syntax error reading book file (line 3)\n");
139 t.quantthresh=calloc(threshvals-1,sizeof(double));
140 t.quantmap=calloc(threshvals,sizeof(int));
141 t.threshvals=threshvals;
142 t.quantvals=quantvals;
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");
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");
160 /* gen a real quant list from the more easily human-grokked input */
162 double min=quantlist[0];
164 for(j=1;j<quantvals;j++){
165 if(quantlist[j]<min)min=quantlist[j];
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;}
173 c.q_min=_float32_pack(min);
174 c.q_delta=_float32_pack(mindel);
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]);
185 vorbis_book_init_encode(&b,&c);
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 */
192 /* we have to do our own de-interleave */
194 fprintf(stderr,"Need a data file on the command line.\n");
197 in=fopen(argv[2],"r");
199 fprintf(stderr,"Could not open input file %s\n",argv[2]);
209 /* count cols before we start reading */
212 while(*temp==' ')temp++;
213 for(cols=0;*temp;cols++){
214 while(*temp>32)temp++;
215 while(*temp==' ')temp++;
218 vec=alloca(cols*sizeof(double));
219 interleaved=cols/dim;
224 if(!(lines&0xff))spinnit("lines so far...",lines);
226 /* don't need to deinterleave; besterror does that for us */
228 if(get_line_value(in,vec+j)){
229 fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
234 for(j=0;j<interleaved;j++)
235 hits[vorbis_book_besterror(&b,vec+j,interleaved,addmul)]++;
239 fprintf(stdout,"%g, ",vec[j]);
240 fprintf(stdout,"\n");
247 /* build the codeword lengths */
248 memset(c.lengthlist,0,sizeof(long)*entries);
249 build_tree_from_lengths(entries,hits,c.lengthlist);
251 /* save the book in C header form */
253 "/********************************************************************\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"
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"
264 " ********************************************************************\n"
266 " function: static codebook autogenerated by vq/latticebuild\n"
268 " ********************************************************************/\n\n");
270 fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
271 fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
273 /* first, the static vectors, then the book structure to tie it together. */
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]);
279 fprintf(out,"};\n\n");
282 fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
283 for(j=0;j<c.entries;){
285 for(k=0;k<16 && j<c.entries;k++,j++)
286 fprintf(out,"%2ld,",c.lengthlist[j]);
289 fprintf(out,"};\n\n");
292 fprintf(out,"static double _vq_quantthresh_%s[] = {\n",name);
293 for(j=0;j<t.threshvals-1;){
295 for(k=0;k<8 && j<t.threshvals-1;k++,j++)
296 fprintf(out,"%.5g, ",t.quantthresh[j]);
299 fprintf(out,"};\n\n");
302 fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
303 for(j=0;j<t.threshvals;){
305 for(k=0;k<8 && j<t.threshvals;k++,j++)
306 fprintf(out,"%5ld,",t.quantmap[j]);
309 fprintf(out,"};\n\n");
311 /* tie it all together */
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);
319 fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
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");
330 fprintf(out,"\n#endif\n");