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 functions for loading .vqh and .vqd files
15 last mod: $Id: bookutil.c,v 1.8 2000/02/07 19:39:44 xiphmont Exp $
17 ********************************************************************/
24 #include "vorbis/codebook.h"
27 void codebook_unquantize(codebook *b){
29 const static_codebook *c=b->c;
30 double mindel=float24_unpack(c->q_min);
31 double delta=float24_unpack(c->q_delta);
32 if(!b->valuelist)b->valuelist=malloc(sizeof(double)*c->entries*c->dim);
34 for(j=0;j<c->entries;j++){
36 for(k=0;k<c->dim;k++){
37 double val=c->quantlist[j*c->dim+k]*delta+last+mindel;
38 b->valuelist[j*c->dim+k]=val;
39 if(c->q_sequencep)last=val;
45 /* A few little utils for reading files */
46 /* read a line. Use global, persistent buffering */
47 static char *linebuffer=NULL;
48 static int lbufsize=0;
49 char *get_line(FILE *in){
51 if(feof(in))return NULL;
57 if(sofar+1>=lbufsize){
60 linebuffer=malloc(lbufsize);
63 linebuffer=realloc(linebuffer,lbufsize);
70 if(sofar==0)return(NULL);
71 /* fallthrough correct */
73 linebuffer[sofar]='\0';
77 linebuffer[sofar++]=c;
78 linebuffer[sofar]='\0';
84 if(linebuffer[0]=='#'){
92 /* read the next numerical value from the given file */
93 static char *value_line_buff=NULL;
95 int get_line_value(FILE *in,double *value){
98 if(!value_line_buff)return(-1);
100 *value=strtod(value_line_buff, &next);
101 if(next==value_line_buff){
102 value_line_buff=NULL;
105 value_line_buff=next;
106 while(*value_line_buff>32)value_line_buff++;
111 int get_next_value(FILE *in,double *value){
113 if(get_line_value(in,value)){
114 value_line_buff=get_line(in);
115 if(!value_line_buff)return(-1);
122 int get_next_ivalue(FILE *in,long *ivalue){
124 int ret=get_next_value(in,&value);
129 static double sequence_base=0.;
130 static int v_sofar=0;
131 void reset_next_value(void){
132 value_line_buff=NULL;
137 int get_vector(codebook *b,FILE *in,int start, int n,double *a){
139 const static_codebook *c=b->c;
143 if(v_sofar==n || get_line_value(in,a)){
145 if(get_next_value(in,a))
147 for(i=0;i<start;i++){
149 get_line_value(in,a);
153 for(i=1;i<c->dim;i++)
154 if(get_line_value(in,a+i))
158 double temp=a[c->dim-1];
159 for(i=0;i<c->dim;i++)a[i]-=sequence_base;
160 if(c->q_sequencep)sequence_base=temp;
170 /* read lines fromt he beginning until we find one containing the
172 char *find_seek_to(FILE *in,char *s){
175 char *line=get_line(in);
185 /* this reads the format as written by vqbuild; innocent (legal)
186 tweaking of the file that would not affect its valid header-ness
187 will break this routine */
189 codebook *codebook_load(char *filename){
190 codebook *b=calloc(1,sizeof(codebook));
191 static_codebook *c=(static_codebook *)(b->c=calloc(1,sizeof(static_codebook)));
192 encode_aux *a=calloc(1,sizeof(encode_aux));
193 FILE *in=fopen(filename,"r");
200 fprintf(stderr,"Couldn't open codebook %s\n",filename);
204 /* find the codebook struct */
205 find_seek_to(in,"static static_codebook _vq_book_");
207 /* get the major important values */
209 if(sscanf(line,"%ld, %ld, %ld, %ld, %d, %d",
210 &(c->dim),&(c->entries),&(c->q_min),&(c->q_delta),&(c->q_quant),
211 &(c->q_sequencep))!=6){
212 fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
216 /* find the auxiliary encode struct (if any) */
217 find_seek_to(in,"static encode_aux _vq_aux_");
224 if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
225 fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line);
229 /* load the quantized entries */
230 find_seek_to(in,"static long _vq_quantlist_");
232 c->quantlist=malloc(sizeof(long)*c->entries*c->dim);
233 for(i=0;i<c->entries*c->dim;i++)
234 if(get_next_ivalue(in,c->quantlist+i)){
235 fprintf(stderr,"out of data while reading codebook %s\n",filename);
239 /* load the lengthlist */
240 find_seek_to(in,"static long _vq_lengthlist");
242 c->lengthlist=malloc(sizeof(long)*c->entries);
243 for(i=0;i<c->entries;i++)
244 if(get_next_ivalue(in,c->lengthlist+i)){
245 fprintf(stderr,"out of data while reading codebook %s\n",filename);
250 find_seek_to(in,"static long _vq_ptr0");
252 a->ptr0=malloc(sizeof(long)*a->aux);
253 for(i=0;i<a->aux;i++)
254 if(get_next_ivalue(in,a->ptr0+i)){
255 fprintf(stderr,"out of data while reading codebook %s\n",filename);
260 find_seek_to(in,"static long _vq_ptr1");
262 a->ptr1=malloc(sizeof(long)*a->aux);
263 for(i=0;i<a->aux;i++)
264 if(get_next_ivalue(in,a->ptr1+i)){
265 fprintf(stderr,"out of data while reading codebook %s\n",filename);
271 find_seek_to(in,"static long _vq_p_");
273 a->p=malloc(sizeof(long)*a->aux);
274 for(i=0;i<a->aux;i++)
275 if(get_next_ivalue(in,a->p+i)){
276 fprintf(stderr,"out of data while reading codebook %s\n",filename);
281 find_seek_to(in,"static long _vq_q_");
283 a->q=malloc(sizeof(long)*a->aux);
284 for(i=0;i<a->aux;i++)
285 if(get_next_ivalue(in,a->q+i)){
286 fprintf(stderr,"out of data while reading codebook %s\n",filename);
293 /* might as well unquantize the entries while we're at it */
294 codebook_unquantize(b);
296 /* don't need n and c */
300 int codebook_entry(codebook *b,double *val){
301 const static_codebook *c=b->c;
302 encode_aux *t=c->encode_tree;
304 double *n=alloca(c->dim*sizeof(double));
308 double *p=b->valuelist+t->p[ptr];
309 double *q=b->valuelist+t->q[ptr];
311 for(k=0;k<c->dim;k++){
317 for(k=0;k<c->dim;k++)
329 /* 24 bit float (not IEEE; nonnormalized mantissa +
330 biased exponent ): neeeeemm mmmmmmmm mmmmmmmm */
332 long float24_pack(double val){
340 exp= floor(log(val)/log(2));
341 mant=rint(ldexp(val,17-exp));
342 exp=(exp+VQ_FEXP_BIAS)<<18;
344 return(sign|exp|mant);
347 double float24_unpack(long val){
348 double mant=val&0x3ffff;
349 double sign=val&0x800000;
350 double exp =(val&0x7c0000)>>18;
352 return(ldexp(mant,exp-17-VQ_FEXP_BIAS));
355 void spinnit(char *s,int n){
357 static long lasttime=0;
359 struct timeval thistime;
361 gettimeofday(&thistime,NULL);
362 test=thistime.tv_sec*10+thistime.tv_usec/100000;
366 fprintf(stderr,"%s%d ",s,n);
371 fprintf(stderr,"| \r");
374 fprintf(stderr,"/ \r");
377 fprintf(stderr,"- \r");
380 fprintf(stderr,"\\ \r");