1 /* Copyright (C) 2002 Jean-Marc Valin
4 Handles bit packing/unpacking
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
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.
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.
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.
39 #include <speex/speex_bits.h>
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)
47 void speex_bits_init(SpeexBits *bits)
49 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
53 bits->buf_size = MAX_CHARS_PER_FRAME;
57 speex_bits_reset(bits);
60 void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
62 bits->chars = (char*)buff;
63 bits->buf_size = buf_size;
67 speex_bits_reset(bits);
70 void speex_bits_destroy(SpeexBits *bits)
73 speex_free(bits->chars);
74 /* Will do something once the allocation is dynamic */
77 void speex_bits_reset(SpeexBits *bits)
86 void speex_bits_rewind(SpeexBits *bits)
93 void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
96 int nchars = len / BYTES_PER_CHAR;
97 if (nchars > bits->buf_size)
99 speex_warning_int("Packet is larger than allocated buffer: ", len);
102 char *tmp = (char*)speex_realloc(bits->chars, nchars);
105 bits->buf_size=nchars;
108 nchars=bits->buf_size;
109 speex_warning("Could not resize input buffer: truncating input");
112 speex_warning("Do not own input buffer: truncating input");
113 nchars=bits->buf_size;
116 #if (BYTES_PER_CHAR==2)
117 /* Swap bytes to proper endian order (could be done externally) */
118 #define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
122 for (i=0;i<nchars;i++)
123 bits->chars[i]=HTOLS(chars[i]);
125 bits->nbBits=nchars<<LOG2_BITS_PER_CHAR;
131 static void speex_bits_flush(SpeexBits *bits)
134 int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
137 for (i=bits->charPtr;i<nchars; i++)
138 bits->chars[i-bits->charPtr]=bits->chars[i];
140 bits->nbBits -= bits->charPtr<<LOG2_BITS_PER_CHAR;
144 void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
147 int nchars = nbytes/BYTES_PER_CHAR;
149 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
151 /* Packet is larger than allocated buffer */
154 char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1);
157 bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1;
160 nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1;
161 speex_warning("Could not resize input buffer: truncating input");
164 speex_warning("Do not own input buffer: truncating input");
165 nchars=bits->buf_size;
169 speex_bits_flush(bits);
170 pos=bits->nbBits>>LOG2_BITS_PER_CHAR;
171 for (i=0;i<nchars;i++)
172 bits->chars[pos+i]=HTOLS(chars[i]);
173 bits->nbBits+=nchars<<LOG2_BITS_PER_CHAR;
176 int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
179 int max_nchars = max_nbytes/BYTES_PER_CHAR;
180 int charPtr, bitPtr, nbBits;
182 /* Insert terminator, but save the data so we can put it back after */
184 charPtr=bits->charPtr;
186 speex_bits_insert_terminator(bits);
188 bits->charPtr=charPtr;
191 if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR))
192 max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
194 for (i=0;i<max_nchars;i++)
195 chars[i]=HTOLS(bits->chars[i]);
196 return max_nchars*BYTES_PER_CHAR;
199 int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
201 int max_nchars = max_nbytes/BYTES_PER_CHAR;
203 if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR))
204 max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR);
205 for (i=0;i<max_nchars;i++)
206 chars[i]=HTOLS(bits->chars[i]);
209 bits->chars[0]=bits->chars[max_nchars];
212 for (i=1;i<((bits->nbBits)>>LOG2_BITS_PER_CHAR)+1;i++)
215 bits->nbBits &= (BITS_PER_CHAR-1);
216 return max_nchars*BYTES_PER_CHAR;
219 void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
223 if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size)
225 speex_warning("Buffer too small to pack bits");
228 int new_nchars = ((bits->buf_size+5)*3)>>1;
229 char *tmp = (char*)speex_realloc(bits->chars, new_nchars);
232 speex_memset_bytes(tmp, 0, new_nchars);
233 bits->buf_size=new_nchars;
236 speex_warning("Could not resize input buffer: not packing");
240 speex_warning("Do not own input buffer: not packing");
248 bit = (d>>(nbBits-1))&1;
249 bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr);
252 if (bits->bitPtr==BITS_PER_CHAR)
256 bits->chars[bits->charPtr] = 0;
263 int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
265 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
266 /* If number is negative */
274 unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
277 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
284 d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
286 if (bits->bitPtr==BITS_PER_CHAR)
296 unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
302 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
308 charPtr=bits->charPtr;
313 d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1;
315 if (bitPtr==BITS_PER_CHAR)
325 int speex_bits_peek(SpeexBits *bits)
327 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
331 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
334 void speex_bits_advance(SpeexBits *bits, int n)
336 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
340 bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */
341 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
344 int speex_bits_remaining(SpeexBits *bits)
349 return bits->nbBits-((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr);
352 int speex_bits_nbytes(SpeexBits *bits)
354 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
357 void speex_bits_insert_terminator(SpeexBits *bits)
360 speex_bits_pack(bits, 0, 1);
362 speex_bits_pack(bits, 1, 1);