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.1 2000/01/05 10:14:54 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;
59 linebuffer=malloc(lbufsize);
62 linebuffer=realloc(linebuffer,lbufsize);
73 linebuffer[sofar++]=c;
74 linebuffer[sofar]='\0';
80 if(linebuffer[0]=='#'){
88 /* read the next numerical value from the given file */
89 static char *value_line_buff=NULL;
91 int get_line_value(FILE *in,double *value){
94 if(!value_line_buff)return(-1);
96 *value=strtod(value_line_buff, &next);
97 if(next==value_line_buff){
101 value_line_buff=next+1;
106 int get_next_value(FILE *in,double *value){
108 if(get_line_value(in,value)){
109 value_line_buff=get_line(in);
110 if(!value_line_buff)return(-1);
117 int get_next_ivalue(FILE *in,long *ivalue){
119 int ret=get_next_value(in,&value);
124 static double sequence_base=0.;
125 void reset_next_value(void){
126 value_line_buff=NULL;
130 int get_vector(codebook *b,FILE *in,double *a){
135 if(get_next_value(in,a))
138 for(i=1;i<b->dim;i++)
139 if(get_line_value(in,a+i))
143 for(i=0;i<b->dim;i++)a[i]-=sequence_base;
144 if(b->q_sequencep)sequence_base=a[b->dim-1];
153 /* read lines fromt he beginning until we find one containing the
155 char *find_seek_to(FILE *in,char *s){
158 char *line=get_line(in);
168 /* this reads the format as written by vqbuild; innocent (legal)
169 tweaking of the file that would not affect its valid header-ness
170 will break this routine */
172 codebook *codebook_load(char *filename){
173 codebook *b=calloc(1,sizeof(codebook));
174 encode_aux *a=calloc(1,sizeof(encode_aux));
175 FILE *in=fopen(filename,"r");
182 fprintf(stderr,"Couldn't open codebook %s\n",filename);
186 /* find the codebook struct */
187 find_seek_to(in,"static codebook _vq_book_");
189 /* get the major important values */
191 if(sscanf(line,"%ld, %ld, %ld, %ld, %d, %d",
192 &(b->dim),&(b->entries),&(b->q_min),&(b->q_delta),&(b->q_quant),
193 &(b->q_sequencep))!=6){
194 fprintf(stderr,"syntax in %s in line:\t %s",filename,line);
198 /* find the auxiliary encode struct (if any) */
199 find_seek_to(in,"static encode_aux _vq_aux_");
208 if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
209 fprintf(stderr,"syntax in %s in line:\t %s",filename,line);
213 /* load the quantized entries */
214 find_seek_to(in,"static long _vq_quantlist_");
216 b->quantlist=malloc(sizeof(long)*b->entries*b->dim);
217 for(i=0;i<b->entries*b->dim;i++)
218 if(get_next_ivalue(in,b->quantlist+i)){
219 fprintf(stderr,"out of data while reading codebook %s\n",filename);
223 /* load the codewords */
224 find_seek_to(in,"static long _vq_codelist");
226 b->codelist=malloc(sizeof(long)*b->entries);
227 for(i=0;i<b->entries;i++)
228 if(get_next_ivalue(in,b->codelist+i)){
229 fprintf(stderr,"out of data while reading codebook %s\n",filename);
233 /* load the lengthlist */
234 find_seek_to(in,"static long _vq_lengthlist");
236 b->lengthlist=malloc(sizeof(long)*b->entries);
237 for(i=0;i<b->entries;i++)
238 if(get_next_ivalue(in,b->lengthlist+i)){
239 fprintf(stderr,"out of data while reading codebook %s\n",filename);
244 find_seek_to(in,"static long _vq_ptr0");
246 a->ptr0=malloc(sizeof(long)*a->aux);
247 for(i=0;i<a->aux;i++)
248 if(get_next_ivalue(in,a->ptr0+i)){
249 fprintf(stderr,"out of data while reading codebook %s\n",filename);
254 find_seek_to(in,"static long _vq_ptr1");
256 a->ptr1=malloc(sizeof(long)*a->aux);
257 for(i=0;i<a->aux;i++)
258 if(get_next_ivalue(in,a->ptr1+i)){
259 fprintf(stderr,"out of data while reading codebook %s\n",filename);
265 find_seek_to(in,"static long _vq_p_");
267 a->p=malloc(sizeof(long)*a->aux);
268 for(i=0;i<a->aux;i++)
269 if(get_next_ivalue(in,a->p+i)){
270 fprintf(stderr,"out of data while reading codebook %s\n",filename);
275 find_seek_to(in,"static long _vq_q_");
277 a->q=malloc(sizeof(long)*a->aux);
278 for(i=0;i<a->aux;i++)
279 if(get_next_ivalue(in,a->q+i)){
280 fprintf(stderr,"out of data while reading codebook %s\n",filename);
287 /* might as well unquantize the entries while we're at it */
288 codebook_unquantize(b);
290 /* don't need n and c */
294 int codebook_entry(codebook *b,double *val){
295 encode_aux *t=b->encode_tree;
297 double *n=alloca(b->dim*sizeof(double));
301 double *p=b->valuelist+t->p[ptr]*b->dim;
302 double *q=b->valuelist+t->q[ptr]*b->dim;
304 for(k=0;k<b->dim;k++){
310 for(k=0;k<b->dim;k++)
321 /* 24 bit float (not IEEE; nonnormalized mantissa +
322 biased exponent ): neeeeemm mmmmmmmm mmmmmmmm */
324 #define VQ_FEXP_BIAS 20 /* bias toward values smaller than 1. */
325 long float24_pack(double val){
333 exp= floor(log(val)/log(2));
334 mant=rint(ldexp(val,17-exp));
335 exp=(exp+VQ_FEXP_BIAS)<<18;
337 return(sign|exp|mant);
340 double float24_unpack(long val){
341 double mant=val&0x3ffff;
342 double sign=val&0x800000;
343 double exp =(val&0x7c0000)>>18;
345 return(ldexp(mant,exp-17-VQ_FEXP_BIAS));