summaryrefslogtreecommitdiff
path: root/apps/codecs/Tremor/bitwise.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/Tremor/bitwise.c')
-rw-r--r--apps/codecs/Tremor/bitwise.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/apps/codecs/Tremor/bitwise.c b/apps/codecs/Tremor/bitwise.c
new file mode 100644
index 0000000000..ccb82b0f3f
--- /dev/null
+++ b/apps/codecs/Tremor/bitwise.c
@@ -0,0 +1,265 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
+ * *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
+ * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: packing variable sized words into an octet stream
+
+ ********************************************************************/
+
+/* We're 'LSb' endian; if we write a word but read individual bits,
+ then we'll read the lsb first */
+
+#include <string.h>
+#include <stdlib.h>
+#include "ogg.h"
+
+static unsigned long mask[]=
+{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
+ 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
+ 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
+ 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
+ 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
+ 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
+ 0x3fffffff,0x7fffffff,0xffffffff };
+
+/* mark read process as having run off the end */
+static void _adv_halt(oggpack_buffer *b){
+ b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
+ b->headend=-1;
+ b->headbit=0;
+}
+
+/* spans forward, skipping as many bytes as headend is negative; if
+ headend is zero, simply finds next byte. If we're up to the end
+ of the buffer, leaves headend at zero. If we've read past the end,
+ halt the decode process. */
+static void _span(oggpack_buffer *b){
+ while(b->headend<1){
+ if(b->head->next){
+ b->count+=b->head->length;
+ b->head=b->head->next;
+ b->headptr=b->head->buffer->data+b->head->begin-b->headend;
+ b->headend+=b->head->length;
+ }else{
+ /* we've either met the end of decode, or gone past it. halt
+ only if we're past */
+ if(b->headend<0 || b->headbit)
+ /* read has fallen off the end */
+ _adv_halt(b);
+
+ break;
+ }
+ }
+}
+
+void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
+ memset(b,0,sizeof(*b));
+
+ b->tail=b->head=r;
+ b->count=0;
+ b->headptr=b->head->buffer->data+b->head->begin;
+ b->headend=b->head->length;
+ _span(b);
+}
+
+#define _lookspan() while(!end){\
+ head=head->next;\
+ if(!head) return -1;\
+ ptr=head->buffer->data + head->begin;\
+ end=head->length;\
+ }
+
+/* Read in bits without advancing the bitptr; bits <= 32 */
+long oggpack_look(oggpack_buffer *b,int bits){
+ unsigned long m=mask[bits];
+ unsigned long ret;
+
+ bits+=b->headbit;
+
+ if(bits >= b->headend<<3){
+ int end=b->headend;
+ unsigned char *ptr=b->headptr;
+ ogg_reference *head=b->head;
+
+ if(end<0)return -1;
+
+ if(bits){
+ _lookspan();
+ ret=*ptr++>>b->headbit;
+ if(bits>8){
+ --end;
+ _lookspan();
+ ret|=*ptr++<<(8-b->headbit);
+ if(bits>16){
+ --end;
+ _lookspan();
+ ret|=*ptr++<<(16-b->headbit);
+ if(bits>24){
+ --end;
+ _lookspan();
+ ret|=*ptr++<<(24-b->headbit);
+ if(bits>32 && b->headbit){
+ --end;
+ _lookspan();
+ ret|=*ptr<<(32-b->headbit);
+ }
+ }
+ }
+ }
+ }
+
+ }else{
+
+ /* make this a switch jump-table */
+ ret=b->headptr[0]>>b->headbit;
+ if(bits>8){
+ ret|=b->headptr[1]<<(8-b->headbit);
+ if(bits>16){
+ ret|=b->headptr[2]<<(16-b->headbit);
+ if(bits>24){
+ ret|=b->headptr[3]<<(24-b->headbit);
+ if(bits>32 && b->headbit)
+ ret|=b->headptr[4]<<(32-b->headbit);
+ }
+ }
+ }
+ }
+
+ ret&=m;
+ return ret;
+}
+
+/* limited to 32 at a time */
+void oggpack_adv(oggpack_buffer *b,int bits){
+ bits+=b->headbit;
+ b->headbit=bits&7;
+ b->headptr+=bits/8;
+ if((b->headend-=bits/8)<1)_span(b);
+}
+
+/* spans forward and finds next byte. Never halts */
+static void _span_one(oggpack_buffer *b){
+ while(b->headend<1){
+ if(b->head->next){
+ b->count+=b->head->length;
+ b->head=b->head->next;
+ b->headptr=b->head->buffer->data+b->head->begin;
+ b->headend=b->head->length;
+ }else
+ break;
+ }
+}
+
+static int _halt_one(oggpack_buffer *b){
+ if(b->headend<1){
+ _adv_halt(b);
+ return -1;
+ }
+ return 0;
+}
+
+int oggpack_eop(oggpack_buffer *b){
+ if(b->headend<0)return -1;
+ return 0;
+}
+
+/* bits <= 32 */
+long oggpack_read(oggpack_buffer *b,int bits){
+ unsigned long m=mask[bits];
+ ogg_uint32_t ret;
+
+ bits+=b->headbit;
+
+ if(bits >= b->headend<<3){
+
+ if(b->headend<0)return -1;
+
+ if(bits){
+ if (_halt_one(b)) return -1;
+ ret=*b->headptr>>b->headbit;
+
+ if(bits>=8){
+ ++b->headptr;
+ --b->headend;
+ _span_one(b);
+ if(bits>8){
+ if (_halt_one(b)) return -1;
+ ret|=*b->headptr<<(8-b->headbit);
+
+ if(bits>=16){
+ ++b->headptr;
+ --b->headend;
+ _span_one(b);
+ if(bits>16){
+ if (_halt_one(b)) return -1;
+ ret|=*b->headptr<<(16-b->headbit);
+
+ if(bits>=24){
+ ++b->headptr;
+ --b->headend;
+ _span_one(b);
+ if(bits>24){
+ if (_halt_one(b)) return -1;
+ ret|=*b->headptr<<(24-b->headbit);
+
+ if(bits>=32){
+ ++b->headptr;
+ --b->headend;
+ _span_one(b);
+ if(bits>32){
+ if (_halt_one(b)) return -1;
+ if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }else{
+
+ ret=b->headptr[0]>>b->headbit;
+ if(bits>8){
+ ret|=b->headptr[1]<<(8-b->headbit);
+ if(bits>16){
+ ret|=b->headptr[2]<<(16-b->headbit);
+ if(bits>24){
+ ret|=b->headptr[3]<<(24-b->headbit);
+ if(bits>32 && b->headbit){
+ ret|=b->headptr[4]<<(32-b->headbit);
+ }
+ }
+ }
+ }
+
+ b->headptr+=bits/8;
+ b->headend-=bits/8;
+ }
+
+ ret&=m;
+ b->headbit=bits&7;
+ return ret;
+}
+
+long oggpack_bytes(oggpack_buffer *b){
+ return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
+ (b->headbit+7)/8);
+}
+
+long oggpack_bits(oggpack_buffer *b){
+ return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
+ b->headbit);
+}
+