1 | /******************************************************************** |
---|
2 | * * |
---|
3 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * |
---|
4 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
---|
5 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
---|
6 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
---|
7 | * * |
---|
8 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * |
---|
9 | * by the Xiph.Org Foundation http://www.xiph.org/ * |
---|
10 | * * |
---|
11 | ******************************************************************** |
---|
12 | |
---|
13 | function: utility functions for loading .vqh and .vqd files |
---|
14 | last mod: $Id: bookutil.c 13293 2007-07-24 00:09:47Z xiphmont $ |
---|
15 | |
---|
16 | ********************************************************************/ |
---|
17 | |
---|
18 | #include <stdlib.h> |
---|
19 | #include <stdio.h> |
---|
20 | #include <math.h> |
---|
21 | #include <string.h> |
---|
22 | #include <errno.h> |
---|
23 | #include "bookutil.h" |
---|
24 | |
---|
25 | /* A few little utils for reading files */ |
---|
26 | /* read a line. Use global, persistent buffering */ |
---|
27 | static char *linebuffer=NULL; |
---|
28 | static int lbufsize=0; |
---|
29 | char *get_line(FILE *in){ |
---|
30 | long sofar=0; |
---|
31 | if(feof(in))return NULL; |
---|
32 | |
---|
33 | while(1){ |
---|
34 | int gotline=0; |
---|
35 | |
---|
36 | while(!gotline){ |
---|
37 | if(sofar+1>=lbufsize){ |
---|
38 | if(!lbufsize){ |
---|
39 | lbufsize=1024; |
---|
40 | linebuffer=_ogg_malloc(lbufsize); |
---|
41 | }else{ |
---|
42 | lbufsize*=2; |
---|
43 | linebuffer=_ogg_realloc(linebuffer,lbufsize); |
---|
44 | } |
---|
45 | } |
---|
46 | { |
---|
47 | long c=fgetc(in); |
---|
48 | switch(c){ |
---|
49 | case EOF: |
---|
50 | if(sofar==0)return(NULL); |
---|
51 | /* fallthrough correct */ |
---|
52 | case '\n': |
---|
53 | linebuffer[sofar]='\0'; |
---|
54 | gotline=1; |
---|
55 | break; |
---|
56 | default: |
---|
57 | linebuffer[sofar++]=c; |
---|
58 | linebuffer[sofar]='\0'; |
---|
59 | break; |
---|
60 | } |
---|
61 | } |
---|
62 | } |
---|
63 | |
---|
64 | if(linebuffer[0]=='#'){ |
---|
65 | sofar=0; |
---|
66 | }else{ |
---|
67 | return(linebuffer); |
---|
68 | } |
---|
69 | } |
---|
70 | } |
---|
71 | |
---|
72 | /* read the next numerical value from the given file */ |
---|
73 | static char *value_line_buff=NULL; |
---|
74 | |
---|
75 | int get_line_value(FILE *in,float *value){ |
---|
76 | char *next; |
---|
77 | |
---|
78 | if(!value_line_buff)return(-1); |
---|
79 | |
---|
80 | *value=strtod(value_line_buff, &next); |
---|
81 | if(next==value_line_buff){ |
---|
82 | value_line_buff=NULL; |
---|
83 | return(-1); |
---|
84 | }else{ |
---|
85 | value_line_buff=next; |
---|
86 | while(*value_line_buff>44)value_line_buff++; |
---|
87 | if(*value_line_buff==44)value_line_buff++; |
---|
88 | return(0); |
---|
89 | } |
---|
90 | } |
---|
91 | |
---|
92 | int get_next_value(FILE *in,float *value){ |
---|
93 | while(1){ |
---|
94 | if(get_line_value(in,value)){ |
---|
95 | value_line_buff=get_line(in); |
---|
96 | if(!value_line_buff)return(-1); |
---|
97 | }else{ |
---|
98 | return(0); |
---|
99 | } |
---|
100 | } |
---|
101 | } |
---|
102 | |
---|
103 | int get_next_ivalue(FILE *in,long *ivalue){ |
---|
104 | float value; |
---|
105 | int ret=get_next_value(in,&value); |
---|
106 | *ivalue=value; |
---|
107 | return(ret); |
---|
108 | } |
---|
109 | |
---|
110 | static float sequence_base=0.f; |
---|
111 | static int v_sofar=0; |
---|
112 | void reset_next_value(void){ |
---|
113 | value_line_buff=NULL; |
---|
114 | sequence_base=0.f; |
---|
115 | v_sofar=0; |
---|
116 | } |
---|
117 | |
---|
118 | char *setup_line(FILE *in){ |
---|
119 | reset_next_value(); |
---|
120 | value_line_buff=get_line(in); |
---|
121 | return(value_line_buff); |
---|
122 | } |
---|
123 | |
---|
124 | |
---|
125 | int get_vector(codebook *b,FILE *in,int start, int n,float *a){ |
---|
126 | int i; |
---|
127 | const static_codebook *c=b->c; |
---|
128 | |
---|
129 | while(1){ |
---|
130 | |
---|
131 | if(v_sofar==n || get_line_value(in,a)){ |
---|
132 | reset_next_value(); |
---|
133 | if(get_next_value(in,a)) |
---|
134 | break; |
---|
135 | for(i=0;i<start;i++){ |
---|
136 | sequence_base=*a; |
---|
137 | get_line_value(in,a); |
---|
138 | } |
---|
139 | } |
---|
140 | |
---|
141 | for(i=1;i<c->dim;i++) |
---|
142 | if(get_line_value(in,a+i)) |
---|
143 | break; |
---|
144 | |
---|
145 | if(i==c->dim){ |
---|
146 | float temp=a[c->dim-1]; |
---|
147 | for(i=0;i<c->dim;i++)a[i]-=sequence_base; |
---|
148 | if(c->q_sequencep)sequence_base=temp; |
---|
149 | v_sofar++; |
---|
150 | return(0); |
---|
151 | } |
---|
152 | sequence_base=0.f; |
---|
153 | } |
---|
154 | |
---|
155 | return(-1); |
---|
156 | } |
---|
157 | |
---|
158 | /* read lines fromt he beginning until we find one containing the |
---|
159 | specified string */ |
---|
160 | char *find_seek_to(FILE *in,char *s){ |
---|
161 | rewind(in); |
---|
162 | while(1){ |
---|
163 | char *line=get_line(in); |
---|
164 | if(line){ |
---|
165 | if(strstr(line,s)) |
---|
166 | return(line); |
---|
167 | }else |
---|
168 | return(NULL); |
---|
169 | } |
---|
170 | } |
---|
171 | |
---|
172 | |
---|
173 | /* this reads the format as written by vqbuild/latticebuild; innocent |
---|
174 | (legal) tweaking of the file that would not affect its valid |
---|
175 | header-ness will break this routine */ |
---|
176 | |
---|
177 | codebook *codebook_load(char *filename){ |
---|
178 | codebook *b=_ogg_calloc(1,sizeof(codebook)); |
---|
179 | static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook))); |
---|
180 | encode_aux_nearestmatch *a=NULL; |
---|
181 | encode_aux_threshmatch *t=NULL; |
---|
182 | encode_aux_pigeonhole *p=NULL; |
---|
183 | int quant_to_read=0; |
---|
184 | FILE *in=fopen(filename,"r"); |
---|
185 | char *line; |
---|
186 | long i; |
---|
187 | |
---|
188 | if(in==NULL){ |
---|
189 | fprintf(stderr,"Couldn't open codebook %s\n",filename); |
---|
190 | exit(1); |
---|
191 | } |
---|
192 | |
---|
193 | /* find the codebook struct */ |
---|
194 | find_seek_to(in,"static static_codebook "); |
---|
195 | |
---|
196 | /* get the major important values */ |
---|
197 | line=get_line(in); |
---|
198 | if(sscanf(line,"%ld, %ld,", |
---|
199 | &(c->dim),&(c->entries))!=2){ |
---|
200 | fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); |
---|
201 | exit(1); |
---|
202 | } |
---|
203 | line=get_line(in); |
---|
204 | line=get_line(in); |
---|
205 | if(sscanf(line,"%d, %ld, %ld, %d, %d,", |
---|
206 | &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant), |
---|
207 | &(c->q_sequencep))!=5){ |
---|
208 | fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); |
---|
209 | exit(1); |
---|
210 | } |
---|
211 | |
---|
212 | /* find the auxiliary encode struct[s] (if any) */ |
---|
213 | if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){ |
---|
214 | /* how big? */ |
---|
215 | c->nearest_tree=a=_ogg_calloc(1,sizeof(encode_aux_nearestmatch)); |
---|
216 | line=get_line(in); |
---|
217 | line=get_line(in); |
---|
218 | line=get_line(in); |
---|
219 | line=get_line(in); |
---|
220 | line=get_line(in); |
---|
221 | if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){ |
---|
222 | fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line); |
---|
223 | exit(1); |
---|
224 | } |
---|
225 | |
---|
226 | /* load ptr0 */ |
---|
227 | find_seek_to(in,"static long _vq_ptr0"); |
---|
228 | reset_next_value(); |
---|
229 | a->ptr0=_ogg_malloc(sizeof(long)*a->aux); |
---|
230 | for(i=0;i<a->aux;i++) |
---|
231 | if(get_next_ivalue(in,a->ptr0+i)){ |
---|
232 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
233 | exit(1); |
---|
234 | } |
---|
235 | |
---|
236 | /* load ptr1 */ |
---|
237 | find_seek_to(in,"static long _vq_ptr1"); |
---|
238 | reset_next_value(); |
---|
239 | a->ptr1=_ogg_malloc(sizeof(long)*a->aux); |
---|
240 | for(i=0;i<a->aux;i++) |
---|
241 | if(get_next_ivalue(in,a->ptr1+i)){ |
---|
242 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
243 | exit(1); |
---|
244 | } |
---|
245 | |
---|
246 | |
---|
247 | /* load p */ |
---|
248 | find_seek_to(in,"static long _vq_p_"); |
---|
249 | reset_next_value(); |
---|
250 | a->p=_ogg_malloc(sizeof(long)*a->aux); |
---|
251 | for(i=0;i<a->aux;i++) |
---|
252 | if(get_next_ivalue(in,a->p+i)){ |
---|
253 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
254 | exit(1); |
---|
255 | } |
---|
256 | |
---|
257 | /* load q */ |
---|
258 | find_seek_to(in,"static long _vq_q_"); |
---|
259 | reset_next_value(); |
---|
260 | a->q=_ogg_malloc(sizeof(long)*a->aux); |
---|
261 | for(i=0;i<a->aux;i++) |
---|
262 | if(get_next_ivalue(in,a->q+i)){ |
---|
263 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
264 | exit(1); |
---|
265 | } |
---|
266 | } |
---|
267 | |
---|
268 | if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){ |
---|
269 | /* how big? */ |
---|
270 | c->thresh_tree=t=_ogg_calloc(1,sizeof(encode_aux_threshmatch)); |
---|
271 | line=get_line(in); |
---|
272 | line=get_line(in); |
---|
273 | line=get_line(in); |
---|
274 | if(sscanf(line,"%d",&(t->quantvals))!=1){ |
---|
275 | fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line); |
---|
276 | exit(1); |
---|
277 | } |
---|
278 | line=get_line(in); |
---|
279 | if(sscanf(line,"%d",&(t->threshvals))!=1){ |
---|
280 | fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line); |
---|
281 | exit(1); |
---|
282 | } |
---|
283 | /* load quantthresh */ |
---|
284 | find_seek_to(in,"static float _vq_quantthresh_"); |
---|
285 | reset_next_value(); |
---|
286 | t->quantthresh=_ogg_malloc(sizeof(float)*t->threshvals); |
---|
287 | for(i=0;i<t->threshvals-1;i++) |
---|
288 | if(get_next_value(in,t->quantthresh+i)){ |
---|
289 | fprintf(stderr,"out of data 1 while reading codebook %s\n",filename); |
---|
290 | exit(1); |
---|
291 | } |
---|
292 | /* load quantmap */ |
---|
293 | find_seek_to(in,"static long _vq_quantmap_"); |
---|
294 | reset_next_value(); |
---|
295 | t->quantmap=_ogg_malloc(sizeof(long)*t->threshvals); |
---|
296 | for(i=0;i<t->threshvals;i++) |
---|
297 | if(get_next_ivalue(in,t->quantmap+i)){ |
---|
298 | fprintf(stderr,"out of data 2 while reading codebook %s\n",filename); |
---|
299 | exit(1); |
---|
300 | } |
---|
301 | } |
---|
302 | |
---|
303 | if(find_seek_to(in,"static encode_aux_pigeonhole _vq_aux")){ |
---|
304 | int pigeons=1,i; |
---|
305 | /* how big? */ |
---|
306 | c->pigeon_tree=p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole)); |
---|
307 | line=get_line(in); |
---|
308 | if(sscanf(line,"%f, %f, %d, %d",&(p->min),&(p->del), |
---|
309 | &(p->mapentries),&(p->quantvals))!=4){ |
---|
310 | fprintf(stderr,"5: syntax in %s in line:\t %s",filename,line); |
---|
311 | exit(1); |
---|
312 | } |
---|
313 | line=get_line(in); |
---|
314 | line=get_line(in); |
---|
315 | if(sscanf(line,"%ld",&(p->fittotal))!=1){ |
---|
316 | fprintf(stderr,"6: syntax in %s in line:\t %s",filename,line); |
---|
317 | exit(1); |
---|
318 | } |
---|
319 | /* load pigeonmap */ |
---|
320 | find_seek_to(in,"static long _vq_pigeonmap_"); |
---|
321 | reset_next_value(); |
---|
322 | p->pigeonmap=_ogg_malloc(sizeof(long)*p->mapentries); |
---|
323 | for(i=0;i<p->mapentries;i++) |
---|
324 | if(get_next_ivalue(in,p->pigeonmap+i)){ |
---|
325 | fprintf(stderr,"out of data (pigeonmap) while reading codebook %s\n",filename); |
---|
326 | exit(1); |
---|
327 | } |
---|
328 | /* load fitlist */ |
---|
329 | find_seek_to(in,"static long _vq_fitlist_"); |
---|
330 | reset_next_value(); |
---|
331 | p->fitlist=_ogg_malloc(sizeof(long)*p->fittotal); |
---|
332 | for(i=0;i<p->fittotal;i++) |
---|
333 | if(get_next_ivalue(in,p->fitlist+i)){ |
---|
334 | fprintf(stderr,"out of data (fitlist) while reading codebook %s\n",filename); |
---|
335 | exit(1); |
---|
336 | } |
---|
337 | /* load fitmap */ |
---|
338 | find_seek_to(in,"static long _vq_fitmap_"); |
---|
339 | reset_next_value(); |
---|
340 | for(i=0;i<c->dim;i++)pigeons*=p->quantvals; |
---|
341 | p->fitmap=_ogg_malloc(sizeof(long)*pigeons); |
---|
342 | for(i=0;i<pigeons;i++) |
---|
343 | if(get_next_ivalue(in,p->fitmap+i)){ |
---|
344 | fprintf(stderr,"out of data (fitmap) while reading codebook %s\n",filename); |
---|
345 | exit(1); |
---|
346 | } |
---|
347 | |
---|
348 | /* load fitlength */ |
---|
349 | find_seek_to(in,"static long _vq_fitlength_"); |
---|
350 | reset_next_value(); |
---|
351 | p->fitlength=_ogg_malloc(sizeof(long)*pigeons); |
---|
352 | for(i=0;i<pigeons;i++) |
---|
353 | if(get_next_ivalue(in,p->fitlength+i)){ |
---|
354 | fprintf(stderr,"out of data (fitlength) while reading codebook %s\n",filename); |
---|
355 | exit(1); |
---|
356 | } |
---|
357 | } |
---|
358 | |
---|
359 | switch(c->maptype){ |
---|
360 | case 0: |
---|
361 | quant_to_read=0; |
---|
362 | break; |
---|
363 | case 1: |
---|
364 | quant_to_read=_book_maptype1_quantvals(c); |
---|
365 | break; |
---|
366 | case 2: |
---|
367 | quant_to_read=c->entries*c->dim; |
---|
368 | break; |
---|
369 | } |
---|
370 | |
---|
371 | /* load the quantized entries */ |
---|
372 | find_seek_to(in,"static long _vq_quantlist_"); |
---|
373 | reset_next_value(); |
---|
374 | c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read); |
---|
375 | for(i=0;i<quant_to_read;i++) |
---|
376 | if(get_next_ivalue(in,c->quantlist+i)){ |
---|
377 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
378 | exit(1); |
---|
379 | } |
---|
380 | |
---|
381 | /* load the lengthlist */ |
---|
382 | find_seek_to(in,"_lengthlist"); |
---|
383 | reset_next_value(); |
---|
384 | c->lengthlist=_ogg_malloc(sizeof(long)*c->entries); |
---|
385 | for(i=0;i<c->entries;i++) |
---|
386 | if(get_next_ivalue(in,c->lengthlist+i)){ |
---|
387 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
388 | exit(1); |
---|
389 | } |
---|
390 | |
---|
391 | /* got it all */ |
---|
392 | fclose(in); |
---|
393 | |
---|
394 | vorbis_book_init_encode(b,c); |
---|
395 | |
---|
396 | return(b); |
---|
397 | } |
---|
398 | |
---|
399 | void spinnit(char *s,int n){ |
---|
400 | static int p=0; |
---|
401 | static long lasttime=0; |
---|
402 | long test; |
---|
403 | struct timeval thistime; |
---|
404 | |
---|
405 | gettimeofday(&thistime,NULL); |
---|
406 | test=thistime.tv_sec*10+thistime.tv_usec/100000; |
---|
407 | if(lasttime!=test){ |
---|
408 | lasttime=test; |
---|
409 | |
---|
410 | fprintf(stderr,"%s%d ",s,n); |
---|
411 | |
---|
412 | p++;if(p>3)p=0; |
---|
413 | switch(p){ |
---|
414 | case 0: |
---|
415 | fprintf(stderr,"| \r"); |
---|
416 | break; |
---|
417 | case 1: |
---|
418 | fprintf(stderr,"/ \r"); |
---|
419 | break; |
---|
420 | case 2: |
---|
421 | fprintf(stderr,"- \r"); |
---|
422 | break; |
---|
423 | case 3: |
---|
424 | fprintf(stderr,"\\ \r"); |
---|
425 | break; |
---|
426 | } |
---|
427 | fflush(stderr); |
---|
428 | } |
---|
429 | } |
---|
430 | |
---|
431 | void build_tree_from_lengths(int vals, long *hist, long *lengths){ |
---|
432 | int i,j; |
---|
433 | long *membership=_ogg_malloc(vals*sizeof(long)); |
---|
434 | long *histsave=alloca(vals*sizeof(long)); |
---|
435 | memcpy(histsave,hist,vals*sizeof(long)); |
---|
436 | |
---|
437 | for(i=0;i<vals;i++)membership[i]=i; |
---|
438 | |
---|
439 | /* find codeword lengths */ |
---|
440 | /* much more elegant means exist. Brute force n^2, minimum thought */ |
---|
441 | for(i=vals;i>1;i--){ |
---|
442 | int first=-1,second=-1; |
---|
443 | long least=-1; |
---|
444 | |
---|
445 | spinnit("building... ",i); |
---|
446 | |
---|
447 | /* find the two nodes to join */ |
---|
448 | for(j=0;j<vals;j++) |
---|
449 | if(least==-1 || hist[j]<=least){ |
---|
450 | least=hist[j]; |
---|
451 | first=membership[j]; |
---|
452 | } |
---|
453 | least=-1; |
---|
454 | for(j=0;j<vals;j++) |
---|
455 | if((least==-1 || hist[j]<=least) && membership[j]!=first){ |
---|
456 | least=hist[j]; |
---|
457 | second=membership[j]; |
---|
458 | } |
---|
459 | if(first==-1 || second==-1){ |
---|
460 | fprintf(stderr,"huffman fault; no free branch\n"); |
---|
461 | exit(1); |
---|
462 | } |
---|
463 | |
---|
464 | /* join them */ |
---|
465 | least=hist[first]+hist[second]; |
---|
466 | for(j=0;j<vals;j++) |
---|
467 | if(membership[j]==first || membership[j]==second){ |
---|
468 | membership[j]=first; |
---|
469 | hist[j]=least; |
---|
470 | lengths[j]++; |
---|
471 | } |
---|
472 | } |
---|
473 | for(i=0;i<vals-1;i++) |
---|
474 | if(membership[i]!=membership[i+1]){ |
---|
475 | fprintf(stderr,"huffman fault; failed to build single tree\n"); |
---|
476 | exit(1); |
---|
477 | } |
---|
478 | |
---|
479 | /* for sanity check purposes: how many bits would it have taken to |
---|
480 | encode the training set? */ |
---|
481 | { |
---|
482 | long bitsum=0; |
---|
483 | long samples=0; |
---|
484 | for(i=0;i<vals;i++){ |
---|
485 | bitsum+=(histsave[i]-1)*lengths[i]; |
---|
486 | samples+=histsave[i]-1; |
---|
487 | } |
---|
488 | |
---|
489 | if(samples){ |
---|
490 | fprintf(stderr,"\rTotal samples in training set: %ld \n",samples); |
---|
491 | fprintf(stderr,"\rTotal bits used to represent training set: %ld\n", |
---|
492 | bitsum); |
---|
493 | } |
---|
494 | } |
---|
495 | |
---|
496 | free(membership); |
---|
497 | } |
---|
498 | |
---|
499 | /* wrap build_tree_from_lengths to allow zero entries in the histogram */ |
---|
500 | void build_tree_from_lengths0(int vals, long *hist, long *lengths){ |
---|
501 | |
---|
502 | /* pack the 'sparse' hit list into a dense list, then unpack |
---|
503 | the lengths after the build */ |
---|
504 | |
---|
505 | int upper=0,i; |
---|
506 | long *lengthlist=_ogg_calloc(vals,sizeof(long)); |
---|
507 | long *newhist=alloca(vals*sizeof(long)); |
---|
508 | |
---|
509 | for(i=0;i<vals;i++) |
---|
510 | if(hist[i]>0) |
---|
511 | newhist[upper++]=hist[i]; |
---|
512 | |
---|
513 | if(upper != vals){ |
---|
514 | fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n", |
---|
515 | vals-upper,upper); |
---|
516 | } |
---|
517 | |
---|
518 | build_tree_from_lengths(upper,newhist,lengthlist); |
---|
519 | |
---|
520 | upper=0; |
---|
521 | for(i=0;i<vals;i++) |
---|
522 | if(hist[i]>0) |
---|
523 | lengths[i]=lengthlist[upper++]; |
---|
524 | else |
---|
525 | lengths[i]=0; |
---|
526 | |
---|
527 | free(lengthlist); |
---|
528 | } |
---|
529 | |
---|
530 | void write_codebook(FILE *out,char *name,const static_codebook *c){ |
---|
531 | encode_aux_pigeonhole *p=c->pigeon_tree; |
---|
532 | encode_aux_threshmatch *t=c->thresh_tree; |
---|
533 | encode_aux_nearestmatch *n=c->nearest_tree; |
---|
534 | int i,j,k; |
---|
535 | |
---|
536 | /* save the book in C header form */ |
---|
537 | |
---|
538 | /* first, the static vectors, then the book structure to tie it together. */ |
---|
539 | /* quantlist */ |
---|
540 | if(c->quantlist){ |
---|
541 | long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim); |
---|
542 | fprintf(out,"static long _vq_quantlist_%s[] = {\n",name); |
---|
543 | for(j=0;j<vals;j++){ |
---|
544 | fprintf(out,"\t%ld,\n",c->quantlist[j]); |
---|
545 | } |
---|
546 | fprintf(out,"};\n\n"); |
---|
547 | } |
---|
548 | |
---|
549 | /* lengthlist */ |
---|
550 | fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name); |
---|
551 | for(j=0;j<c->entries;){ |
---|
552 | fprintf(out,"\t"); |
---|
553 | for(k=0;k<16 && j<c->entries;k++,j++) |
---|
554 | fprintf(out,"%2ld,",c->lengthlist[j]); |
---|
555 | fprintf(out,"\n"); |
---|
556 | } |
---|
557 | fprintf(out,"};\n\n"); |
---|
558 | |
---|
559 | if(t){ |
---|
560 | /* quantthresh */ |
---|
561 | fprintf(out,"static float _vq_quantthresh_%s[] = {\n",name); |
---|
562 | for(j=0;j<t->threshvals-1;){ |
---|
563 | fprintf(out,"\t"); |
---|
564 | for(k=0;k<8 && j<t->threshvals-1;k++,j++) |
---|
565 | fprintf(out,"%.5g, ",t->quantthresh[j]); |
---|
566 | fprintf(out,"\n"); |
---|
567 | } |
---|
568 | fprintf(out,"};\n\n"); |
---|
569 | |
---|
570 | /* quantmap */ |
---|
571 | fprintf(out,"static long _vq_quantmap_%s[] = {\n",name); |
---|
572 | for(j=0;j<t->threshvals;){ |
---|
573 | fprintf(out,"\t"); |
---|
574 | for(k=0;k<8 && j<t->threshvals;k++,j++) |
---|
575 | fprintf(out,"%5ld,",t->quantmap[j]); |
---|
576 | fprintf(out,"\n"); |
---|
577 | } |
---|
578 | fprintf(out,"};\n\n"); |
---|
579 | |
---|
580 | fprintf(out,"static encode_aux_threshmatch _vq_auxt_%s = {\n",name); |
---|
581 | fprintf(out,"\t_vq_quantthresh_%s,\n",name); |
---|
582 | fprintf(out,"\t_vq_quantmap_%s,\n",name); |
---|
583 | fprintf(out,"\t%d,\n",t->quantvals); |
---|
584 | fprintf(out,"\t%d\n};\n\n",t->threshvals); |
---|
585 | } |
---|
586 | |
---|
587 | if(p){ |
---|
588 | int pigeons=1; |
---|
589 | for(i=0;i<c->dim;i++)pigeons*=p->quantvals; |
---|
590 | |
---|
591 | /* pigeonmap */ |
---|
592 | fprintf(out,"static long _vq_pigeonmap_%s[] = {\n",name); |
---|
593 | for(j=0;j<p->mapentries;){ |
---|
594 | fprintf(out,"\t"); |
---|
595 | for(k=0;k<8 && j<p->mapentries;k++,j++) |
---|
596 | fprintf(out,"%5ld, ",p->pigeonmap[j]); |
---|
597 | fprintf(out,"\n"); |
---|
598 | } |
---|
599 | fprintf(out,"};\n\n"); |
---|
600 | /* fitlist */ |
---|
601 | fprintf(out,"static long _vq_fitlist_%s[] = {\n",name); |
---|
602 | for(j=0;j<p->fittotal;){ |
---|
603 | fprintf(out,"\t"); |
---|
604 | for(k=0;k<8 && j<p->fittotal;k++,j++) |
---|
605 | fprintf(out,"%5ld, ",p->fitlist[j]); |
---|
606 | fprintf(out,"\n"); |
---|
607 | } |
---|
608 | fprintf(out,"};\n\n"); |
---|
609 | /* fitmap */ |
---|
610 | fprintf(out,"static long _vq_fitmap_%s[] = {\n",name); |
---|
611 | for(j=0;j<pigeons;){ |
---|
612 | fprintf(out,"\t"); |
---|
613 | for(k=0;k<8 && j<pigeons;k++,j++) |
---|
614 | fprintf(out,"%5ld, ",p->fitmap[j]); |
---|
615 | fprintf(out,"\n"); |
---|
616 | } |
---|
617 | fprintf(out,"};\n\n"); |
---|
618 | /* fitlength */ |
---|
619 | fprintf(out,"static long _vq_fitlength_%s[] = {\n",name); |
---|
620 | for(j=0;j<pigeons;){ |
---|
621 | fprintf(out,"\t"); |
---|
622 | for(k=0;k<8 && j<pigeons;k++,j++) |
---|
623 | fprintf(out,"%5ld, ",p->fitlength[j]); |
---|
624 | fprintf(out,"\n"); |
---|
625 | } |
---|
626 | fprintf(out,"};\n\n"); |
---|
627 | |
---|
628 | fprintf(out,"static encode_aux_pigeonhole _vq_auxp_%s = {\n",name); |
---|
629 | fprintf(out,"\t%g, %g, %d, %d,\n", |
---|
630 | p->min,p->del,p->mapentries,p->quantvals); |
---|
631 | |
---|
632 | fprintf(out,"\t_vq_pigeonmap_%s,\n",name); |
---|
633 | |
---|
634 | fprintf(out,"\t%ld,\n",p->fittotal); |
---|
635 | fprintf(out,"\t_vq_fitlist_%s,\n",name); |
---|
636 | fprintf(out,"\t_vq_fitmap_%s,\n",name); |
---|
637 | fprintf(out,"\t_vq_fitlength_%s\n};\n\n",name); |
---|
638 | } |
---|
639 | |
---|
640 | if(n){ |
---|
641 | |
---|
642 | /* ptr0 */ |
---|
643 | fprintf(out,"static long _vq_ptr0_%s[] = {\n",name); |
---|
644 | for(j=0;j<n->aux;){ |
---|
645 | fprintf(out,"\t"); |
---|
646 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
647 | fprintf(out,"%6ld,",n->ptr0[j]); |
---|
648 | fprintf(out,"\n"); |
---|
649 | } |
---|
650 | fprintf(out,"};\n\n"); |
---|
651 | |
---|
652 | /* ptr1 */ |
---|
653 | fprintf(out,"static long _vq_ptr1_%s[] = {\n",name); |
---|
654 | for(j=0;j<n->aux;){ |
---|
655 | fprintf(out,"\t"); |
---|
656 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
657 | fprintf(out,"%6ld,",n->ptr1[j]); |
---|
658 | fprintf(out,"\n"); |
---|
659 | } |
---|
660 | fprintf(out,"};\n\n"); |
---|
661 | |
---|
662 | /* p */ |
---|
663 | fprintf(out,"static long _vq_p_%s[] = {\n",name); |
---|
664 | for(j=0;j<n->aux;){ |
---|
665 | fprintf(out,"\t"); |
---|
666 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
667 | fprintf(out,"%6ld,",n->p[j]*c->dim); |
---|
668 | fprintf(out,"\n"); |
---|
669 | } |
---|
670 | fprintf(out,"};\n\n"); |
---|
671 | |
---|
672 | /* q */ |
---|
673 | fprintf(out,"static long _vq_q_%s[] = {\n",name); |
---|
674 | for(j=0;j<n->aux;){ |
---|
675 | fprintf(out,"\t"); |
---|
676 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
677 | fprintf(out,"%6ld,",n->q[j]*c->dim); |
---|
678 | fprintf(out,"\n"); |
---|
679 | } |
---|
680 | fprintf(out,"};\n\n"); |
---|
681 | |
---|
682 | fprintf(out,"static encode_aux_nearestmatch _vq_auxn_%s = {\n",name); |
---|
683 | fprintf(out,"\t_vq_ptr0_%s,\n",name); |
---|
684 | fprintf(out,"\t_vq_ptr1_%s,\n",name); |
---|
685 | fprintf(out,"\t_vq_p_%s,\n",name); |
---|
686 | fprintf(out,"\t_vq_q_%s,\n",name); |
---|
687 | fprintf(out,"\t%ld, %ld\n};\n\n",n->aux,n->aux); |
---|
688 | } |
---|
689 | |
---|
690 | /* tie it all together */ |
---|
691 | |
---|
692 | fprintf(out,"static static_codebook %s = {\n",name); |
---|
693 | |
---|
694 | fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries); |
---|
695 | fprintf(out,"\t_vq_lengthlist_%s,\n",name); |
---|
696 | fprintf(out,"\t%d, %ld, %ld, %d, %d,\n", |
---|
697 | c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep); |
---|
698 | if(c->quantlist) |
---|
699 | fprintf(out,"\t_vq_quantlist_%s,\n",name); |
---|
700 | else |
---|
701 | fprintf(out,"\tNULL,\n"); |
---|
702 | |
---|
703 | if(n) |
---|
704 | fprintf(out,"\t&_vq_auxn_%s,\n",name); |
---|
705 | else |
---|
706 | fprintf(out,"\tNULL,\n"); |
---|
707 | if(t) |
---|
708 | fprintf(out,"\t&_vq_auxt_%s,\n",name); |
---|
709 | else |
---|
710 | fprintf(out,"\tNULL,\n"); |
---|
711 | if(p) |
---|
712 | fprintf(out,"\t&_vq_auxp_%s,\n",name); |
---|
713 | else |
---|
714 | fprintf(out,"\tNULL,\n"); |
---|
715 | |
---|
716 | fprintf(out,"\t0\n};\n\n"); |
---|
717 | } |
---|