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.3 2000/07/12 09:36:18 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> <sequentialp>
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,sequencep=0;
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 %d",&quantvals,&dim,&addmul,&sequencep)!=4){
107 if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
108 fprintf(stderr,"Syntax error reading book file (line 1)\n");
112 entries=pow(quantvals,dim);
116 c.lengthlist=malloc(entries*sizeof(long));
118 c.q_sequencep=sequencep;
119 c.quantlist=calloc(quantvals,sizeof(long));
121 quantlist=malloc(sizeof(long)*c.dim*c.entries);
122 hits=malloc(c.entries*sizeof(long));
123 for(j=0;j<entries;j++)hits[j]=1;
124 for(j=0;j<entries;j++)c.lengthlist[j]=1;
128 for(j=0;j<quantvals;j++){
129 if(get_line_value(in,quantlist+j)==-1){
130 fprintf(stderr,"Ran out of data on line 2 of description file\n");
136 if(sscanf(line,"%d",&threshvals)!=1){
137 fprintf(stderr,"Syntax error reading book file (line 3)\n");
141 t.quantthresh=calloc(threshvals-1,sizeof(double));
142 t.quantmap=calloc(threshvals,sizeof(int));
143 t.threshvals=threshvals;
144 t.quantvals=quantvals;
147 for(j=0;j<threshvals-1;j++){
148 if(get_line_value(in,t.quantthresh+j)==-1){
149 fprintf(stderr,"Ran out of data on line 4 of description file\n");
155 for(j=0;j<threshvals;j++){
156 if(get_next_ivalue(in,t.quantmap+j)==-1){
157 fprintf(stderr,"Ran out of data on line 5 of description file\n");
162 /* gen a real quant list from the more easily human-grokked input */
164 double min=quantlist[0];
167 for(j=1;j<quantvals;j++)if(quantlist[j]<min)min=quantlist[j];
168 for(j=0;j<quantvals;j++)
169 if(min!=quantlist[j] && (mindel==-1 || quantlist[j]-min<mindel))
170 mindel=quantlist[j]-min;
172 fprintf(stderr,"min=%g mindel=%g\n",min,mindel);
175 for(j=0;j<quantvals;j++){
176 double test=(quantlist[j]-min)/(mindel/fac);
177 if( fabs(rint(test)-test)>.000001) break;
179 if(j<quantvals)fac++;
184 c.q_min=_float32_pack(min);
185 c.q_delta=_float32_pack(mindel);
188 min=_float32_unpack(c.q_min);
189 mindel=_float32_unpack(c.q_delta);
190 for(j=0;j<quantvals;j++){
191 c.quantlist[j]=rint((quantlist[j]-min)/mindel);
192 if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]);
196 vorbis_book_init_encode(&b,&c);
199 /* at this point, we have enough to do best entry matching. We
200 don't have counts yet, but that's OK; match, write residual data,
201 and track hits. The build word lengths when we're done */
203 /* we have to do our own de-interleave */
205 fprintf(stderr,"Need a data file on the command line.\n");
208 in=fopen(argv[2],"r");
210 fprintf(stderr,"Could not open input file %s\n",argv[2]);
220 /* count cols before we start reading */
223 while(*temp==' ')temp++;
224 for(cols=0;*temp;cols++){
225 while(*temp>32)temp++;
226 while(*temp==' ')temp++;
229 vec=alloca(cols*sizeof(double));
230 interleaved=cols/dim;
235 if(!(lines&0xff))spinnit("lines so far...",lines);
237 /* don't need to deinterleave; besterror does that for us */
239 if(get_line_value(in,vec+j)){
240 fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
245 for(j=0;j<interleaved;j++)
246 hits[vorbis_book_besterror(&b,vec+j,interleaved,addmul)]++;
250 fprintf(stdout,"%g, ",vec[j]);
251 fprintf(stdout,"\n");
258 /* build the codeword lengths */
259 memset(c.lengthlist,0,sizeof(long)*entries);
260 build_tree_from_lengths(entries,hits,c.lengthlist);
262 /* save the book in C header form */
264 "/********************************************************************\n"
266 " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *\n"
267 " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
268 " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *\n"
269 " * PLEASE READ THESE TERMS DISTRIBUTING. *\n"
271 " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 *\n"
272 " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company *\n"
273 " * http://www.xiph.org/ *\n"
275 " ********************************************************************\n"
277 " function: static codebook autogenerated by vq/latticebuild\n"
279 " ********************************************************************/\n\n");
281 fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
282 fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
284 /* first, the static vectors, then the book structure to tie it together. */
286 fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
287 for(j=0;j<_book_maptype1_quantvals(&c);j++){
288 fprintf(out,"\t%ld,\n",c.quantlist[j]);
290 fprintf(out,"};\n\n");
293 fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
294 for(j=0;j<c.entries;){
296 for(k=0;k<16 && j<c.entries;k++,j++)
297 fprintf(out,"%2ld,",c.lengthlist[j]);
300 fprintf(out,"};\n\n");
303 fprintf(out,"static double _vq_quantthresh_%s[] = {\n",name);
304 for(j=0;j<t.threshvals-1;){
306 for(k=0;k<8 && j<t.threshvals-1;k++,j++)
307 fprintf(out,"%.5g, ",t.quantthresh[j]);
310 fprintf(out,"};\n\n");
313 fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
314 for(j=0;j<t.threshvals;){
316 for(k=0;k<8 && j<t.threshvals;k++,j++)
317 fprintf(out,"%5ld,",t.quantmap[j]);
320 fprintf(out,"};\n\n");
322 /* tie it all together */
324 fprintf(out,"static encode_aux_threshmatch _vq_aux_%s = {\n",name);
325 fprintf(out,"\t_vq_quantthresh_%s,\n",name);
326 fprintf(out,"\t_vq_quantmap_%s,\n",name);
327 fprintf(out,"\t%d,\n",t.quantvals);
328 fprintf(out,"\t%d\n};\n\n",t.threshvals);
330 fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
332 fprintf(out,"\t%ld, %ld,\n",c.dim,c.entries);
333 fprintf(out,"\t_vq_lengthlist_%s,\n",name);
334 fprintf(out,"\t1, %ld, %ld, %d, %d,\n",
335 c.q_min,c.q_delta,c.q_quant,c.q_sequencep);
336 fprintf(out,"\t_vq_quantlist_%s,\n",name);
337 fprintf(out,"\tNULL,\n");
338 fprintf(out,"\t&_vq_aux_%s\n",name);
339 fprintf(out,"};\n\n");
341 fprintf(out,"\n#endif\n");