Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 244 | chris | 1 | /******************************************************************** |
| 2 | * * |
||
| 3 | * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * |
||
| 4 | * * |
||
| 5 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
||
| 6 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
||
| 7 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
||
| 8 | * * |
||
| 9 | * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * |
||
| 10 | * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * |
||
| 11 | * * |
||
| 12 | ******************************************************************** |
||
| 13 | |||
| 14 | function: basic codebook pack/unpack/code/decode operations |
||
| 15 | |||
| 16 | ********************************************************************/ |
||
| 17 | |||
| 18 | #include <stdlib.h> |
||
| 19 | #include <string.h> |
||
| 20 | #include <math.h> |
||
| 21 | #include "ogg.h" |
||
| 22 | #include "ivorbiscodec.h" |
||
| 23 | #include "codebook.h" |
||
| 24 | #include "misc.h" |
||
| 25 | #include "os.h" |
||
| 26 | |||
| 27 | /* unpacks a codebook from the packet buffer into the codebook struct, |
||
| 28 | readies the codebook auxiliary structures for decode *************/ |
||
| 29 | int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ |
||
| 30 | long i,j; |
||
| 31 | memset(s,0,sizeof(*s)); |
||
| 32 | |||
| 33 | /* make sure alignment is correct */ |
||
| 34 | if(oggpack_read(opb,24)!=0x564342)goto _eofout; |
||
| 35 | |||
| 36 | /* first the basic parameters */ |
||
| 37 | s->dim=oggpack_read(opb,16); |
||
| 38 | s->entries=oggpack_read(opb,24); |
||
| 39 | if(s->entries==-1)goto _eofout; |
||
| 40 | |||
| 41 | /* codeword ordering.... length ordered or unordered? */ |
||
| 42 | switch((int)oggpack_read(opb,1)){ |
||
| 43 | case 0: |
||
| 44 | /* unordered */ |
||
| 45 | s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); |
||
| 46 | |||
| 47 | /* allocated but unused entries? */ |
||
| 48 | if(oggpack_read(opb,1)){ |
||
| 49 | /* yes, unused entries */ |
||
| 50 | |||
| 51 | for(i=0;i<s->entries;i++){ |
||
| 52 | if(oggpack_read(opb,1)){ |
||
| 53 | long num=oggpack_read(opb,5); |
||
| 54 | if(num==-1)goto _eofout; |
||
| 55 | s->lengthlist[i]=num+1; |
||
| 56 | }else |
||
| 57 | s->lengthlist[i]=0; |
||
| 58 | } |
||
| 59 | }else{ |
||
| 60 | /* all entries used; no tagging */ |
||
| 61 | for(i=0;i<s->entries;i++){ |
||
| 62 | long num=oggpack_read(opb,5); |
||
| 63 | if(num==-1)goto _eofout; |
||
| 64 | s->lengthlist[i]=num+1; |
||
| 65 | } |
||
| 66 | } |
||
| 67 | |||
| 68 | break; |
||
| 69 | case 1: |
||
| 70 | /* ordered */ |
||
| 71 | { |
||
| 72 | long length=oggpack_read(opb,5)+1; |
||
| 73 | s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); |
||
| 74 | |||
| 75 | for(i=0;i<s->entries;){ |
||
| 76 | long num=oggpack_read(opb,_ilog(s->entries-i)); |
||
| 77 | if(num==-1)goto _eofout; |
||
| 78 | for(j=0;j<num && i<s->entries;j++,i++) |
||
| 79 | s->lengthlist[i]=length; |
||
| 80 | length++; |
||
| 81 | } |
||
| 82 | } |
||
| 83 | break; |
||
| 84 | default: |
||
| 85 | /* EOF */ |
||
| 86 | return(-1); |
||
| 87 | } |
||
| 88 | |||
| 89 | /* Do we have a mapping to unpack? */ |
||
| 90 | switch((s->maptype=oggpack_read(opb,4))){ |
||
| 91 | case 0: |
||
| 92 | /* no mapping */ |
||
| 93 | break; |
||
| 94 | case 1: case 2: |
||
| 95 | /* implicitly populated value mapping */ |
||
| 96 | /* explicitly populated value mapping */ |
||
| 97 | |||
| 98 | s->q_min=oggpack_read(opb,32); |
||
| 99 | s->q_delta=oggpack_read(opb,32); |
||
| 100 | s->q_quant=oggpack_read(opb,4)+1; |
||
| 101 | s->q_sequencep=oggpack_read(opb,1); |
||
| 102 | |||
| 103 | { |
||
| 104 | int quantvals=0; |
||
| 105 | switch(s->maptype){ |
||
| 106 | case 1: |
||
| 107 | quantvals=_book_maptype1_quantvals(s); |
||
| 108 | break; |
||
| 109 | case 2: |
||
| 110 | quantvals=s->entries*s->dim; |
||
| 111 | break; |
||
| 112 | } |
||
| 113 | |||
| 114 | /* quantized values */ |
||
| 115 | s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals); |
||
| 116 | for(i=0;i<quantvals;i++) |
||
| 117 | s->quantlist[i]=oggpack_read(opb,s->q_quant); |
||
| 118 | |||
| 119 | if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; |
||
| 120 | } |
||
| 121 | break; |
||
| 122 | default: |
||
| 123 | goto _errout; |
||
| 124 | } |
||
| 125 | |||
| 126 | /* all set */ |
||
| 127 | return(0); |
||
| 128 | |||
| 129 | _errout: |
||
| 130 | _eofout: |
||
| 131 | vorbis_staticbook_clear(s); |
||
| 132 | return(-1); |
||
| 133 | } |
||
| 134 | |||
| 135 | /* the 'eliminate the decode tree' optimization actually requires the |
||
| 136 | codewords to be MSb first, not LSb. This is an annoying inelegancy |
||
| 137 | (and one of the first places where carefully thought out design |
||
| 138 | turned out to be wrong; Vorbis II and future Ogg codecs should go |
||
| 139 | to an MSb bitpacker), but not actually the huge hit it appears to |
||
| 140 | be. The first-stage decode table catches most words so that |
||
| 141 | bitreverse is not in the main execution path. */ |
||
| 142 | |||
| 143 | static ogg_uint32_t bitreverse(ogg_uint32_t x){ |
||
| 144 | x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000); |
||
| 145 | x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00); |
||
| 146 | x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0); |
||
| 147 | x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc); |
||
| 148 | return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa); |
||
| 149 | } |
||
| 150 | |||
| 151 | STIN long decode_packed_entry_number(codebook *book, |
||
| 152 | oggpack_buffer *b){ |
||
| 153 | int read=book->dec_maxlength; |
||
| 154 | long lo,hi; |
||
| 155 | long lok = oggpack_look(b,book->dec_firsttablen); |
||
| 156 | |||
| 157 | if (lok >= 0) { |
||
| 158 | long entry = book->dec_firsttable[lok]; |
||
| 159 | if(entry&0x80000000UL){ |
||
| 160 | lo=(entry>>15)&0x7fff; |
||
| 161 | hi=book->used_entries-(entry&0x7fff); |
||
| 162 | }else{ |
||
| 163 | oggpack_adv(b, book->dec_codelengths[entry-1]); |
||
| 164 | return(entry-1); |
||
| 165 | } |
||
| 166 | }else{ |
||
| 167 | lo=0; |
||
| 168 | hi=book->used_entries; |
||
| 169 | } |
||
| 170 | |||
| 171 | lok = oggpack_look(b, read); |
||
| 172 | |||
| 173 | while(lok<0 && read>1) |
||
| 174 | lok = oggpack_look(b, --read); |
||
| 175 | if(lok<0)return -1; |
||
| 176 | |||
| 177 | /* bisect search for the codeword in the ordered list */ |
||
| 178 | { |
||
| 179 | ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); |
||
| 180 | |||
| 181 | while(hi-lo>1){ |
||
| 182 | long p=(hi-lo)>>1; |
||
| 183 | long test=book->codelist[lo+p]>testword; |
||
| 184 | lo+=p&(test-1); |
||
| 185 | hi-=p&(-test); |
||
| 186 | } |
||
| 187 | |||
| 188 | if(book->dec_codelengths[lo]<=read){ |
||
| 189 | oggpack_adv(b, book->dec_codelengths[lo]); |
||
| 190 | return(lo); |
||
| 191 | } |
||
| 192 | } |
||
| 193 | |||
| 194 | oggpack_adv(b, read); |
||
| 195 | return(-1); |
||
| 196 | } |
||
| 197 | |||
| 198 | /* Decode side is specced and easier, because we don't need to find |
||
| 199 | matches using different criteria; we simply read and map. There are |
||
| 200 | two things we need to do 'depending': |
||
| 201 | |||
| 202 | We may need to support interleave. We don't really, but it's |
||
| 203 | convenient to do it here rather than rebuild the vector later. |
||
| 204 | |||
| 205 | Cascades may be additive or multiplicitive; this is not inherent in |
||
| 206 | the codebook, but set in the code using the codebook. Like |
||
| 207 | interleaving, it's easiest to do it here. |
||
| 208 | addmul==0 -> declarative (set the value) |
||
| 209 | addmul==1 -> additive |
||
| 210 | addmul==2 -> multiplicitive */ |
||
| 211 | |||
| 212 | /* returns the [original, not compacted] entry number or -1 on eof *********/ |
||
| 213 | long vorbis_book_decode(codebook *book, oggpack_buffer *b){ |
||
| 214 | long packed_entry=decode_packed_entry_number(book,b); |
||
| 215 | if(packed_entry>=0) |
||
| 216 | return(book->dec_index[packed_entry]); |
||
| 217 | |||
| 218 | /* if there's no dec_index, the codebook unpacking isn't collapsed */ |
||
| 219 | return(packed_entry); |
||
| 220 | } |
||
| 221 | |||
| 222 | /* returns 0 on OK or -1 on eof *************************************/ |
||
| 223 | long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a, |
||
| 224 | oggpack_buffer *b,int n,int point){ |
||
| 225 | int step=n/book->dim; |
||
| 226 | long *entry = (long *)alloca(sizeof(*entry)*step); |
||
| 227 | ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step); |
||
| 228 | int i,j,o; |
||
| 229 | int shift=point-book->binarypoint; |
||
| 230 | |||
| 231 | if(shift>=0){ |
||
| 232 | for (i = 0; i < step; i++) { |
||
| 233 | entry[i]=decode_packed_entry_number(book,b); |
||
| 234 | if(entry[i]==-1)return(-1); |
||
| 235 | t[i] = book->valuelist+entry[i]*book->dim; |
||
| 236 | } |
||
| 237 | for(i=0,o=0;i<book->dim;i++,o+=step) |
||
| 238 | for (j=0;j<step;j++) |
||
| 239 | a[o+j]+=t[j][i]>>shift; |
||
| 240 | }else{ |
||
| 241 | for (i = 0; i < step; i++) { |
||
| 242 | entry[i]=decode_packed_entry_number(book,b); |
||
| 243 | if(entry[i]==-1)return(-1); |
||
| 244 | t[i] = book->valuelist+entry[i]*book->dim; |
||
| 245 | } |
||
| 246 | for(i=0,o=0;i<book->dim;i++,o+=step) |
||
| 247 | for (j=0;j<step;j++) |
||
| 248 | a[o+j]+=t[j][i]<<-shift; |
||
| 249 | } |
||
| 250 | return(0); |
||
| 251 | } |
||
| 252 | |||
| 253 | long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a, |
||
| 254 | oggpack_buffer *b,int n,int point){ |
||
| 255 | int i,j,entry; |
||
| 256 | ogg_int32_t *t; |
||
| 257 | int shift=point-book->binarypoint; |
||
| 258 | |||
| 259 | if(shift>=0){ |
||
| 260 | for(i=0;i<n;){ |
||
| 261 | entry = decode_packed_entry_number(book,b); |
||
| 262 | if(entry==-1)return(-1); |
||
| 263 | t = book->valuelist+entry*book->dim; |
||
| 264 | for (j=0;j<book->dim;) |
||
| 265 | a[i++]+=t[j++]>>shift; |
||
| 266 | } |
||
| 267 | }else{ |
||
| 268 | for(i=0;i<n;){ |
||
| 269 | entry = decode_packed_entry_number(book,b); |
||
| 270 | if(entry==-1)return(-1); |
||
| 271 | t = book->valuelist+entry*book->dim; |
||
| 272 | for (j=0;j<book->dim;) |
||
| 273 | a[i++]+=t[j++]<<-shift; |
||
| 274 | } |
||
| 275 | } |
||
| 276 | return(0); |
||
| 277 | } |
||
| 278 | |||
| 279 | long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a, |
||
| 280 | oggpack_buffer *b,int n,int point){ |
||
| 281 | int i,j,entry; |
||
| 282 | ogg_int32_t *t; |
||
| 283 | int shift=point-book->binarypoint; |
||
| 284 | |||
| 285 | if(shift>=0){ |
||
| 286 | |||
| 287 | for(i=0;i<n;){ |
||
| 288 | entry = decode_packed_entry_number(book,b); |
||
| 289 | if(entry==-1)return(-1); |
||
| 290 | t = book->valuelist+entry*book->dim; |
||
| 291 | for (j=0;j<book->dim;){ |
||
| 292 | a[i++]=t[j++]>>shift; |
||
| 293 | } |
||
| 294 | } |
||
| 295 | }else{ |
||
| 296 | |||
| 297 | for(i=0;i<n;){ |
||
| 298 | entry = decode_packed_entry_number(book,b); |
||
| 299 | if(entry==-1)return(-1); |
||
| 300 | t = book->valuelist+entry*book->dim; |
||
| 301 | for (j=0;j<book->dim;){ |
||
| 302 | a[i++]=t[j++]<<-shift; |
||
| 303 | } |
||
| 304 | } |
||
| 305 | } |
||
| 306 | return(0); |
||
| 307 | } |
||
| 308 | |||
| 309 | long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,\ |
||
| 310 | long offset,int ch, |
||
| 311 | oggpack_buffer *b,int n,int point){ |
||
| 312 | long i,j,entry; |
||
| 313 | int chptr=0; |
||
| 314 | int shift=point-book->binarypoint; |
||
| 315 | |||
| 316 | if(shift>=0){ |
||
| 317 | |||
| 318 | for(i=offset;i<offset+n;){ |
||
| 319 | entry = decode_packed_entry_number(book,b); |
||
| 320 | if(entry==-1)return(-1); |
||
| 321 | { |
||
| 322 | const ogg_int32_t *t = book->valuelist+entry*book->dim; |
||
| 323 | for (j=0;j<book->dim;j++){ |
||
| 324 | a[chptr++][i]+=t[j]>>shift; |
||
| 325 | if(chptr==ch){ |
||
| 326 | chptr=0; |
||
| 327 | i++; |
||
| 328 | } |
||
| 329 | } |
||
| 330 | } |
||
| 331 | } |
||
| 332 | }else{ |
||
| 333 | |||
| 334 | for(i=offset;i<offset+n;){ |
||
| 335 | entry = decode_packed_entry_number(book,b); |
||
| 336 | if(entry==-1)return(-1); |
||
| 337 | { |
||
| 338 | const ogg_int32_t *t = book->valuelist+entry*book->dim; |
||
| 339 | for (j=0;j<book->dim;j++){ |
||
| 340 | a[chptr++][i]+=t[j]<<-shift; |
||
| 341 | if(chptr==ch){ |
||
| 342 | chptr=0; |
||
| 343 | i++; |
||
| 344 | } |
||
| 345 | } |
||
| 346 | } |
||
| 347 | } |
||
| 348 | } |
||
| 349 | return(0); |
||
| 350 | } |