annotate src/libvorbis-1.3.3/lib/codebook.c @ 124:e3d5853d5918

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