summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libtremor/codebook.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libtremor/codebook.c')
-rw-r--r--lib/rbcodec/codecs/libtremor/codebook.c587
1 files changed, 587 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libtremor/codebook.c b/lib/rbcodec/codecs/libtremor/codebook.c
new file mode 100644
index 0000000000..7087f0a323
--- /dev/null
+++ b/lib/rbcodec/codecs/libtremor/codebook.c
@@ -0,0 +1,587 @@
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 "config-tremor.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 *************/
29static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
30 long i,j;
31 static_codebook *s=_ogg_calloc(1,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 if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
42
43 /* codeword ordering.... length ordered or unordered? */
44 switch((int)oggpack_read(opb,1)){
45 case 0:{
46 long unused;
47 /* allocated but unused entries? */
48 unused=oggpack_read(opb,1);
49 if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
50 goto _eofout;
51 /* unordered */
52 s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
53
54 /* allocated but unused entries? */
55 if(unused){
56 /* yes, unused entries */
57
58 for(i=0;i<s->entries;i++){
59 if(oggpack_read(opb,1)){
60 long num=oggpack_read(opb,5);
61 if(num==-1)goto _eofout;
62 s->lengthlist[i]=num+1;
63 }else
64 s->lengthlist[i]=0;
65 }
66 }else{
67 /* all entries used; no tagging */
68 for(i=0;i<s->entries;i++){
69 long num=oggpack_read(opb,5);
70 if(num==-1)goto _eofout;
71 s->lengthlist[i]=num+1;
72 }
73 }
74
75 break;
76 }
77 case 1:
78 /* ordered */
79 {
80 long length=oggpack_read(opb,5)+1;
81 if(length==0)goto _eofout;
82 s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
83
84 for(i=0;i<s->entries;){
85 long num=oggpack_read(opb,_ilog(s->entries-i));
86 if(num==-1)goto _eofout;
87 if(length>32 || num>s->entries-i ||
88 (num>0 && (num-1)>>(length>>1)>>((length+1)>>1))>0){
89 goto _errout;
90 }
91 for(j=0;j<num;j++,i++)
92 s->lengthlist[i]=length;
93 length++;
94 }
95 }
96 break;
97 default:
98 /* EOF */
99 goto _eofout;
100 }
101
102 /* Do we have a mapping to unpack? */
103 switch((s->maptype=oggpack_read(opb,4))){
104 case 0:
105 /* no mapping */
106 break;
107 case 1: case 2:
108 /* implicitly populated value mapping */
109 /* explicitly populated value mapping */
110
111 s->q_min=oggpack_read(opb,32);
112 s->q_delta=oggpack_read(opb,32);
113 s->q_quant=oggpack_read(opb,4)+1;
114 s->q_sequencep=oggpack_read(opb,1);
115 if(s->q_sequencep==-1)goto _eofout;
116
117 {
118 int quantvals=0;
119 switch(s->maptype){
120 case 1:
121 quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
122 break;
123 case 2:
124 quantvals=s->entries*s->dim;
125 break;
126 }
127
128 /* quantized values */
129 if((quantvals*s->q_quant+7)>>3>opb->storage-oggpack_bytes(opb))
130 goto _eofout;
131 s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals);
132 for(i=0;i<quantvals;i++)
133 s->quantlist[i]=oggpack_read(opb,s->q_quant);
134
135 if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
136 }
137 break;
138 default:
139 goto _errout;
140 }
141
142 /* all set */
143 return(s);
144
145 _errout:
146 _eofout:
147 vorbis_staticbook_destroy(s);
148 return(NULL);
149}
150
151/* the 'eliminate the decode tree' optimization actually requires the
152 codewords to be MSb first, not LSb. This is an annoying inelegancy
153 (and one of the first places where carefully thought out design
154 turned out to be wrong; Vorbis II and future Ogg codecs should go
155 to an MSb bitpacker), but not actually the huge hit it appears to
156 be. The first-stage decode table catches most words so that
157 bitreverse is not in the main execution path. */
158
159static inline ogg_uint32_t bitreverse(register ogg_uint32_t x)
160{
161 unsigned tmp, ret;
162#ifdef _ARM_ASSEM_
163#if ARM_ARCH >= 6
164 unsigned mask = 0x0f0f0f0f;
165#else
166 unsigned mask = 0x00ff00ff;
167#endif
168 asm (
169#if ARM_ARCH >= 6
170 "rev %[r], %[x] \n" /* swap halfwords and bytes */
171 "and %[t], %[m], %[r] \n" /* Sequence is one instruction */
172 "eor %[r], %[t], %[r] \n" /* longer than on <= ARMv5, but */
173 "mov %[t], %[t], lsl #4 \n" /* interlock free */
174 "orr %[r], %[t], %[r], lsr #4\n" /* nibbles swapped */
175 "eor %[m], %[m], %[m], lsl #2\n" /* mask = 0x33333333 */
176 "and %[t], %[m], %[r] \n"
177 "eor %[r], %[t], %[r] \n"
178 "mov %[t], %[t], lsl #2 \n"
179 "orr %[r], %[t], %[r], lsr #2\n" /* dibits swapped */
180 "eor %[m], %[m], %[m], lsl #1\n" /* mask = 0x55555555 */
181 "and %[t], %[m], %[r] \n"
182 "eor %[r], %[t], %[r] \n"
183 "mov %[t], %[t], lsl #1 \n"
184 "orr %[r], %[t], %[r], lsr #1\n" /* bits swapped */
185#else /* ARM_ARCH <= 5 */
186 "mov %[r], %[x], ror #16 \n" /* swap halfwords */
187 "and %[t], %[m], %[r], lsr #8\n"
188 "eor %[r], %[r], %[t], lsl #8\n"
189 "orr %[r], %[t], %[r], lsl #8\n" /* bytes swapped */
190 "eor %[m], %[m], %[m], lsl #4\n" /* mask = 0x0f0f0f0f */
191 "and %[t], %[m], %[r], lsr #4\n"
192 "eor %[r], %[r], %[t], lsl #4\n"
193 "orr %[r], %[t], %[r], lsl #4\n" /* nibbles swapped */
194 "eor %[m], %[m], %[m], lsl #2\n" /* mask = 0x33333333 */
195 "and %[t], %[m], %[r], lsr #2\n"
196 "eor %[r], %[r], %[t], lsl #2\n"
197 "orr %[r], %[t], %[r], lsl #2\n" /* dibits swapped */
198 "eor %[m], %[m], %[m], lsl #1\n" /* mask = 0x55555555 */
199 "and %[t], %[m], %[r], lsr #1\n"
200 "eor %[r], %[r], %[t], lsl #1\n"
201 "orr %[r], %[t], %[r], lsl #1\n" /* bits swapped */
202#endif /* ARM_ARCH */
203 : /* outputs */
204 [m]"+r"(mask),
205 [r]"=r"(ret),
206 [t]"=r"(tmp)
207 : /* inputs */
208 [x]"r"(x)
209 );
210#else /* !_ARM_ASSEM_ */
211
212 ret = (x>>16) | (x<<16);
213 tmp = ret & 0x00ff00ff;
214 ret ^= tmp;
215 ret = (ret >> 8) | (tmp << 8); /* bytes swapped */
216 tmp = ret & 0x0f0f0f0f;
217 ret ^= tmp;
218 ret = (ret >> 4) | (tmp << 4); /* 4-bit units swapped */
219 tmp = ret & 0x33333333;
220 ret ^= tmp;
221 ret = (ret >> 2) | (tmp << 2); /* 2-bit units swapped */
222 tmp = ret & 0x55555555;
223 ret ^= tmp;
224 ret = (ret >> 1) | (tmp << 1); /* done */
225#endif /* !_ARM_ASSEM_ */
226 return ret;
227}
228
229static inline long bisect_codelist(long lo, long hi, ogg_uint32_t cache,
230 const ogg_uint32_t *codelist)
231{
232 ogg_uint32_t testword=bitreverse(cache);
233 long p;
234 while(LIKELY(p = (hi-lo) >> 1) > 0){
235 if(codelist[lo+p] > testword)
236 hi -= p;
237 else
238 lo += p;
239 }
240 return lo;
241}
242
243STIN long decode_packed_entry_number(codebook *book,
244 oggpack_buffer *b){
245 int read=book->dec_maxlength;
246 long lo,hi;
247 long lok = oggpack_look(b,book->dec_firsttablen);
248
249 if (LIKELY(lok >= 0)) {
250 ogg_int32_t entry = book->dec_firsttable[lok];
251 if(UNLIKELY(entry < 0)){
252 lo=(entry>>15)&0x7fff;
253 hi=book->used_entries-(entry&0x7fff);
254 }else{
255 oggpack_adv(b, book->dec_codelengths[entry-1]);
256 return(entry-1);
257 }
258 }else{
259 lo=0;
260 hi=book->used_entries;
261 }
262
263 lok = oggpack_look(b, read);
264
265 while(lok<0 && read>1)
266 lok = oggpack_look(b, --read);
267
268 if(lok<0){
269 oggpack_adv(b,1); /* force eop */
270 return -1;
271 }
272
273 /* bisect search for the codeword in the ordered list */
274 {
275 lo = bisect_codelist(lo, hi, lok, book->codelist);
276
277 if(book->dec_codelengths[lo]<=read){
278 oggpack_adv(b, book->dec_codelengths[lo]);
279 return(lo);
280 }
281 }
282
283 oggpack_adv(b, read+1);
284 return(-1);
285}
286
287static long decode_packed_block(codebook *book, oggpack_buffer *b,
288 long *buf, int n){
289 long *bufptr = buf;
290 long *bufend = buf + n;
291
292 while (bufptr<bufend) {
293 if(b->endbyte < b->storage - 8) {
294 ogg_uint32_t *ptr;
295 unsigned long bit, bitend;
296 unsigned long adr;
297 ogg_uint32_t cache = 0;
298 int cachesize = 0;
299 const unsigned int cachemask = (1<<book->dec_firsttablen)-1;
300 const int book_dec_maxlength = book->dec_maxlength;
301 const ogg_uint32_t *book_dec_firsttable = book->dec_firsttable;
302 const long book_used_entries = book->used_entries;
303 const ogg_uint32_t *book_codelist = book->codelist;
304 const char *book_dec_codelengths = book->dec_codelengths;
305
306 adr = (unsigned long)b->ptr;
307 bit = (adr&3)*8+b->endbit;
308 ptr = (ogg_uint32_t*)(adr&~3);
309 bitend = ((adr&3)+(b->storage-b->endbyte))*8;
310 while (bufptr<bufend){
311 if (UNLIKELY(cachesize<book_dec_maxlength)) {
312 if (bit-cachesize+32>=bitend)
313 break;
314 bit-=cachesize;
315 cache = letoh32(ptr[bit>>5]);
316 if (bit&31) {
317 cache >>= (bit&31);
318 cache |= letoh32(ptr[(bit>>5)+1]) << (32-(bit&31));
319 }
320 cachesize=32;
321 bit+=32;
322 }
323
324 ogg_int32_t entry = book_dec_firsttable[cache&cachemask];
325 if(UNLIKELY(entry < 0)){
326 const long lo = (entry>>15)&0x7fff, hi = book_used_entries-(entry&0x7fff);
327 entry = bisect_codelist(lo, hi, cache, book_codelist);
328 }else
329 entry--;
330
331 *bufptr++ = entry;
332 int l = book_dec_codelengths[entry];
333 cachesize -= l;
334 cache >>= l;
335 }
336
337 adr=(unsigned long)b->ptr;
338 bit-=(adr&3)*8+cachesize;
339 b->endbyte+=bit/8;
340 b->ptr+=bit/8;
341 b->endbit=bit&7;
342 } else {
343 long r = decode_packed_entry_number(book, b);
344 if (r == -1) return bufptr-buf;
345 *bufptr++ = r;
346 }
347 }
348 return n;
349}
350
351/* Decode side is specced and easier, because we don't need to find
352 matches using different criteria; we simply read and map. There are
353 two things we need to do 'depending':
354
355 We may need to support interleave. We don't really, but it's
356 convenient to do it here rather than rebuild the vector later.
357
358 Cascades may be additive or multiplicitive; this is not inherent in
359 the codebook, but set in the code using the codebook. Like
360 interleaving, it's easiest to do it here.
361 addmul==0 -> declarative (set the value)
362 addmul==1 -> additive
363 addmul==2 -> multiplicitive */
364
365/* returns the [original, not compacted] entry number or -1 on eof *********/
366long vorbis_book_decode(codebook *book, oggpack_buffer *b){
367 if(book->used_entries>0){
368 long packed_entry=decode_packed_entry_number(book,b);
369 if(packed_entry>=0)
370 return(book->dec_index[packed_entry]);
371 }
372
373 /* if there's no dec_index, the codebook unpacking isn't collapsed */
374 return(-1);
375}
376
377/* returns 0 on OK or -1 on eof *************************************/
378/* decode vector / dim granularity gaurding is done in the upper layer */
379long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
380 oggpack_buffer *b,int n,int point){
381 if(book->used_entries>0){
382 int step=n/book->dim;
383 long *entry = (long *)alloca(sizeof(*entry)*step);
384 ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step);
385 int i,j,o;
386 int shift=point-book->binarypoint;
387
388 if(shift>=0){
389 for (i = 0; i < step; i++) {
390 entry[i]=decode_packed_entry_number(book,b);
391 if(entry[i]==-1)return(-1);
392 t[i] = book->valuelist+entry[i]*book->dim;
393 }
394 for(i=0,o=0;i<book->dim;i++,o+=step)
395 for (j=0;j<step;j++)
396 a[o+j]+=t[j][i]>>shift;
397 }else{
398 for (i = 0; i < step; i++) {
399 entry[i]=decode_packed_entry_number(book,b);
400 if(entry[i]==-1)return(-1);
401 t[i] = book->valuelist+entry[i]*book->dim;
402 }
403 for(i=0,o=0;i<book->dim;i++,o+=step)
404 for (j=0;j<step;j++)
405 a[o+j]+=t[j][i]<<-shift;
406 }
407 }
408 return(0);
409}
410
411/* decode vector / dim granularity gaurding is done in the upper layer */
412long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
413 oggpack_buffer *b,int n,int point){
414 if(book->used_entries>0){
415 int i,j,entry;
416 ogg_int32_t *t;
417 int shift=point-book->binarypoint;
418
419 if(shift>=0){
420 for(i=0;i<n;){
421 entry = decode_packed_entry_number(book,b);
422 if(entry==-1)return(-1);
423 t = book->valuelist+entry*book->dim;
424 for (j=0;j<book->dim;)
425 a[i++]+=t[j++]>>shift;
426 }
427 }else{
428 shift = -shift;
429 for(i=0;i<n;){
430 entry = decode_packed_entry_number(book,b);
431 if(entry==-1)return(-1);
432 t = book->valuelist+entry*book->dim;
433 for (j=0;j<book->dim;)
434 a[i++]+=t[j++]<<shift;
435 }
436 }
437 }
438 return(0);
439}
440
441/* unlike the others, we guard against n not being an integer number
442 of <dim> internally rather than in the upper layer (called only by
443 floor0) */
444long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
445 oggpack_buffer *b,int n,int point){
446 if(book->used_entries>0){
447 int i,j,entry;
448 ogg_int32_t *t;
449 int shift=point-book->binarypoint;
450
451 if(shift>=0){
452
453 for(i=0;i<n;){
454 entry = decode_packed_entry_number(book,b);
455 if(entry==-1)return(-1);
456 t = book->valuelist+entry*book->dim;
457 for (j=0;i<n && j<book->dim;){
458 a[i++]=t[j++]>>shift;
459 }
460 }
461 }else{
462 shift = -shift;
463 for(i=0;i<n;){
464 entry = decode_packed_entry_number(book,b);
465 if(entry==-1)return(-1);
466 t = book->valuelist+entry*book->dim;
467 for (j=0;i<n && j<book->dim;){
468 a[i++]=t[j++]<<shift;
469 }
470 }
471 }
472 }else{
473
474 int i;
475 for(i=0;i<n;){
476 a[i++]=0;
477 }
478 }
479 return(0);
480}
481
482/* decode vector / dim granularity gaurding is done in the upper layer */
483static long vorbis_book_decodevv_add_2ch_even(codebook *book,ogg_int32_t **a,
484 long offset,oggpack_buffer *b,
485 unsigned int n,int point){
486 long k,chunk,read;
487 int shift=point-book->binarypoint;
488 long entries[32];
489 ogg_int32_t *p0 = &(a[0][offset]);
490 ogg_int32_t *p1 = &(a[1][offset]);
491 const unsigned long dim = book->dim;
492 const ogg_int32_t * const vlist = book->valuelist;
493
494 if(shift>=0){
495 while(n>0){
496 chunk=32;
497 if (16*dim>n)
498 chunk=(n*2-1)/dim + 1;
499 read = decode_packed_block(book,b,entries,chunk);
500 for(k=0;k<read;k++){
501 const ogg_int32_t *t = vlist+entries[k]*dim;
502 const ogg_int32_t *u = t+dim;
503 do{
504 *p0++ += *t++>>shift;
505 *p1++ += *t++>>shift;
506 }while(t<u);
507 }
508 if (read<chunk)return-1;
509 n -= read*dim/2;
510 }
511 }else{
512 shift = -shift;
513 while(n>0){
514 chunk=32;
515 if (16*dim>n)
516 chunk=(n*2-1)/dim + 1;
517 read = decode_packed_block(book,b,entries,chunk);
518 for(k=0;k<read;k++){
519 const ogg_int32_t *t = vlist+entries[k]*dim;
520 const ogg_int32_t *u = t+dim;
521 do{
522 *p0++ += *t++<<shift;
523 *p1++ += *t++<<shift;
524 }while(t<u);
525 }
526 if (read<chunk)return-1;
527 n -= read*dim/2;
528 }
529 }
530 return(0);
531}
532
533long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
534 long offset,int ch,
535 oggpack_buffer *b,int n,int point){
536 if(LIKELY(book->used_entries>0)){
537 long i,j,k,chunk,read;
538 int chptr=0;
539 int shift=point-book->binarypoint;
540 long entries[32];
541
542 if (!(book->dim&1) && ch==2)
543 return vorbis_book_decodevv_add_2ch_even(book,a,offset,b,n,point);
544
545 if(shift>=0){
546
547 for(i=offset;i<offset+n;){
548 chunk=32;
549 if (chunk*book->dim>(offset+n-i)*ch)
550 chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
551 read = decode_packed_block(book,b,entries,chunk);
552 for(k=0;k<read;k++){
553 const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
554 for (j=0;j<book->dim;j++){
555 a[chptr++][i]+=t[j]>>shift;
556 if(chptr==ch){
557 chptr=0;
558 i++;
559 }
560 }
561 }
562 if (read<chunk)return-1;
563 }
564 }else{
565 shift = -shift;
566 for(i=offset;i<offset+n;){
567 chunk=32;
568 if (chunk*book->dim>(offset+n-i)*ch)
569 chunk=((offset+n-i)*ch+book->dim-1)/book->dim;
570 read = decode_packed_block(book,b,entries,chunk);
571 for(k=0;k<read;k++){
572 const ogg_int32_t *t = book->valuelist+entries[k]*book->dim;
573 for (j=0;j<book->dim;j++){
574 a[chptr++][i]+=t[j]<<shift;
575 if(chptr==ch){
576 chptr=0;
577 i++;
578 }
579 }
580 }
581 if (read<chunk)return-1;
582 }
583 }
584 }
585 return(0);
586}
587