blob: fae7a9e079fba348d8b13f0e25448270989a1ec6 [file] [log] [blame]
Benny Prijonoeb30bf52006-03-04 20:43:52 +00001/* 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 "misc.h"
41
42/* Maximum size of the bit-stream (for fixed-size allocation) */
43#ifndef MAX_CHARS_PER_FRAME
44#define MAX_CHARS_PER_FRAME (2000/BYTES_PER_CHAR)
45#endif
46
47void speex_bits_init(SpeexBits *bits)
48{
49 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
50 if (!bits->chars)
51 return;
52
53 bits->buf_size = MAX_CHARS_PER_FRAME;
54
55 bits->owner=1;
56
57 speex_bits_reset(bits);
58}
59
60void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
61{
62 bits->chars = (char*)buff;
63 bits->buf_size = buf_size;
64
65 bits->owner=0;
66
67 speex_bits_reset(bits);
68}
69
70void speex_bits_destroy(SpeexBits *bits)
71{
72 if (bits->owner)
73 speex_free(bits->chars);
74 /* Will do something once the allocation is dynamic */
75}
76
77void speex_bits_reset(SpeexBits *bits)
78{
79 bits->chars[0]=0;
80 bits->nbBits=0;
81 bits->charPtr=0;
82 bits->bitPtr=0;
83 bits->overflow=0;
84}
85
86void speex_bits_rewind(SpeexBits *bits)
87{
88 bits->charPtr=0;
89 bits->bitPtr=0;
90 bits->overflow=0;
91}
92
93void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
94{
95 int i;
96 if (len > bits->buf_size)
97 {
98 speex_warning_int("Packet is larger than allocated buffer: ", len);
99 if (bits->owner)
100 {
101 char *tmp = (char*)speex_realloc(bits->chars, len);
102 if (tmp)
103 {
104 bits->buf_size=len;
105 bits->chars=tmp;
106 } else {
107 len=bits->buf_size;
108 speex_warning("Could not resize input buffer: truncating input");
109 }
110 } else {
111 speex_warning("Do not own input buffer: truncating input");
112 len=bits->buf_size;
113 }
114 }
115 for (i=0;i<len;i++)
116 bits->chars[i]=chars[i];
117 bits->nbBits=len<<3;
118 bits->charPtr=0;
119 bits->bitPtr=0;
120 bits->overflow=0;
121}
122
123static void speex_bits_flush(SpeexBits *bits)
124{
125 int i;
126 int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
127 if (bits->charPtr>0)
128 {
129 for (i=bits->charPtr;i<nchars; i++)
130 bits->chars[i-bits->charPtr]=bits->chars[i];
131 }
132 bits->nbBits -= bits->charPtr<<LOG2_BITS_PER_CHAR;
133 bits->charPtr=0;
134}
135
136void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
137{
138 int i,pos;
139 int nchars = nbytes/BYTES_PER_CHAR;
140
141 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
142 {
143 /* Packet is larger than allocated buffer */
144 if (bits->owner)
145 {
146 char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1);
147 if (tmp)
148 {
149 bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1;
150 bits->chars=tmp;
151 } else {
152 nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1;
153 speex_warning("Could not resize input buffer: truncating input");
154 }
155 } else {
156 speex_warning("Do not own input buffer: truncating input");
157 nchars=bits->buf_size;
158 }
159 }
160
161 speex_bits_flush(bits);
162 pos=bits->nbBits>>LOG2_BITS_PER_CHAR;
163 for (i=0;i<nchars;i++)
164 bits->chars[pos+i]=chars[i];
165 bits->nbBits+=nchars<<LOG2_BITS_PER_CHAR;
166}
167
168int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
169{
170 int i;
171 int max_nchars = max_nbytes/BYTES_PER_CHAR;
172 int charPtr, bitPtr, nbBits;
173
174 /* Insert terminator, but save the data so we can put it back after */
175 bitPtr=bits->bitPtr;
176 charPtr=bits->charPtr;
177 nbBits=bits->nbBits;
178 speex_bits_insert_terminator(bits);
179 bits->bitPtr=bitPtr;
180 bits->charPtr=charPtr;
181 bits->nbBits=nbBits;
182
183 if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR))
184 max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
185#if BYTES_PER_CHAR==1
186#define HTOLS(A) (A)
187#else
188#define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
189#endif
190 for (i=0;i<max_nchars;i++)
191 chars[i]=HTOLS(bits->chars[i]);
192 return max_nchars*BYTES_PER_CHAR;
193}
194
195int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
196{
197 int max_nchars = max_nbytes/BYTES_PER_CHAR;
198 int i;
199 if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR))
200 max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR);
201 for (i=0;i<max_nchars;i++)
202 chars[i]=bits->chars[i];
203
204 if (bits->bitPtr>0)
205 bits->chars[0]=bits->chars[max_nchars];
206 else
207 bits->chars[0]=0;
208 for (i=1;i<((bits->nbBits)>>LOG2_BITS_PER_CHAR)+1;i++)
209 bits->chars[i]=0;
210 bits->charPtr=0;
211 bits->nbBits &= (BITS_PER_CHAR-1);
212 return max_nchars*BYTES_PER_CHAR;
213}
214
215void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
216{
217 unsigned int d=data;
218
219 if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size)
220 {
221 speex_warning("Buffer too small to pack bits");
222 if (bits->owner)
223 {
224 int new_nchars = ((bits->buf_size+5)*3)>>1;
225 char *tmp = (char*)speex_realloc(bits->chars, new_nchars);
226 if (tmp)
227 {
228 speex_memset_bytes(tmp, 0, new_nchars);
229 bits->buf_size=new_nchars;
230 bits->chars=tmp;
231 } else {
232 speex_warning("Could not resize input buffer: not packing");
233 return;
234 }
235 } else {
236 speex_warning("Do not own input buffer: not packing");
237 return;
238 }
239 }
240
241 while(nbBits)
242 {
243 int bit;
244 bit = (d>>(nbBits-1))&1;
245 bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr);
246 bits->bitPtr++;
247
248 if (bits->bitPtr==BITS_PER_CHAR)
249 {
250 bits->bitPtr=0;
251 bits->charPtr++;
252 bits->chars[bits->charPtr] = 0;
253 }
254 bits->nbBits++;
255 nbBits--;
256 }
257}
258
259int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
260{
261 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
262 /* If number is negative */
263 if (d>>(nbBits-1))
264 {
265 d |= (-1)<<nbBits;
266 }
267 return d;
268}
269
270unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
271{
272 unsigned int d=0;
273 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
274 bits->overflow=1;
275 if (bits->overflow)
276 return 0;
277 while(nbBits)
278 {
279 d<<=1;
280 d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
281 bits->bitPtr++;
282 if (bits->bitPtr==BITS_PER_CHAR)
283 {
284 bits->bitPtr=0;
285 bits->charPtr++;
286 }
287 nbBits--;
288 }
289 return d;
290}
291
292unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
293{
294 unsigned int d=0;
295 int bitPtr, charPtr;
296 char *chars;
297
298 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
299 bits->overflow=1;
300 if (bits->overflow)
301 return 0;
302
303 bitPtr=bits->bitPtr;
304 charPtr=bits->charPtr;
305 chars = bits->chars;
306 while(nbBits)
307 {
308 d<<=1;
309 d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1;
310 bitPtr++;
311 if (bitPtr==BITS_PER_CHAR)
312 {
313 bitPtr=0;
314 charPtr++;
315 }
316 nbBits--;
317 }
318 return d;
319}
320
321int speex_bits_peek(SpeexBits *bits)
322{
323 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
324 bits->overflow=1;
325 if (bits->overflow)
326 return 0;
327 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
328}
329
330void speex_bits_advance(SpeexBits *bits, int n)
331{
332 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
333 bits->overflow=1;
334 return;
335 }
336 bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */
337 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
338}
339
340int speex_bits_remaining(SpeexBits *bits)
341{
342 if (bits->overflow)
343 return -1;
344 else
345 return bits->nbBits-((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr);
346}
347
348int speex_bits_nbytes(SpeexBits *bits)
349{
350 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
351}
352
353void speex_bits_insert_terminator(SpeexBits *bits)
354{
355 if (bits->bitPtr)
356 speex_bits_pack(bits, 0, 1);
357 while (bits->bitPtr)
358 speex_bits_pack(bits, 1, 1);
359}