media/libvorbis/lib/vorbis_codebook.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 SOFTWARE CODEC SOURCE CODE. *
michael@0 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
michael@0 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
michael@0 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
michael@0 7 * *
michael@0 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
michael@0 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
michael@0 10 * *
michael@0 11 ********************************************************************
michael@0 12
michael@0 13 function: basic codebook pack/unpack/code/decode operations
michael@0 14 last mod: $Id: codebook.c 19057 2014-01-22 12:32:31Z xiphmont $
michael@0 15
michael@0 16 ********************************************************************/
michael@0 17
michael@0 18 #include <stdlib.h>
michael@0 19 #include <string.h>
michael@0 20 #include <math.h>
michael@0 21 #include <ogg/ogg.h>
michael@0 22 #include "vorbis/codec.h"
michael@0 23 #include "codebook.h"
michael@0 24 #include "scales.h"
michael@0 25 #include "misc.h"
michael@0 26 #include "os.h"
michael@0 27
michael@0 28 /* packs the given codebook into the bitstream **************************/
michael@0 29
michael@0 30 int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
michael@0 31 long i,j;
michael@0 32 int ordered=0;
michael@0 33
michael@0 34 /* first the basic parameters */
michael@0 35 oggpack_write(opb,0x564342,24);
michael@0 36 oggpack_write(opb,c->dim,16);
michael@0 37 oggpack_write(opb,c->entries,24);
michael@0 38
michael@0 39 /* pack the codewords. There are two packings; length ordered and
michael@0 40 length random. Decide between the two now. */
michael@0 41
michael@0 42 for(i=1;i<c->entries;i++)
michael@0 43 if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break;
michael@0 44 if(i==c->entries)ordered=1;
michael@0 45
michael@0 46 if(ordered){
michael@0 47 /* length ordered. We only need to say how many codewords of
michael@0 48 each length. The actual codewords are generated
michael@0 49 deterministically */
michael@0 50
michael@0 51 long count=0;
michael@0 52 oggpack_write(opb,1,1); /* ordered */
michael@0 53 oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
michael@0 54
michael@0 55 for(i=1;i<c->entries;i++){
michael@0 56 char this=c->lengthlist[i];
michael@0 57 char last=c->lengthlist[i-1];
michael@0 58 if(this>last){
michael@0 59 for(j=last;j<this;j++){
michael@0 60 oggpack_write(opb,i-count,_ilog(c->entries-count));
michael@0 61 count=i;
michael@0 62 }
michael@0 63 }
michael@0 64 }
michael@0 65 oggpack_write(opb,i-count,_ilog(c->entries-count));
michael@0 66
michael@0 67 }else{
michael@0 68 /* length random. Again, we don't code the codeword itself, just
michael@0 69 the length. This time, though, we have to encode each length */
michael@0 70 oggpack_write(opb,0,1); /* unordered */
michael@0 71
michael@0 72 /* algortihmic mapping has use for 'unused entries', which we tag
michael@0 73 here. The algorithmic mapping happens as usual, but the unused
michael@0 74 entry has no codeword. */
michael@0 75 for(i=0;i<c->entries;i++)
michael@0 76 if(c->lengthlist[i]==0)break;
michael@0 77
michael@0 78 if(i==c->entries){
michael@0 79 oggpack_write(opb,0,1); /* no unused entries */
michael@0 80 for(i=0;i<c->entries;i++)
michael@0 81 oggpack_write(opb,c->lengthlist[i]-1,5);
michael@0 82 }else{
michael@0 83 oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
michael@0 84 for(i=0;i<c->entries;i++){
michael@0 85 if(c->lengthlist[i]==0){
michael@0 86 oggpack_write(opb,0,1);
michael@0 87 }else{
michael@0 88 oggpack_write(opb,1,1);
michael@0 89 oggpack_write(opb,c->lengthlist[i]-1,5);
michael@0 90 }
michael@0 91 }
michael@0 92 }
michael@0 93 }
michael@0 94
michael@0 95 /* is the entry number the desired return value, or do we have a
michael@0 96 mapping? If we have a mapping, what type? */
michael@0 97 oggpack_write(opb,c->maptype,4);
michael@0 98 switch(c->maptype){
michael@0 99 case 0:
michael@0 100 /* no mapping */
michael@0 101 break;
michael@0 102 case 1:case 2:
michael@0 103 /* implicitly populated value mapping */
michael@0 104 /* explicitly populated value mapping */
michael@0 105
michael@0 106 if(!c->quantlist){
michael@0 107 /* no quantlist? error */
michael@0 108 return(-1);
michael@0 109 }
michael@0 110
michael@0 111 /* values that define the dequantization */
michael@0 112 oggpack_write(opb,c->q_min,32);
michael@0 113 oggpack_write(opb,c->q_delta,32);
michael@0 114 oggpack_write(opb,c->q_quant-1,4);
michael@0 115 oggpack_write(opb,c->q_sequencep,1);
michael@0 116
michael@0 117 {
michael@0 118 int quantvals;
michael@0 119 switch(c->maptype){
michael@0 120 case 1:
michael@0 121 /* a single column of (c->entries/c->dim) quantized values for
michael@0 122 building a full value list algorithmically (square lattice) */
michael@0 123 quantvals=_book_maptype1_quantvals(c);
michael@0 124 break;
michael@0 125 case 2:
michael@0 126 /* every value (c->entries*c->dim total) specified explicitly */
michael@0 127 quantvals=c->entries*c->dim;
michael@0 128 break;
michael@0 129 default: /* NOT_REACHABLE */
michael@0 130 quantvals=-1;
michael@0 131 }
michael@0 132
michael@0 133 /* quantized values */
michael@0 134 for(i=0;i<quantvals;i++)
michael@0 135 oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
michael@0 136
michael@0 137 }
michael@0 138 break;
michael@0 139 default:
michael@0 140 /* error case; we don't have any other map types now */
michael@0 141 return(-1);
michael@0 142 }
michael@0 143
michael@0 144 return(0);
michael@0 145 }
michael@0 146
michael@0 147 /* unpacks a codebook from the packet buffer into the codebook struct,
michael@0 148 readies the codebook auxiliary structures for decode *************/
michael@0 149 static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
michael@0 150 long i,j;
michael@0 151 static_codebook *s=_ogg_calloc(1,sizeof(*s));
michael@0 152 s->allocedp=1;
michael@0 153
michael@0 154 /* make sure alignment is correct */
michael@0 155 if(oggpack_read(opb,24)!=0x564342)goto _eofout;
michael@0 156
michael@0 157 /* first the basic parameters */
michael@0 158 s->dim=oggpack_read(opb,16);
michael@0 159 s->entries=oggpack_read(opb,24);
michael@0 160 if(s->entries==-1)goto _eofout;
michael@0 161
michael@0 162 if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
michael@0 163
michael@0 164 /* codeword ordering.... length ordered or unordered? */
michael@0 165 switch((int)oggpack_read(opb,1)){
michael@0 166 case 0:{
michael@0 167 long unused;
michael@0 168 /* allocated but unused entries? */
michael@0 169 unused=oggpack_read(opb,1);
michael@0 170 if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
michael@0 171 goto _eofout;
michael@0 172 /* unordered */
michael@0 173 s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
michael@0 174
michael@0 175 /* allocated but unused entries? */
michael@0 176 if(unused){
michael@0 177 /* yes, unused entries */
michael@0 178
michael@0 179 for(i=0;i<s->entries;i++){
michael@0 180 if(oggpack_read(opb,1)){
michael@0 181 long num=oggpack_read(opb,5);
michael@0 182 if(num==-1)goto _eofout;
michael@0 183 s->lengthlist[i]=num+1;
michael@0 184 }else
michael@0 185 s->lengthlist[i]=0;
michael@0 186 }
michael@0 187 }else{
michael@0 188 /* all entries used; no tagging */
michael@0 189 for(i=0;i<s->entries;i++){
michael@0 190 long num=oggpack_read(opb,5);
michael@0 191 if(num==-1)goto _eofout;
michael@0 192 s->lengthlist[i]=num+1;
michael@0 193 }
michael@0 194 }
michael@0 195
michael@0 196 break;
michael@0 197 }
michael@0 198 case 1:
michael@0 199 /* ordered */
michael@0 200 {
michael@0 201 long length=oggpack_read(opb,5)+1;
michael@0 202 if(length==0)goto _eofout;
michael@0 203 s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
michael@0 204
michael@0 205 for(i=0;i<s->entries;){
michael@0 206 long num=oggpack_read(opb,_ilog(s->entries-i));
michael@0 207 if(num==-1)goto _eofout;
michael@0 208 if(length>32 || num>s->entries-i ||
michael@0 209 (num>0 && (num-1)>>(length-1)>1)){
michael@0 210 goto _errout;
michael@0 211 }
michael@0 212 if(length>32)goto _errout;
michael@0 213 for(j=0;j<num;j++,i++)
michael@0 214 s->lengthlist[i]=length;
michael@0 215 length++;
michael@0 216 }
michael@0 217 }
michael@0 218 break;
michael@0 219 default:
michael@0 220 /* EOF */
michael@0 221 goto _eofout;
michael@0 222 }
michael@0 223
michael@0 224 /* Do we have a mapping to unpack? */
michael@0 225 switch((s->maptype=oggpack_read(opb,4))){
michael@0 226 case 0:
michael@0 227 /* no mapping */
michael@0 228 break;
michael@0 229 case 1: case 2:
michael@0 230 /* implicitly populated value mapping */
michael@0 231 /* explicitly populated value mapping */
michael@0 232
michael@0 233 s->q_min=oggpack_read(opb,32);
michael@0 234 s->q_delta=oggpack_read(opb,32);
michael@0 235 s->q_quant=oggpack_read(opb,4)+1;
michael@0 236 s->q_sequencep=oggpack_read(opb,1);
michael@0 237 if(s->q_sequencep==-1)goto _eofout;
michael@0 238
michael@0 239 {
michael@0 240 int quantvals=0;
michael@0 241 switch(s->maptype){
michael@0 242 case 1:
michael@0 243 quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
michael@0 244 break;
michael@0 245 case 2:
michael@0 246 quantvals=s->entries*s->dim;
michael@0 247 break;
michael@0 248 }
michael@0 249
michael@0 250 /* quantized values */
michael@0 251 if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb))
michael@0 252 goto _eofout;
michael@0 253 s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
michael@0 254 for(i=0;i<quantvals;i++)
michael@0 255 s->quantlist[i]=oggpack_read(opb,s->q_quant);
michael@0 256
michael@0 257 if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
michael@0 258 }
michael@0 259 break;
michael@0 260 default:
michael@0 261 goto _errout;
michael@0 262 }
michael@0 263
michael@0 264 /* all set */
michael@0 265 return(s);
michael@0 266
michael@0 267 _errout:
michael@0 268 _eofout:
michael@0 269 vorbis_staticbook_destroy(s);
michael@0 270 return(NULL);
michael@0 271 }
michael@0 272
michael@0 273 /* returns the number of bits ************************************************/
michael@0 274 int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
michael@0 275 if(a<0 || a>=book->c->entries)return(0);
michael@0 276 oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
michael@0 277 return(book->c->lengthlist[a]);
michael@0 278 }
michael@0 279
michael@0 280 /* the 'eliminate the decode tree' optimization actually requires the
michael@0 281 codewords to be MSb first, not LSb. This is an annoying inelegancy
michael@0 282 (and one of the first places where carefully thought out design
michael@0 283 turned out to be wrong; Vorbis II and future Ogg codecs should go
michael@0 284 to an MSb bitpacker), but not actually the huge hit it appears to
michael@0 285 be. The first-stage decode table catches most words so that
michael@0 286 bitreverse is not in the main execution path. */
michael@0 287
michael@0 288 static ogg_uint32_t bitreverse(ogg_uint32_t x){
michael@0 289 x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
michael@0 290 x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
michael@0 291 x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
michael@0 292 x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
michael@0 293 return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
michael@0 294 }
michael@0 295
michael@0 296 STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
michael@0 297 int read=book->dec_maxlength;
michael@0 298 long lo,hi;
michael@0 299 long lok = oggpack_look(b,book->dec_firsttablen);
michael@0 300
michael@0 301 if (lok >= 0) {
michael@0 302 long entry = book->dec_firsttable[lok];
michael@0 303 if(entry&0x80000000UL){
michael@0 304 lo=(entry>>15)&0x7fff;
michael@0 305 hi=book->used_entries-(entry&0x7fff);
michael@0 306 }else{
michael@0 307 oggpack_adv(b, book->dec_codelengths[entry-1]);
michael@0 308 return(entry-1);
michael@0 309 }
michael@0 310 }else{
michael@0 311 lo=0;
michael@0 312 hi=book->used_entries;
michael@0 313 }
michael@0 314
michael@0 315 lok = oggpack_look(b, read);
michael@0 316
michael@0 317 while(lok<0 && read>1)
michael@0 318 lok = oggpack_look(b, --read);
michael@0 319 if(lok<0)return -1;
michael@0 320
michael@0 321 /* bisect search for the codeword in the ordered list */
michael@0 322 {
michael@0 323 ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
michael@0 324
michael@0 325 while(hi-lo>1){
michael@0 326 long p=(hi-lo)>>1;
michael@0 327 long test=book->codelist[lo+p]>testword;
michael@0 328 lo+=p&(test-1);
michael@0 329 hi-=p&(-test);
michael@0 330 }
michael@0 331
michael@0 332 if(book->dec_codelengths[lo]<=read){
michael@0 333 oggpack_adv(b, book->dec_codelengths[lo]);
michael@0 334 return(lo);
michael@0 335 }
michael@0 336 }
michael@0 337
michael@0 338 oggpack_adv(b, read);
michael@0 339
michael@0 340 return(-1);
michael@0 341 }
michael@0 342
michael@0 343 /* Decode side is specced and easier, because we don't need to find
michael@0 344 matches using different criteria; we simply read and map. There are
michael@0 345 two things we need to do 'depending':
michael@0 346
michael@0 347 We may need to support interleave. We don't really, but it's
michael@0 348 convenient to do it here rather than rebuild the vector later.
michael@0 349
michael@0 350 Cascades may be additive or multiplicitive; this is not inherent in
michael@0 351 the codebook, but set in the code using the codebook. Like
michael@0 352 interleaving, it's easiest to do it here.
michael@0 353 addmul==0 -> declarative (set the value)
michael@0 354 addmul==1 -> additive
michael@0 355 addmul==2 -> multiplicitive */
michael@0 356
michael@0 357 /* returns the [original, not compacted] entry number or -1 on eof *********/
michael@0 358 long vorbis_book_decode(codebook *book, oggpack_buffer *b){
michael@0 359 if(book->used_entries>0){
michael@0 360 long packed_entry=decode_packed_entry_number(book,b);
michael@0 361 if(packed_entry>=0)
michael@0 362 return(book->dec_index[packed_entry]);
michael@0 363 }
michael@0 364
michael@0 365 /* if there's no dec_index, the codebook unpacking isn't collapsed */
michael@0 366 return(-1);
michael@0 367 }
michael@0 368
michael@0 369 /* returns 0 on OK or -1 on eof *************************************/
michael@0 370 /* decode vector / dim granularity gaurding is done in the upper layer */
michael@0 371 long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
michael@0 372 if(book->used_entries>0){
michael@0 373 int step=n/book->dim;
michael@0 374 long *entry = alloca(sizeof(*entry)*step);
michael@0 375 float **t = alloca(sizeof(*t)*step);
michael@0 376 int i,j,o;
michael@0 377
michael@0 378 for (i = 0; i < step; i++) {
michael@0 379 entry[i]=decode_packed_entry_number(book,b);
michael@0 380 if(entry[i]==-1)return(-1);
michael@0 381 t[i] = book->valuelist+entry[i]*book->dim;
michael@0 382 }
michael@0 383 for(i=0,o=0;i<book->dim;i++,o+=step)
michael@0 384 for (j=0;j<step;j++)
michael@0 385 a[o+j]+=t[j][i];
michael@0 386 }
michael@0 387 return(0);
michael@0 388 }
michael@0 389
michael@0 390 /* decode vector / dim granularity gaurding is done in the upper layer */
michael@0 391 long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
michael@0 392 if(book->used_entries>0){
michael@0 393 int i,j,entry;
michael@0 394 float *t;
michael@0 395
michael@0 396 if(book->dim>8){
michael@0 397 for(i=0;i<n;){
michael@0 398 entry = decode_packed_entry_number(book,b);
michael@0 399 if(entry==-1)return(-1);
michael@0 400 t = book->valuelist+entry*book->dim;
michael@0 401 for (j=0;j<book->dim;)
michael@0 402 a[i++]+=t[j++];
michael@0 403 }
michael@0 404 }else{
michael@0 405 for(i=0;i<n;){
michael@0 406 entry = decode_packed_entry_number(book,b);
michael@0 407 if(entry==-1)return(-1);
michael@0 408 t = book->valuelist+entry*book->dim;
michael@0 409 j=0;
michael@0 410 switch((int)book->dim){
michael@0 411 case 8:
michael@0 412 a[i++]+=t[j++];
michael@0 413 case 7:
michael@0 414 a[i++]+=t[j++];
michael@0 415 case 6:
michael@0 416 a[i++]+=t[j++];
michael@0 417 case 5:
michael@0 418 a[i++]+=t[j++];
michael@0 419 case 4:
michael@0 420 a[i++]+=t[j++];
michael@0 421 case 3:
michael@0 422 a[i++]+=t[j++];
michael@0 423 case 2:
michael@0 424 a[i++]+=t[j++];
michael@0 425 case 1:
michael@0 426 a[i++]+=t[j++];
michael@0 427 case 0:
michael@0 428 break;
michael@0 429 }
michael@0 430 }
michael@0 431 }
michael@0 432 }
michael@0 433 return(0);
michael@0 434 }
michael@0 435
michael@0 436 /* unlike the others, we guard against n not being an integer number
michael@0 437 of <dim> internally rather than in the upper layer (called only by
michael@0 438 floor0) */
michael@0 439 long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
michael@0 440 if(book->used_entries>0){
michael@0 441 int i,j,entry;
michael@0 442 float *t;
michael@0 443
michael@0 444 for(i=0;i<n;){
michael@0 445 entry = decode_packed_entry_number(book,b);
michael@0 446 if(entry==-1)return(-1);
michael@0 447 t = book->valuelist+entry*book->dim;
michael@0 448 for (j=0;i<n && j<book->dim;){
michael@0 449 a[i++]=t[j++];
michael@0 450 }
michael@0 451 }
michael@0 452 }else{
michael@0 453 int i;
michael@0 454
michael@0 455 for(i=0;i<n;){
michael@0 456 a[i++]=0.f;
michael@0 457 }
michael@0 458 }
michael@0 459 return(0);
michael@0 460 }
michael@0 461
michael@0 462 long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
michael@0 463 oggpack_buffer *b,int n){
michael@0 464
michael@0 465 long i,j,entry;
michael@0 466 int chptr=0;
michael@0 467 if(book->used_entries>0){
michael@0 468 for(i=offset/ch;i<(offset+n)/ch;){
michael@0 469 entry = decode_packed_entry_number(book,b);
michael@0 470 if(entry==-1)return(-1);
michael@0 471 {
michael@0 472 const float *t = book->valuelist+entry*book->dim;
michael@0 473 for (j=0;j<book->dim;j++){
michael@0 474 a[chptr++][i]+=t[j];
michael@0 475 if(chptr==ch){
michael@0 476 chptr=0;
michael@0 477 i++;
michael@0 478 }
michael@0 479 }
michael@0 480 }
michael@0 481 }
michael@0 482 }
michael@0 483 return(0);
michael@0 484 }

mercurial