Update tizen 2.0 beta source
[external/libvorbis.git] / vq / bookutil.c
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 16037 2009-05-26 21:10:58Z 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const 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 const encode_aux_threshmatch _vq_auxt_%s = {\n",name);
581     fprintf(out,"\t(float *)_vq_quantthresh_%s,\n",name);
582     fprintf(out,"\t(long *)_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 const 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 const 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 const 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 const 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 const 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(long *)_vq_fitlist_%s,\n",name);
636     fprintf(out,"\t(long *)_vq_fitmap_%s,\n",name);
637     fprintf(out,"\t(long *)_vq_fitlength_%s\n};\n\n",name);
638   }
639
640   if(n){
641     
642     /* ptr0 */
643     fprintf(out,"static const 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 const 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 const 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 const 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 const encode_aux_nearestmatch _vq_auxn_%s = {\n",name);
683     fprintf(out,"\t(long *)_vq_ptr0_%s,\n",name);
684     fprintf(out,"\t(long *)_vq_ptr1_%s,\n",name);
685     fprintf(out,"\t(long *)_vq_p_%s,\n",name);
686     fprintf(out,"\t(long *)_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 const static_codebook %s = {\n",name);
693   
694   fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
695   fprintf(out,"\t(long *)_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(long *)_vq_quantlist_%s,\n",name);
700   else
701     fprintf(out,"\tNULL,\n");
702
703   if(n)
704     fprintf(out,"\t(encode_aux_nearestmatch *)&_vq_auxn_%s,\n",name);
705   else
706     fprintf(out,"\tNULL,\n");
707   if(t)
708     fprintf(out,"\t(encode_aux_threshmatch *)&_vq_auxt_%s,\n",name);
709   else
710     fprintf(out,"\tNULL,\n");
711   if(p)
712     fprintf(out,"\t(encode_aux_pigeonhole *)&_vq_auxp_%s,\n",name);
713   else
714     fprintf(out,"\tNULL,\n");
715
716   fprintf(out,"\t0\n};\n\n");
717 }