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_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 
speex_bits_init(SpeexBits * bits)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 
speex_bits_init_buffer(SpeexBits * bits,void * buff,int buf_size)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 
speex_bits_destroy(SpeexBits * bits)70 void 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 
speex_bits_reset(SpeexBits * bits)77 void 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 
speex_bits_rewind(SpeexBits * bits)86 void speex_bits_rewind(SpeexBits *bits)
87 {
88    bits->charPtr=0;
89    bits->bitPtr=0;
90    bits->overflow=0;
91 }
92 
speex_bits_read_from(SpeexBits * bits,char * chars,int len)93 void 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 
speex_bits_flush(SpeexBits * bits)123 static 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 
speex_bits_read_whole_bytes(SpeexBits * bits,char * chars,int nbytes)136 void 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 
speex_bits_write(SpeexBits * bits,char * chars,int max_nbytes)168 int 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 
speex_bits_write_whole_bytes(SpeexBits * bits,char * chars,int max_nbytes)195 int 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 
speex_bits_pack(SpeexBits * bits,int data,int nbBits)215 void 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 
speex_bits_unpack_signed(SpeexBits * bits,int nbBits)259 int 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 
speex_bits_unpack_unsigned(SpeexBits * bits,int nbBits)270 unsigned 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 
speex_bits_peek_unsigned(SpeexBits * bits,int nbBits)292 unsigned 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 
speex_bits_peek(SpeexBits * bits)321 int 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 
speex_bits_advance(SpeexBits * bits,int n)330 void 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 
speex_bits_remaining(SpeexBits * bits)340 int 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 
speex_bits_nbytes(SpeexBits * bits)348 int speex_bits_nbytes(SpeexBits *bits)
349 {
350    return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
351 }
352 
speex_bits_insert_terminator(SpeexBits * bits)353 void 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 }
360