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