diff options
author | Marcoen Hirschberg <marcoen@gmail.com> | 2005-02-17 09:08:18 +0000 |
---|---|---|
committer | Marcoen Hirschberg <marcoen@gmail.com> | 2005-02-17 09:08:18 +0000 |
commit | 99d2599b79649fd5a7df13b4e43383c428cc5657 (patch) | |
tree | 5512330f8ad66d5bae14a0ed990601e3bf29f520 /apps/codecs/Tremor/bitwise.c | |
parent | e3e116d3c732c99d95fe11f11726ed8a5b587fc4 (diff) | |
download | rockbox-99d2599b79649fd5a7df13b4e43383c428cc5657.tar.gz rockbox-99d2599b79649fd5a7df13b4e43383c428cc5657.zip |
Initial commit of the the Ogg Vorbis 'Tremor' integer playback codec
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5996 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/Tremor/bitwise.c')
-rw-r--r-- | apps/codecs/Tremor/bitwise.c | 265 |
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 @@ | |||
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: packing variable sized words into an octet stream | ||
15 | |||
16 | ********************************************************************/ | ||
17 | |||
18 | /* We're 'LSb' endian; if we write a word but read individual bits, | ||
19 | then we'll read the lsb first */ | ||
20 | |||
21 | #include <string.h> | ||
22 | #include <stdlib.h> | ||
23 | #include "ogg.h" | ||
24 | |||
25 | static unsigned long mask[]= | ||
26 | {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, | ||
27 | 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, | ||
28 | 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, | ||
29 | 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, | ||
30 | 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, | ||
31 | 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, | ||
32 | 0x3fffffff,0x7fffffff,0xffffffff }; | ||
33 | |||
34 | /* mark read process as having run off the end */ | ||
35 | static void _adv_halt(oggpack_buffer *b){ | ||
36 | b->headptr=b->head->buffer->data+b->head->begin+b->head->length; | ||
37 | b->headend=-1; | ||
38 | b->headbit=0; | ||
39 | } | ||
40 | |||
41 | /* spans forward, skipping as many bytes as headend is negative; if | ||
42 | headend is zero, simply finds next byte. If we're up to the end | ||
43 | of the buffer, leaves headend at zero. If we've read past the end, | ||
44 | halt the decode process. */ | ||
45 | static void _span(oggpack_buffer *b){ | ||
46 | while(b->headend<1){ | ||
47 | if(b->head->next){ | ||
48 | b->count+=b->head->length; | ||
49 | b->head=b->head->next; | ||
50 | b->headptr=b->head->buffer->data+b->head->begin-b->headend; | ||
51 | b->headend+=b->head->length; | ||
52 | }else{ | ||
53 | /* we've either met the end of decode, or gone past it. halt | ||
54 | only if we're past */ | ||
55 | if(b->headend<0 || b->headbit) | ||
56 | /* read has fallen off the end */ | ||
57 | _adv_halt(b); | ||
58 | |||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){ | ||
65 | memset(b,0,sizeof(*b)); | ||
66 | |||
67 | b->tail=b->head=r; | ||
68 | b->count=0; | ||
69 | b->headptr=b->head->buffer->data+b->head->begin; | ||
70 | b->headend=b->head->length; | ||
71 | _span(b); | ||
72 | } | ||
73 | |||
74 | #define _lookspan() while(!end){\ | ||
75 | head=head->next;\ | ||
76 | if(!head) return -1;\ | ||
77 | ptr=head->buffer->data + head->begin;\ | ||
78 | end=head->length;\ | ||
79 | } | ||
80 | |||
81 | /* Read in bits without advancing the bitptr; bits <= 32 */ | ||
82 | long oggpack_look(oggpack_buffer *b,int bits){ | ||
83 | unsigned long m=mask[bits]; | ||
84 | unsigned long ret; | ||
85 | |||
86 | bits+=b->headbit; | ||
87 | |||
88 | if(bits >= b->headend<<3){ | ||
89 | int end=b->headend; | ||
90 | unsigned char *ptr=b->headptr; | ||
91 | ogg_reference *head=b->head; | ||
92 | |||
93 | if(end<0)return -1; | ||
94 | |||
95 | if(bits){ | ||
96 | _lookspan(); | ||
97 | ret=*ptr++>>b->headbit; | ||
98 | if(bits>8){ | ||
99 | --end; | ||
100 | _lookspan(); | ||
101 | ret|=*ptr++<<(8-b->headbit); | ||
102 | if(bits>16){ | ||
103 | --end; | ||
104 | _lookspan(); | ||
105 | ret|=*ptr++<<(16-b->headbit); | ||
106 | if(bits>24){ | ||
107 | --end; | ||
108 | _lookspan(); | ||
109 | ret|=*ptr++<<(24-b->headbit); | ||
110 | if(bits>32 && b->headbit){ | ||
111 | --end; | ||
112 | _lookspan(); | ||
113 | ret|=*ptr<<(32-b->headbit); | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | }else{ | ||
121 | |||
122 | /* make this a switch jump-table */ | ||
123 | ret=b->headptr[0]>>b->headbit; | ||
124 | if(bits>8){ | ||
125 | ret|=b->headptr[1]<<(8-b->headbit); | ||
126 | if(bits>16){ | ||
127 | ret|=b->headptr[2]<<(16-b->headbit); | ||
128 | if(bits>24){ | ||
129 | ret|=b->headptr[3]<<(24-b->headbit); | ||
130 | if(bits>32 && b->headbit) | ||
131 | ret|=b->headptr[4]<<(32-b->headbit); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | ret&=m; | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | /* limited to 32 at a time */ | ||
142 | void oggpack_adv(oggpack_buffer *b,int bits){ | ||
143 | bits+=b->headbit; | ||
144 | b->headbit=bits&7; | ||
145 | b->headptr+=bits/8; | ||
146 | if((b->headend-=bits/8)<1)_span(b); | ||
147 | } | ||
148 | |||
149 | /* spans forward and finds next byte. Never halts */ | ||
150 | static void _span_one(oggpack_buffer *b){ | ||
151 | while(b->headend<1){ | ||
152 | if(b->head->next){ | ||
153 | b->count+=b->head->length; | ||
154 | b->head=b->head->next; | ||
155 | b->headptr=b->head->buffer->data+b->head->begin; | ||
156 | b->headend=b->head->length; | ||
157 | }else | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static int _halt_one(oggpack_buffer *b){ | ||
163 | if(b->headend<1){ | ||
164 | _adv_halt(b); | ||
165 | return -1; | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | int oggpack_eop(oggpack_buffer *b){ | ||
171 | if(b->headend<0)return -1; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /* bits <= 32 */ | ||
176 | long oggpack_read(oggpack_buffer *b,int bits){ | ||
177 | unsigned long m=mask[bits]; | ||
178 | ogg_uint32_t ret; | ||
179 | |||
180 | bits+=b->headbit; | ||
181 | |||
182 | if(bits >= b->headend<<3){ | ||
183 | |||
184 | if(b->headend<0)return -1; | ||
185 | |||
186 | if(bits){ | ||
187 | if (_halt_one(b)) return -1; | ||
188 | ret=*b->headptr>>b->headbit; | ||
189 | |||
190 | if(bits>=8){ | ||
191 | ++b->headptr; | ||
192 | --b->headend; | ||
193 | _span_one(b); | ||
194 | if(bits>8){ | ||
195 | if (_halt_one(b)) return -1; | ||
196 | ret|=*b->headptr<<(8-b->headbit); | ||
197 | |||
198 | if(bits>=16){ | ||
199 | ++b->headptr; | ||
200 | --b->headend; | ||
201 | _span_one(b); | ||
202 | if(bits>16){ | ||
203 | if (_halt_one(b)) return -1; | ||
204 | ret|=*b->headptr<<(16-b->headbit); | ||
205 | |||
206 | if(bits>=24){ | ||
207 | ++b->headptr; | ||
208 | --b->headend; | ||
209 | _span_one(b); | ||
210 | if(bits>24){ | ||
211 | if (_halt_one(b)) return -1; | ||
212 | ret|=*b->headptr<<(24-b->headbit); | ||
213 | |||
214 | if(bits>=32){ | ||
215 | ++b->headptr; | ||
216 | --b->headend; | ||
217 | _span_one(b); | ||
218 | if(bits>32){ | ||
219 | if (_halt_one(b)) return -1; | ||
220 | if(b->headbit)ret|=*b->headptr<<(32-b->headbit); | ||
221 | |||
222 | } | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | }else{ | ||
232 | |||
233 | ret=b->headptr[0]>>b->headbit; | ||
234 | if(bits>8){ | ||
235 | ret|=b->headptr[1]<<(8-b->headbit); | ||
236 | if(bits>16){ | ||
237 | ret|=b->headptr[2]<<(16-b->headbit); | ||
238 | if(bits>24){ | ||
239 | ret|=b->headptr[3]<<(24-b->headbit); | ||
240 | if(bits>32 && b->headbit){ | ||
241 | ret|=b->headptr[4]<<(32-b->headbit); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | b->headptr+=bits/8; | ||
248 | b->headend-=bits/8; | ||
249 | } | ||
250 | |||
251 | ret&=m; | ||
252 | b->headbit=bits&7; | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | long oggpack_bytes(oggpack_buffer *b){ | ||
257 | return(b->count+b->headptr-b->head->buffer->data-b->head->begin+ | ||
258 | (b->headbit+7)/8); | ||
259 | } | ||
260 | |||
261 | long oggpack_bits(oggpack_buffer *b){ | ||
262 | return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+ | ||
263 | b->headbit); | ||
264 | } | ||
265 | |||