Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /******************************************************************** |
michael@0 | 2 | * * |
michael@0 | 3 | * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * |
michael@0 | 4 | * * |
michael@0 | 5 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
michael@0 | 6 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
michael@0 | 7 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
michael@0 | 8 | * * |
michael@0 | 9 | * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * |
michael@0 | 10 | * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * |
michael@0 | 11 | * * |
michael@0 | 12 | ******************************************************************** |
michael@0 | 13 | |
michael@0 | 14 | function: basic shared codebook operations |
michael@0 | 15 | |
michael@0 | 16 | ********************************************************************/ |
michael@0 | 17 | |
michael@0 | 18 | #include <stdlib.h> |
michael@0 | 19 | #include <math.h> |
michael@0 | 20 | #include <string.h> |
michael@0 | 21 | #include <ogg/ogg.h> |
michael@0 | 22 | #include "misc.h" |
michael@0 | 23 | #include "ivorbiscodec.h" |
michael@0 | 24 | #include "codebook.h" |
michael@0 | 25 | |
michael@0 | 26 | /**** pack/unpack helpers ******************************************/ |
michael@0 | 27 | int _ilog(unsigned int v){ |
michael@0 | 28 | int ret=0; |
michael@0 | 29 | while(v){ |
michael@0 | 30 | ret++; |
michael@0 | 31 | v>>=1; |
michael@0 | 32 | } |
michael@0 | 33 | return(ret); |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | /* 32 bit float (not IEEE; nonnormalized mantissa + |
michael@0 | 37 | biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm |
michael@0 | 38 | Why not IEEE? It's just not that important here. */ |
michael@0 | 39 | |
michael@0 | 40 | #define VQ_FEXP 10 |
michael@0 | 41 | #define VQ_FMAN 21 |
michael@0 | 42 | #define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ |
michael@0 | 43 | |
michael@0 | 44 | static ogg_int32_t _float32_unpack(long val,int *point){ |
michael@0 | 45 | long mant=val&0x1fffff; |
michael@0 | 46 | int sign=val&0x80000000; |
michael@0 | 47 | long exp =(val&0x7fe00000L)>>VQ_FMAN; |
michael@0 | 48 | |
michael@0 | 49 | exp-=(VQ_FMAN-1)+VQ_FEXP_BIAS; |
michael@0 | 50 | |
michael@0 | 51 | if(mant){ |
michael@0 | 52 | while(!(mant&0x40000000)){ |
michael@0 | 53 | mant<<=1; |
michael@0 | 54 | exp-=1; |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | if(sign)mant= -mant; |
michael@0 | 58 | }else{ |
michael@0 | 59 | sign=0; |
michael@0 | 60 | exp=-9999; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | *point=exp; |
michael@0 | 64 | return mant; |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | /* given a list of word lengths, generate a list of codewords. Works |
michael@0 | 68 | for length ordered or unordered, always assigns the lowest valued |
michael@0 | 69 | codewords first. Extended to handle unused entries (length 0) */ |
michael@0 | 70 | ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ |
michael@0 | 71 | long i,j,count=0; |
michael@0 | 72 | ogg_uint32_t marker[33]; |
michael@0 | 73 | ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); |
michael@0 | 74 | memset(marker,0,sizeof(marker)); |
michael@0 | 75 | |
michael@0 | 76 | for(i=0;i<n;i++){ |
michael@0 | 77 | long length=l[i]; |
michael@0 | 78 | if(length>0){ |
michael@0 | 79 | ogg_uint32_t entry=marker[length]; |
michael@0 | 80 | |
michael@0 | 81 | /* when we claim a node for an entry, we also claim the nodes |
michael@0 | 82 | below it (pruning off the imagined tree that may have dangled |
michael@0 | 83 | from it) as well as blocking the use of any nodes directly |
michael@0 | 84 | above for leaves */ |
michael@0 | 85 | |
michael@0 | 86 | /* update ourself */ |
michael@0 | 87 | if(length<32 && (entry>>length)){ |
michael@0 | 88 | /* error condition; the lengths must specify an overpopulated tree */ |
michael@0 | 89 | _ogg_free(r); |
michael@0 | 90 | return(NULL); |
michael@0 | 91 | } |
michael@0 | 92 | r[count++]=entry; |
michael@0 | 93 | |
michael@0 | 94 | /* Look to see if the next shorter marker points to the node |
michael@0 | 95 | above. if so, update it and repeat. */ |
michael@0 | 96 | { |
michael@0 | 97 | for(j=length;j>0;j--){ |
michael@0 | 98 | |
michael@0 | 99 | if(marker[j]&1){ |
michael@0 | 100 | /* have to jump branches */ |
michael@0 | 101 | if(j==1) |
michael@0 | 102 | marker[1]++; |
michael@0 | 103 | else |
michael@0 | 104 | marker[j]=marker[j-1]<<1; |
michael@0 | 105 | break; /* invariant says next upper marker would already |
michael@0 | 106 | have been moved if it was on the same path */ |
michael@0 | 107 | } |
michael@0 | 108 | marker[j]++; |
michael@0 | 109 | } |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | /* prune the tree; the implicit invariant says all the longer |
michael@0 | 113 | markers were dangling from our just-taken node. Dangle them |
michael@0 | 114 | from our *new* node. */ |
michael@0 | 115 | for(j=length+1;j<33;j++) |
michael@0 | 116 | if((marker[j]>>1) == entry){ |
michael@0 | 117 | entry=marker[j]; |
michael@0 | 118 | marker[j]=marker[j-1]<<1; |
michael@0 | 119 | }else |
michael@0 | 120 | break; |
michael@0 | 121 | }else |
michael@0 | 122 | if(sparsecount==0)count++; |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | /* sanity check the huffman tree; an underpopulated tree must be |
michael@0 | 126 | rejected. The only exception is the one-node pseudo-nil tree, |
michael@0 | 127 | which appears to be underpopulated because the tree doesn't |
michael@0 | 128 | really exist; there's only one possible 'codeword' or zero bits, |
michael@0 | 129 | but the above tree-gen code doesn't mark that. */ |
michael@0 | 130 | if(sparsecount != 1){ |
michael@0 | 131 | for(i=1;i<33;i++) |
michael@0 | 132 | if(marker[i] & (0xffffffffUL>>(32-i))){ |
michael@0 | 133 | _ogg_free(r); |
michael@0 | 134 | return(NULL); |
michael@0 | 135 | } |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | /* bitreverse the words because our bitwise packer/unpacker is LSb |
michael@0 | 139 | endian */ |
michael@0 | 140 | for(i=0,count=0;i<n;i++){ |
michael@0 | 141 | ogg_uint32_t temp=0; |
michael@0 | 142 | for(j=0;j<l[i];j++){ |
michael@0 | 143 | temp<<=1; |
michael@0 | 144 | temp|=(r[count]>>j)&1; |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | if(sparsecount){ |
michael@0 | 148 | if(l[i]) |
michael@0 | 149 | r[count++]=temp; |
michael@0 | 150 | }else |
michael@0 | 151 | r[count++]=temp; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | return(r); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | /* there might be a straightforward one-line way to do the below |
michael@0 | 158 | that's portable and totally safe against roundoff, but I haven't |
michael@0 | 159 | thought of it. Therefore, we opt on the side of caution */ |
michael@0 | 160 | long _book_maptype1_quantvals(const static_codebook *b){ |
michael@0 | 161 | /* get us a starting hint, we'll polish it below */ |
michael@0 | 162 | int bits=_ilog(b->entries); |
michael@0 | 163 | int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim); |
michael@0 | 164 | |
michael@0 | 165 | while(1){ |
michael@0 | 166 | long acc=1; |
michael@0 | 167 | long acc1=1; |
michael@0 | 168 | int i; |
michael@0 | 169 | for(i=0;i<b->dim;i++){ |
michael@0 | 170 | acc*=vals; |
michael@0 | 171 | acc1*=vals+1; |
michael@0 | 172 | } |
michael@0 | 173 | if(acc<=b->entries && acc1>b->entries){ |
michael@0 | 174 | return(vals); |
michael@0 | 175 | }else{ |
michael@0 | 176 | if(acc>b->entries){ |
michael@0 | 177 | vals--; |
michael@0 | 178 | }else{ |
michael@0 | 179 | vals++; |
michael@0 | 180 | } |
michael@0 | 181 | } |
michael@0 | 182 | } |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | /* different than what _book_unquantize does for mainline: |
michael@0 | 186 | we repack the book in a fixed point format that shares the same |
michael@0 | 187 | binary point. Upon first use, we can shift point if needed */ |
michael@0 | 188 | |
michael@0 | 189 | /* we need to deal with two map types: in map type 1, the values are |
michael@0 | 190 | generated algorithmically (each column of the vector counts through |
michael@0 | 191 | the values in the quant vector). in map type 2, all the values came |
michael@0 | 192 | in in an explicit list. Both value lists must be unpacked */ |
michael@0 | 193 | |
michael@0 | 194 | ogg_int32_t *_book_unquantize(const static_codebook *b,int n,int *sparsemap, |
michael@0 | 195 | int *maxpoint){ |
michael@0 | 196 | long j,k,count=0; |
michael@0 | 197 | if(b->maptype==1 || b->maptype==2){ |
michael@0 | 198 | int quantvals; |
michael@0 | 199 | int minpoint,delpoint; |
michael@0 | 200 | ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint); |
michael@0 | 201 | ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint); |
michael@0 | 202 | ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r)); |
michael@0 | 203 | int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp)); |
michael@0 | 204 | |
michael@0 | 205 | *maxpoint=minpoint; |
michael@0 | 206 | |
michael@0 | 207 | /* maptype 1 and 2 both use a quantized value vector, but |
michael@0 | 208 | different sizes */ |
michael@0 | 209 | switch(b->maptype){ |
michael@0 | 210 | case 1: |
michael@0 | 211 | /* most of the time, entries%dimensions == 0, but we need to be |
michael@0 | 212 | well defined. We define that the possible vales at each |
michael@0 | 213 | scalar is values == entries/dim. If entries%dim != 0, we'll |
michael@0 | 214 | have 'too few' values (values*dim<entries), which means that |
michael@0 | 215 | we'll have 'left over' entries; left over entries use zeroed |
michael@0 | 216 | values (and are wasted). So don't generate codebooks like |
michael@0 | 217 | that */ |
michael@0 | 218 | quantvals=_book_maptype1_quantvals(b); |
michael@0 | 219 | for(j=0;j<b->entries;j++){ |
michael@0 | 220 | if((sparsemap && b->lengthlist[j]) || !sparsemap){ |
michael@0 | 221 | ogg_int32_t last=0; |
michael@0 | 222 | int lastpoint=0; |
michael@0 | 223 | int indexdiv=1; |
michael@0 | 224 | for(k=0;k<b->dim;k++){ |
michael@0 | 225 | int index= (j/indexdiv)%quantvals; |
michael@0 | 226 | int point=0; |
michael@0 | 227 | int val=VFLOAT_MULTI(delta,delpoint, |
michael@0 | 228 | abs(b->quantlist[index]),&point); |
michael@0 | 229 | |
michael@0 | 230 | val=VFLOAT_ADD(mindel,minpoint,val,point,&point); |
michael@0 | 231 | val=VFLOAT_ADD(last,lastpoint,val,point,&point); |
michael@0 | 232 | |
michael@0 | 233 | if(b->q_sequencep){ |
michael@0 | 234 | last=val; |
michael@0 | 235 | lastpoint=point; |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | if(sparsemap){ |
michael@0 | 239 | r[sparsemap[count]*b->dim+k]=val; |
michael@0 | 240 | rp[sparsemap[count]*b->dim+k]=point; |
michael@0 | 241 | }else{ |
michael@0 | 242 | r[count*b->dim+k]=val; |
michael@0 | 243 | rp[count*b->dim+k]=point; |
michael@0 | 244 | } |
michael@0 | 245 | if(*maxpoint<point)*maxpoint=point; |
michael@0 | 246 | indexdiv*=quantvals; |
michael@0 | 247 | } |
michael@0 | 248 | count++; |
michael@0 | 249 | } |
michael@0 | 250 | |
michael@0 | 251 | } |
michael@0 | 252 | break; |
michael@0 | 253 | case 2: |
michael@0 | 254 | for(j=0;j<b->entries;j++){ |
michael@0 | 255 | if((sparsemap && b->lengthlist[j]) || !sparsemap){ |
michael@0 | 256 | ogg_int32_t last=0; |
michael@0 | 257 | int lastpoint=0; |
michael@0 | 258 | |
michael@0 | 259 | for(k=0;k<b->dim;k++){ |
michael@0 | 260 | int point=0; |
michael@0 | 261 | int val=VFLOAT_MULTI(delta,delpoint, |
michael@0 | 262 | abs(b->quantlist[j*b->dim+k]),&point); |
michael@0 | 263 | |
michael@0 | 264 | val=VFLOAT_ADD(mindel,minpoint,val,point,&point); |
michael@0 | 265 | val=VFLOAT_ADD(last,lastpoint,val,point,&point); |
michael@0 | 266 | |
michael@0 | 267 | if(b->q_sequencep){ |
michael@0 | 268 | last=val; |
michael@0 | 269 | lastpoint=point; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | if(sparsemap){ |
michael@0 | 273 | r[sparsemap[count]*b->dim+k]=val; |
michael@0 | 274 | rp[sparsemap[count]*b->dim+k]=point; |
michael@0 | 275 | }else{ |
michael@0 | 276 | r[count*b->dim+k]=val; |
michael@0 | 277 | rp[count*b->dim+k]=point; |
michael@0 | 278 | } |
michael@0 | 279 | if(*maxpoint<point)*maxpoint=point; |
michael@0 | 280 | } |
michael@0 | 281 | count++; |
michael@0 | 282 | } |
michael@0 | 283 | } |
michael@0 | 284 | break; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | for(j=0;j<n*b->dim;j++) |
michael@0 | 288 | if(rp[j]<*maxpoint) |
michael@0 | 289 | r[j]>>=*maxpoint-rp[j]; |
michael@0 | 290 | |
michael@0 | 291 | _ogg_free(rp); |
michael@0 | 292 | return(r); |
michael@0 | 293 | } |
michael@0 | 294 | return(NULL); |
michael@0 | 295 | } |
michael@0 | 296 | |
michael@0 | 297 | void vorbis_staticbook_destroy(static_codebook *b){ |
michael@0 | 298 | if(b->quantlist)_ogg_free(b->quantlist); |
michael@0 | 299 | if(b->lengthlist)_ogg_free(b->lengthlist); |
michael@0 | 300 | memset(b,0,sizeof(*b)); |
michael@0 | 301 | _ogg_free(b); |
michael@0 | 302 | } |
michael@0 | 303 | |
michael@0 | 304 | void vorbis_book_clear(codebook *b){ |
michael@0 | 305 | /* static book is not cleared; we're likely called on the lookup and |
michael@0 | 306 | the static codebook belongs to the info struct */ |
michael@0 | 307 | if(b->valuelist)_ogg_free(b->valuelist); |
michael@0 | 308 | if(b->codelist)_ogg_free(b->codelist); |
michael@0 | 309 | |
michael@0 | 310 | if(b->dec_index)_ogg_free(b->dec_index); |
michael@0 | 311 | if(b->dec_codelengths)_ogg_free(b->dec_codelengths); |
michael@0 | 312 | if(b->dec_firsttable)_ogg_free(b->dec_firsttable); |
michael@0 | 313 | |
michael@0 | 314 | memset(b,0,sizeof(*b)); |
michael@0 | 315 | } |
michael@0 | 316 | |
michael@0 | 317 | static ogg_uint32_t bitreverse(ogg_uint32_t x){ |
michael@0 | 318 | x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); |
michael@0 | 319 | x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); |
michael@0 | 320 | x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); |
michael@0 | 321 | x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); |
michael@0 | 322 | return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | static int sort32a(const void *a,const void *b){ |
michael@0 | 326 | return (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- |
michael@0 | 327 | (**(ogg_uint32_t **)a<**(ogg_uint32_t **)b); |
michael@0 | 328 | } |
michael@0 | 329 | |
michael@0 | 330 | /* decode codebook arrangement is more heavily optimized than encode */ |
michael@0 | 331 | int vorbis_book_init_decode(codebook *c,const static_codebook *s){ |
michael@0 | 332 | int i,j,n=0,tabn; |
michael@0 | 333 | int *sortindex; |
michael@0 | 334 | memset(c,0,sizeof(*c)); |
michael@0 | 335 | |
michael@0 | 336 | /* count actually used entries */ |
michael@0 | 337 | for(i=0;i<s->entries;i++) |
michael@0 | 338 | if(s->lengthlist[i]>0) |
michael@0 | 339 | n++; |
michael@0 | 340 | |
michael@0 | 341 | c->entries=s->entries; |
michael@0 | 342 | c->used_entries=n; |
michael@0 | 343 | c->dim=s->dim; |
michael@0 | 344 | |
michael@0 | 345 | if(n>0){ |
michael@0 | 346 | /* two different remappings go on here. |
michael@0 | 347 | |
michael@0 | 348 | First, we collapse the likely sparse codebook down only to |
michael@0 | 349 | actually represented values/words. This collapsing needs to be |
michael@0 | 350 | indexed as map-valueless books are used to encode original entry |
michael@0 | 351 | positions as integers. |
michael@0 | 352 | |
michael@0 | 353 | Second, we reorder all vectors, including the entry index above, |
michael@0 | 354 | by sorted bitreversed codeword to allow treeless decode. */ |
michael@0 | 355 | |
michael@0 | 356 | /* perform sort */ |
michael@0 | 357 | ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); |
michael@0 | 358 | ogg_uint32_t **codep=(ogg_uint32_t **)alloca(sizeof(*codep)*n); |
michael@0 | 359 | |
michael@0 | 360 | if(codes==NULL)goto err_out; |
michael@0 | 361 | |
michael@0 | 362 | for(i=0;i<n;i++){ |
michael@0 | 363 | codes[i]=bitreverse(codes[i]); |
michael@0 | 364 | codep[i]=codes+i; |
michael@0 | 365 | } |
michael@0 | 366 | |
michael@0 | 367 | qsort(codep,n,sizeof(*codep),sort32a); |
michael@0 | 368 | |
michael@0 | 369 | sortindex=(int *)alloca(n*sizeof(*sortindex)); |
michael@0 | 370 | c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist)); |
michael@0 | 371 | /* the index is a reverse index */ |
michael@0 | 372 | for(i=0;i<n;i++){ |
michael@0 | 373 | int position=codep[i]-codes; |
michael@0 | 374 | sortindex[position]=i; |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | for(i=0;i<n;i++) |
michael@0 | 378 | c->codelist[sortindex[i]]=codes[i]; |
michael@0 | 379 | _ogg_free(codes); |
michael@0 | 380 | |
michael@0 | 381 | |
michael@0 | 382 | |
michael@0 | 383 | c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint); |
michael@0 | 384 | c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index)); |
michael@0 | 385 | |
michael@0 | 386 | for(n=0,i=0;i<s->entries;i++) |
michael@0 | 387 | if(s->lengthlist[i]>0) |
michael@0 | 388 | c->dec_index[sortindex[n++]]=i; |
michael@0 | 389 | |
michael@0 | 390 | c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths)); |
michael@0 | 391 | for(n=0,i=0;i<s->entries;i++) |
michael@0 | 392 | if(s->lengthlist[i]>0) |
michael@0 | 393 | c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; |
michael@0 | 394 | |
michael@0 | 395 | c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ |
michael@0 | 396 | if(c->dec_firsttablen<5)c->dec_firsttablen=5; |
michael@0 | 397 | if(c->dec_firsttablen>8)c->dec_firsttablen=8; |
michael@0 | 398 | |
michael@0 | 399 | tabn=1<<c->dec_firsttablen; |
michael@0 | 400 | c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); |
michael@0 | 401 | c->dec_maxlength=0; |
michael@0 | 402 | |
michael@0 | 403 | for(i=0;i<n;i++){ |
michael@0 | 404 | if(c->dec_maxlength<c->dec_codelengths[i]) |
michael@0 | 405 | c->dec_maxlength=c->dec_codelengths[i]; |
michael@0 | 406 | if(c->dec_codelengths[i]<=c->dec_firsttablen){ |
michael@0 | 407 | ogg_uint32_t orig=bitreverse(c->codelist[i]); |
michael@0 | 408 | for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) |
michael@0 | 409 | c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1; |
michael@0 | 410 | } |
michael@0 | 411 | } |
michael@0 | 412 | |
michael@0 | 413 | /* now fill in 'unused' entries in the firsttable with hi/lo search |
michael@0 | 414 | hints for the non-direct-hits */ |
michael@0 | 415 | { |
michael@0 | 416 | ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); |
michael@0 | 417 | long lo=0,hi=0; |
michael@0 | 418 | |
michael@0 | 419 | for(i=0;i<tabn;i++){ |
michael@0 | 420 | ogg_uint32_t word=i<<(32-c->dec_firsttablen); |
michael@0 | 421 | if(c->dec_firsttable[bitreverse(word)]==0){ |
michael@0 | 422 | while((lo+1)<n && c->codelist[lo+1]<=word)lo++; |
michael@0 | 423 | while( hi<n && word>=(c->codelist[hi]&mask))hi++; |
michael@0 | 424 | |
michael@0 | 425 | /* we only actually have 15 bits per hint to play with here. |
michael@0 | 426 | In order to overflow gracefully (nothing breaks, efficiency |
michael@0 | 427 | just drops), encode as the difference from the extremes. */ |
michael@0 | 428 | { |
michael@0 | 429 | unsigned long loval=lo; |
michael@0 | 430 | unsigned long hival=n-hi; |
michael@0 | 431 | |
michael@0 | 432 | if(loval>0x7fff)loval=0x7fff; |
michael@0 | 433 | if(hival>0x7fff)hival=0x7fff; |
michael@0 | 434 | c->dec_firsttable[bitreverse(word)]= |
michael@0 | 435 | 0x80000000UL | (loval<<15) | hival; |
michael@0 | 436 | } |
michael@0 | 437 | } |
michael@0 | 438 | } |
michael@0 | 439 | } |
michael@0 | 440 | } |
michael@0 | 441 | |
michael@0 | 442 | return(0); |
michael@0 | 443 | err_out: |
michael@0 | 444 | vorbis_book_clear(c); |
michael@0 | 445 | return(-1); |
michael@0 | 446 | } |
michael@0 | 447 |