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.3 2000/01/06 13:57:10 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);
70 linebuffer[sofar]='\0';
74 linebuffer[sofar++]=c;
75 linebuffer[sofar]='\0';
81 if(linebuffer[0]=='#'){
89 /* read the next numerical value from the given file */
90 static char *value_line_buff=NULL;
92 int get_line_value(FILE *in,double *value){
95 if(!value_line_buff)return(-1);
97 *value=strtod(value_line_buff, &next);
98 if(next==value_line_buff){
102 value_line_buff=next+1;
107 int get_next_value(FILE *in,double *value){
109 if(get_line_value(in,value)){
110 value_line_buff=get_line(in);
111 if(!value_line_buff)return(-1);
118 int get_next_ivalue(FILE *in,long *ivalue){
120 int ret=get_next_value(in,&value);
125 static double sequence_base=0.;
126 void reset_next_value(void){
127 value_line_buff=NULL;
131 int get_vector(codebook *b,FILE *in,double *a){
136 if(get_line_value(in,a)){
138 if(get_next_value(in,a))
142 for(i=1;i<b->dim;i++)
143 if(get_line_value(in,a+i))
147 double temp=a[b->dim-1];
148 for(i=0;i<b->dim;i++)a[i]-=sequence_base;
149 if(b->q_sequencep)sequence_base=temp;
158 /* read lines fromt he beginning until we find one containing the
160 char *find_seek_to(FILE *in,char *s){
163 char *line=get_line(in);
173 /* this reads the format as written by vqbuild; innocent (legal)
174 tweaking of the file that would not affect its valid header-ness
175 will break this routine */
177 codebook *codebook_load(char *filename){
178 codebook *b=calloc(1,sizeof(codebook));
179 encode_aux *a=calloc(1,sizeof(encode_aux));
180 FILE *in=fopen(filename,"r");
187 fprintf(stderr,"Couldn't open codebook %s\n",filename);
191 /* find the codebook struct */
192 find_seek_to(in,"static codebook _vq_book_");
194 /* get the major important values */
196 if(sscanf(line,"%ld, %ld, %ld, %ld, %d, %d",
197 &(b->dim),&(b->entries),&(b->q_min),&(b->q_delta),&(b->q_quant),
198 &(b->q_sequencep))!=6){
199 fprintf(stderr,"syntax in %s in line:\t %s",filename,line);
203 /* find the auxiliary encode struct (if any) */
204 find_seek_to(in,"static encode_aux _vq_aux_");
213 if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
214 fprintf(stderr,"syntax in %s in line:\t %s",filename,line);
218 /* load the quantized entries */
219 find_seek_to(in,"static long _vq_quantlist_");
221 b->quantlist=malloc(sizeof(long)*b->entries*b->dim);
222 for(i=0;i<b->entries*b->dim;i++)
223 if(get_next_ivalue(in,b->quantlist+i)){
224 fprintf(stderr,"out of data while reading codebook %s\n",filename);
228 /* load the codewords */
229 find_seek_to(in,"static long _vq_codelist");
231 b->codelist=malloc(sizeof(long)*b->entries);
232 for(i=0;i<b->entries;i++)
233 if(get_next_ivalue(in,b->codelist+i)){
234 fprintf(stderr,"out of data while reading codebook %s\n",filename);
238 /* load the lengthlist */
239 find_seek_to(in,"static long _vq_lengthlist");
241 b->lengthlist=malloc(sizeof(long)*b->entries);
242 for(i=0;i<b->entries;i++)
243 if(get_next_ivalue(in,b->lengthlist+i)){
244 fprintf(stderr,"out of data while reading codebook %s\n",filename);
249 find_seek_to(in,"static long _vq_ptr0");
251 a->ptr0=malloc(sizeof(long)*a->aux);
252 for(i=0;i<a->aux;i++)
253 if(get_next_ivalue(in,a->ptr0+i)){
254 fprintf(stderr,"out of data while reading codebook %s\n",filename);
259 find_seek_to(in,"static long _vq_ptr1");
261 a->ptr1=malloc(sizeof(long)*a->aux);
262 for(i=0;i<a->aux;i++)
263 if(get_next_ivalue(in,a->ptr1+i)){
264 fprintf(stderr,"out of data while reading codebook %s\n",filename);
270 find_seek_to(in,"static long _vq_p_");
272 a->p=malloc(sizeof(long)*a->aux);
273 for(i=0;i<a->aux;i++)
274 if(get_next_ivalue(in,a->p+i)){
275 fprintf(stderr,"out of data while reading codebook %s\n",filename);
280 find_seek_to(in,"static long _vq_q_");
282 a->q=malloc(sizeof(long)*a->aux);
283 for(i=0;i<a->aux;i++)
284 if(get_next_ivalue(in,a->q+i)){
285 fprintf(stderr,"out of data while reading codebook %s\n",filename);
292 /* might as well unquantize the entries while we're at it */
293 codebook_unquantize(b);
295 /* don't need n and c */
299 int codebook_entry(codebook *b,double *val){
300 encode_aux *t=b->encode_tree;
302 double *n=alloca(b->dim*sizeof(double));
306 double *p=b->valuelist+t->p[ptr]*b->dim;
307 double *q=b->valuelist+t->q[ptr]*b->dim;
309 for(k=0;k<b->dim;k++){
315 for(k=0;k<b->dim;k++)
326 /* 24 bit float (not IEEE; nonnormalized mantissa +
327 biased exponent ): neeeeemm mmmmmmmm mmmmmmmm */
329 #define VQ_FEXP_BIAS 20 /* bias toward values smaller than 1. */
330 long float24_pack(double val){
338 exp= floor(log(val)/log(2));
339 mant=rint(ldexp(val,17-exp));
340 exp=(exp+VQ_FEXP_BIAS)<<18;
342 return(sign|exp|mant);
345 double float24_unpack(long val){
346 double mant=val&0x3ffff;
347 double sign=val&0x800000;
348 double exp =(val&0x7c0000)>>18;
350 return(ldexp(mant,exp-17-VQ_FEXP_BIAS));
353 void spinnit(char *s,int n){
355 static long lasttime=0;
357 struct timeval thistime;
359 gettimeofday(&thistime,NULL);
360 test=thistime.tv_sec*10+thistime.tv_usec/100000;
364 fprintf(stderr,"%s%d ",s,n);
369 fprintf(stderr,"| \r");
372 fprintf(stderr,"/ \r");
375 fprintf(stderr,"- \r");
378 fprintf(stderr,"\\ \r");