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.4 2000/01/10 10:42:01 xiphmont Exp $
17 ********************************************************************/
24 #include "vorbis/codebook.h"
27 void codebook_unquantize(codebook *b){
29 double mindel=float24_unpack(b->q_min);
30 double delta=float24_unpack(b->q_delta);
31 if(!b->valuelist)b->valuelist=malloc(sizeof(double)*b->entries*b->dim);
33 for(j=0;j<b->entries;j++){
35 for(k=0;k<b->dim;k++){
36 double val=b->quantlist[j*b->dim+k]*delta+last+mindel;
37 b->valuelist[j*b->dim+k]=val;
38 if(b->q_sequencep)last=val;
44 /* A few little utils for reading files */
45 /* read a line. Use global, persistent buffering */
46 static char *linebuffer=NULL;
47 static int lbufsize=0;
48 char *get_line(FILE *in){
50 if(feof(in))return NULL;
56 if(sofar+1>=lbufsize){
59 linebuffer=malloc(lbufsize);
62 linebuffer=realloc(linebuffer,lbufsize);
69 if(sofar==0)return(NULL);
70 /* fallthrough correct */
72 linebuffer[sofar]='\0';
76 linebuffer[sofar++]=c;
77 linebuffer[sofar]='\0';
83 if(linebuffer[0]=='#'){
91 /* read the next numerical value from the given file */
92 static char *value_line_buff=NULL;
94 int get_line_value(FILE *in,double *value){
97 if(!value_line_buff)return(-1);
99 *value=strtod(value_line_buff, &next);
100 if(next==value_line_buff){
101 value_line_buff=NULL;
104 value_line_buff=next+1;
109 int get_next_value(FILE *in,double *value){
111 if(get_line_value(in,value)){
112 value_line_buff=get_line(in);
113 if(!value_line_buff)return(-1);
120 int get_next_ivalue(FILE *in,long *ivalue){
122 int ret=get_next_value(in,&value);
127 static double sequence_base=0.;
128 static int v_sofar=0;
129 void reset_next_value(void){
130 value_line_buff=NULL;
135 int get_vector(codebook *b,FILE *in,int start, int n,double *a){
140 if(v_sofar==n || get_line_value(in,a)){
142 if(get_next_value(in,a))
144 for(i=0;i<start;i++){
146 get_line_value(in,a);
150 for(i=1;i<b->dim;i++)
151 if(get_line_value(in,a+i))
155 double temp=a[b->dim-1];
156 for(i=0;i<b->dim;i++)a[i]-=sequence_base;
157 if(b->q_sequencep)sequence_base=temp;
167 /* read lines fromt he beginning until we find one containing the
169 char *find_seek_to(FILE *in,char *s){
172 char *line=get_line(in);
182 /* this reads the format as written by vqbuild; innocent (legal)
183 tweaking of the file that would not affect its valid header-ness
184 will break this routine */
186 codebook *codebook_load(char *filename){
187 codebook *b=calloc(1,sizeof(codebook));
188 encode_aux *a=calloc(1,sizeof(encode_aux));
189 FILE *in=fopen(filename,"r");
196 fprintf(stderr,"Couldn't open codebook %s\n",filename);
200 /* find the codebook struct */
201 find_seek_to(in,"static codebook _vq_book_");
203 /* get the major important values */
205 if(sscanf(line,"%ld, %ld, %ld, %ld, %d, %d",
206 &(b->dim),&(b->entries),&(b->q_min),&(b->q_delta),&(b->q_quant),
207 &(b->q_sequencep))!=6){
208 fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
212 /* find the auxiliary encode struct (if any) */
213 find_seek_to(in,"static encode_aux _vq_aux_");
222 if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
223 fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line);
227 /* load the quantized entries */
228 find_seek_to(in,"static long _vq_quantlist_");
230 b->quantlist=malloc(sizeof(long)*b->entries*b->dim);
231 for(i=0;i<b->entries*b->dim;i++)
232 if(get_next_ivalue(in,b->quantlist+i)){
233 fprintf(stderr,"out of data while reading codebook %s\n",filename);
237 /* load the codewords */
238 find_seek_to(in,"static long _vq_codelist");
240 b->codelist=malloc(sizeof(long)*b->entries);
241 for(i=0;i<b->entries;i++)
242 if(get_next_ivalue(in,b->codelist+i)){
243 fprintf(stderr,"out of data while reading codebook %s\n",filename);
247 /* load the lengthlist */
248 find_seek_to(in,"static long _vq_lengthlist");
250 b->lengthlist=malloc(sizeof(long)*b->entries);
251 for(i=0;i<b->entries;i++)
252 if(get_next_ivalue(in,b->lengthlist+i)){
253 fprintf(stderr,"out of data while reading codebook %s\n",filename);
258 find_seek_to(in,"static long _vq_ptr0");
260 a->ptr0=malloc(sizeof(long)*a->aux);
261 for(i=0;i<a->aux;i++)
262 if(get_next_ivalue(in,a->ptr0+i)){
263 fprintf(stderr,"out of data while reading codebook %s\n",filename);
268 find_seek_to(in,"static long _vq_ptr1");
270 a->ptr1=malloc(sizeof(long)*a->aux);
271 for(i=0;i<a->aux;i++)
272 if(get_next_ivalue(in,a->ptr1+i)){
273 fprintf(stderr,"out of data while reading codebook %s\n",filename);
279 find_seek_to(in,"static long _vq_p_");
281 a->p=malloc(sizeof(long)*a->aux);
282 for(i=0;i<a->aux;i++)
283 if(get_next_ivalue(in,a->p+i)){
284 fprintf(stderr,"out of data while reading codebook %s\n",filename);
289 find_seek_to(in,"static long _vq_q_");
291 a->q=malloc(sizeof(long)*a->aux);
292 for(i=0;i<a->aux;i++)
293 if(get_next_ivalue(in,a->q+i)){
294 fprintf(stderr,"out of data while reading codebook %s\n",filename);
301 /* might as well unquantize the entries while we're at it */
302 codebook_unquantize(b);
304 /* don't need n and c */
308 int codebook_entry(codebook *b,double *val){
309 encode_aux *t=b->encode_tree;
311 double *n=alloca(b->dim*sizeof(double));
315 double *p=b->valuelist+t->p[ptr]*b->dim;
316 double *q=b->valuelist+t->q[ptr]*b->dim;
318 for(k=0;k<b->dim;k++){
324 for(k=0;k<b->dim;k++)
335 /* 24 bit float (not IEEE; nonnormalized mantissa +
336 biased exponent ): neeeeemm mmmmmmmm mmmmmmmm */
338 #define VQ_FEXP_BIAS 20 /* bias toward values smaller than 1. */
339 long float24_pack(double val){
347 exp= floor(log(val)/log(2));
348 mant=rint(ldexp(val,17-exp));
349 exp=(exp+VQ_FEXP_BIAS)<<18;
351 return(sign|exp|mant);
354 double float24_unpack(long val){
355 double mant=val&0x3ffff;
356 double sign=val&0x800000;
357 double exp =(val&0x7c0000)>>18;
359 return(ldexp(mant,exp-17-VQ_FEXP_BIAS));
362 void spinnit(char *s,int n){
364 static long lasttime=0;
366 struct timeval thistime;
368 gettimeofday(&thistime,NULL);
369 test=thistime.tv_sec*10+thistime.tv_usec/100000;
373 fprintf(stderr,"%s%d ",s,n);
378 fprintf(stderr,"| \r");
381 fprintf(stderr,"/ \r");
384 fprintf(stderr,"- \r");
387 fprintf(stderr,"\\ \r");