1 /* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_bits.c
3
4 Handles bit packing/unpacking
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <speex/speex_bits.h>
40 #include "arch.h"
41 #include "os_support.h"
42
43 /* Maximum size of the bit-stream (for fixed-size allocation) */
44 #ifndef MAX_CHARS_PER_FRAME
45 #define MAX_CHARS_PER_FRAME (2000/BYTES_PER_CHAR)
46 #endif
47
speex_bits_init(SpeexBits * bits)48 EXPORT void speex_bits_init(SpeexBits *bits)
49 {
50 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
51 if (!bits->chars)
52 return;
53
54 bits->buf_size = MAX_CHARS_PER_FRAME;
55
56 bits->owner=1;
57
58 speex_bits_reset(bits);
59 }
60
speex_bits_init_buffer(SpeexBits * bits,void * buff,int buf_size)61 EXPORT void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
62 {
63 bits->chars = (char*)buff;
64 bits->buf_size = buf_size;
65
66 bits->owner=0;
67
68 speex_bits_reset(bits);
69 }
70
speex_bits_set_bit_buffer(SpeexBits * bits,void * buff,int buf_size)71 EXPORT void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
72 {
73 bits->chars = (char*)buff;
74 bits->buf_size = buf_size;
75
76 bits->owner=0;
77
78 bits->nbBits=buf_size<<LOG2_BITS_PER_CHAR;
79 bits->charPtr=0;
80 bits->bitPtr=0;
81 bits->overflow=0;
82
83 }
84
speex_bits_destroy(SpeexBits * bits)85 EXPORT void speex_bits_destroy(SpeexBits *bits)
86 {
87 if (bits->owner)
88 speex_free(bits->chars);
89 /* Will do something once the allocation is dynamic */
90 }
91
speex_bits_reset(SpeexBits * bits)92 EXPORT void speex_bits_reset(SpeexBits *bits)
93 {
94 /* We only need to clear the first byte now */
95 bits->chars[0]=0;
96 bits->nbBits=0;
97 bits->charPtr=0;
98 bits->bitPtr=0;
99 bits->overflow=0;
100 }
101
speex_bits_rewind(SpeexBits * bits)102 EXPORT void speex_bits_rewind(SpeexBits *bits)
103 {
104 bits->charPtr=0;
105 bits->bitPtr=0;
106 bits->overflow=0;
107 }
108
speex_bits_read_from(SpeexBits * bits,char * chars,int len)109 EXPORT void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
110 {
111 int i;
112 int nchars = len / BYTES_PER_CHAR;
113 if (nchars > bits->buf_size)
114 {
115 speex_notify("Packet is larger than allocated buffer");
116 if (bits->owner)
117 {
118 char *tmp = (char*)speex_realloc(bits->chars, nchars);
119 if (tmp)
120 {
121 bits->buf_size=nchars;
122 bits->chars=tmp;
123 } else {
124 nchars=bits->buf_size;
125 speex_warning("Could not resize input buffer: truncating input");
126 }
127 } else {
128 speex_warning("Do not own input buffer: truncating oversize input");
129 nchars=bits->buf_size;
130 }
131 }
132 #if (BYTES_PER_CHAR==2)
133 /* Swap bytes to proper endian order (could be done externally) */
134 #define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
135 #else
136 #define HTOLS(A) (A)
137 #endif
138 for (i=0;i<nchars;i++)
139 bits->chars[i]=HTOLS(chars[i]);
140
141 bits->nbBits=nchars<<LOG2_BITS_PER_CHAR;
142 bits->charPtr=0;
143 bits->bitPtr=0;
144 bits->overflow=0;
145 }
146
speex_bits_flush(SpeexBits * bits)147 static void speex_bits_flush(SpeexBits *bits)
148 {
149 int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
150 if (bits->charPtr>0)
151 SPEEX_MOVE(bits->chars, &bits->chars[bits->charPtr], nchars-bits->charPtr);
152 bits->nbBits -= bits->charPtr<<LOG2_BITS_PER_CHAR;
153 bits->charPtr=0;
154 }
155
speex_bits_read_whole_bytes(SpeexBits * bits,char * chars,int nbytes)156 EXPORT void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
157 {
158 int i,pos;
159 int nchars = nbytes/BYTES_PER_CHAR;
160
161 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
162 {
163 /* Packet is larger than allocated buffer */
164 if (bits->owner)
165 {
166 char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1);
167 if (tmp)
168 {
169 bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1;
170 bits->chars=tmp;
171 } else {
172 nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1;
173 speex_warning("Could not resize input buffer: truncating oversize input");
174 }
175 } else {
176 speex_warning("Do not own input buffer: truncating oversize input");
177 nchars=bits->buf_size;
178 }
179 }
180
181 speex_bits_flush(bits);
182 pos=bits->nbBits>>LOG2_BITS_PER_CHAR;
183 for (i=0;i<nchars;i++)
184 bits->chars[pos+i]=HTOLS(chars[i]);
185 bits->nbBits+=nchars<<LOG2_BITS_PER_CHAR;
186 }
187
speex_bits_write(SpeexBits * bits,char * chars,int max_nbytes)188 EXPORT int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
189 {
190 int i;
191 int max_nchars = max_nbytes/BYTES_PER_CHAR;
192 int charPtr, bitPtr, nbBits;
193
194 /* Insert terminator, but save the data so we can put it back after */
195 bitPtr=bits->bitPtr;
196 charPtr=bits->charPtr;
197 nbBits=bits->nbBits;
198 speex_bits_insert_terminator(bits);
199 bits->bitPtr=bitPtr;
200 bits->charPtr=charPtr;
201 bits->nbBits=nbBits;
202
203 if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR))
204 max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
205
206 for (i=0;i<max_nchars;i++)
207 chars[i]=HTOLS(bits->chars[i]);
208 return max_nchars*BYTES_PER_CHAR;
209 }
210
speex_bits_write_whole_bytes(SpeexBits * bits,char * chars,int max_nbytes)211 EXPORT int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
212 {
213 int max_nchars = max_nbytes/BYTES_PER_CHAR;
214 int i;
215 if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR))
216 max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR);
217 for (i=0;i<max_nchars;i++)
218 chars[i]=HTOLS(bits->chars[i]);
219
220 if (bits->bitPtr>0)
221 bits->chars[0]=bits->chars[max_nchars];
222 else
223 bits->chars[0]=0;
224 bits->charPtr=0;
225 bits->nbBits &= (BITS_PER_CHAR-1);
226 return max_nchars*BYTES_PER_CHAR;
227 }
228
speex_bits_pack(SpeexBits * bits,int data,int nbBits)229 EXPORT void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
230 {
231 unsigned int d=data;
232
233 if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size)
234 {
235 speex_notify("Buffer too small to pack bits");
236 if (bits->owner)
237 {
238 int new_nchars = ((bits->buf_size+5)*3)>>1;
239 char *tmp = (char*)speex_realloc(bits->chars, new_nchars);
240 if (tmp)
241 {
242 bits->buf_size=new_nchars;
243 bits->chars=tmp;
244 } else {
245 speex_warning("Could not resize input buffer: not packing");
246 return;
247 }
248 } else {
249 speex_warning("Do not own input buffer: not packing");
250 return;
251 }
252 }
253
254 while(nbBits)
255 {
256 int bit;
257 bit = (d>>(nbBits-1))&1;
258 bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr);
259 bits->bitPtr++;
260
261 if (bits->bitPtr==BITS_PER_CHAR)
262 {
263 bits->bitPtr=0;
264 bits->charPtr++;
265 bits->chars[bits->charPtr] = 0;
266 }
267 bits->nbBits++;
268 nbBits--;
269 }
270 }
271
speex_bits_unpack_signed(SpeexBits * bits,int nbBits)272 EXPORT int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
273 {
274 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
275 /* If number is negative */
276 if (d>>(nbBits-1))
277 {
278 d |= (-1)<<nbBits;
279 }
280 return d;
281 }
282
speex_bits_unpack_unsigned(SpeexBits * bits,int nbBits)283 EXPORT unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
284 {
285 unsigned int d=0;
286 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
287 bits->overflow=1;
288 if (bits->overflow)
289 return 0;
290 while(nbBits)
291 {
292 d<<=1;
293 d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
294 bits->bitPtr++;
295 if (bits->bitPtr==BITS_PER_CHAR)
296 {
297 bits->bitPtr=0;
298 bits->charPtr++;
299 }
300 nbBits--;
301 }
302 return d;
303 }
304
speex_bits_peek_unsigned(SpeexBits * bits,int nbBits)305 EXPORT unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
306 {
307 unsigned int d=0;
308 int bitPtr, charPtr;
309 char *chars;
310
311 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
312 bits->overflow=1;
313 if (bits->overflow)
314 return 0;
315
316 bitPtr=bits->bitPtr;
317 charPtr=bits->charPtr;
318 chars = bits->chars;
319 while(nbBits)
320 {
321 d<<=1;
322 d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1;
323 bitPtr++;
324 if (bitPtr==BITS_PER_CHAR)
325 {
326 bitPtr=0;
327 charPtr++;
328 }
329 nbBits--;
330 }
331 return d;
332 }
333
speex_bits_peek(SpeexBits * bits)334 EXPORT int speex_bits_peek(SpeexBits *bits)
335 {
336 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
337 bits->overflow=1;
338 if (bits->overflow)
339 return 0;
340 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
341 }
342
speex_bits_advance(SpeexBits * bits,int n)343 EXPORT void speex_bits_advance(SpeexBits *bits, int n)
344 {
345 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
346 bits->overflow=1;
347 return;
348 }
349 bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */
350 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
351 }
352
speex_bits_remaining(SpeexBits * bits)353 EXPORT int speex_bits_remaining(SpeexBits *bits)
354 {
355 if (bits->overflow)
356 return -1;
357 else
358 return bits->nbBits-((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr);
359 }
360
speex_bits_nbytes(SpeexBits * bits)361 EXPORT int speex_bits_nbytes(SpeexBits *bits)
362 {
363 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
364 }
365
speex_bits_insert_terminator(SpeexBits * bits)366 EXPORT void speex_bits_insert_terminator(SpeexBits *bits)
367 {
368 if (bits->bitPtr)
369 speex_bits_pack(bits, 0, 1);
370 while (bits->bitPtr)
371 speex_bits_pack(bits, 1, 1);
372 }
373