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