Build doom on clipv2 and clip+
[kugel-rb.git] / apps / codecs / libspeex / bits.c
blob9d6cad88862a320ca4c3aa0f052fcb64201c82fe
1 /* Copyright (C) 2002 Jean-Marc Valin
2 File: speex_bits.c
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
8 are met:
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.
35 #ifdef HAVE_CONFIG_H
36 #include "config-speex.h"
37 #endif
39 #include "speex/speex_bits.h"
40 #include "arch.h"
41 #include "os_support.h"
43 /* Maximum size of the bit-stream (for fixed-size allocation) */
44 #ifndef MAX_CHARS_PER_FRAME
45 #define MAX_CHARS_PER_FRAME (2000/BYTES_PER_CHAR)
46 #endif
48 #ifndef ROCKBOX_VOICE_CODEC
49 void speex_bits_init(SpeexBits *bits)
51 bits->chars = (char*)speex_alloc(MAX_CHARS_PER_FRAME);
52 if (!bits->chars)
53 return;
55 bits->buf_size = MAX_CHARS_PER_FRAME;
57 bits->owner=1;
59 speex_bits_reset(bits);
61 #endif
63 void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size)
65 bits->chars = (char*)buff;
66 bits->buf_size = buf_size;
68 bits->owner=0;
70 speex_bits_reset(bits);
73 void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size)
75 bits->chars = (char*)buff;
76 bits->buf_size = buf_size;
78 bits->owner=0;
80 bits->nbBits=buf_size<<LOG2_BITS_PER_CHAR;
81 bits->charPtr=0;
82 bits->bitPtr=0;
83 bits->overflow=0;
87 #ifndef ROCKBOX_VOICE_CODEC
88 void speex_bits_destroy(SpeexBits *bits)
90 if (bits->owner)
91 speex_free(bits->chars);
92 /* Will do something once the allocation is dynamic */
94 #endif
96 void speex_bits_reset(SpeexBits *bits)
98 /* We only need to clear the first byte now */
99 bits->chars[0]=0;
100 bits->nbBits=0;
101 bits->charPtr=0;
102 bits->bitPtr=0;
103 bits->overflow=0;
106 void speex_bits_rewind(SpeexBits *bits)
108 bits->charPtr=0;
109 bits->bitPtr=0;
110 bits->overflow=0;
113 #if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC)
114 void speex_bits_read_from(SpeexBits *bits, char *chars, int len)
116 int i;
117 int nchars = len / BYTES_PER_CHAR;
118 if (nchars > bits->buf_size)
120 speex_notify("Packet is larger than allocated buffer");
121 if (bits->owner)
123 char *tmp = (char*)speex_realloc(bits->chars, nchars);
124 if (tmp)
126 bits->buf_size=nchars;
127 bits->chars=tmp;
128 } else {
129 nchars=bits->buf_size;
130 speex_warning("Could not resize input buffer: truncating input");
132 } else {
133 speex_warning("Do not own input buffer: truncating oversize input");
134 nchars=bits->buf_size;
137 #if (BYTES_PER_CHAR==2)
138 /* Swap bytes to proper endian order (could be done externally) */
139 #define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
140 #else
141 #define HTOLS(A) (A)
142 #endif
143 for (i=0;i<nchars;i++)
144 bits->chars[i]=HTOLS(chars[i]);
146 bits->nbBits=nchars<<LOG2_BITS_PER_CHAR;
147 bits->charPtr=0;
148 bits->bitPtr=0;
149 bits->overflow=0;
152 static void speex_bits_flush(SpeexBits *bits)
154 int nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
155 if (bits->charPtr>0)
156 SPEEX_MOVE(bits->chars, &bits->chars[bits->charPtr], nchars-bits->charPtr);
157 bits->nbBits -= bits->charPtr<<LOG2_BITS_PER_CHAR;
158 bits->charPtr=0;
161 void speex_bits_read_whole_bytes(SpeexBits *bits, char *chars, int nbytes)
163 int i,pos;
164 int nchars = nbytes/BYTES_PER_CHAR;
166 if (((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR)+nchars > bits->buf_size)
168 /* Packet is larger than allocated buffer */
169 if (bits->owner)
171 char *tmp = (char*)speex_realloc(bits->chars, (bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1);
172 if (tmp)
174 bits->buf_size=(bits->nbBits>>LOG2_BITS_PER_CHAR)+nchars+1;
175 bits->chars=tmp;
176 } else {
177 nchars=bits->buf_size-(bits->nbBits>>LOG2_BITS_PER_CHAR)-1;
178 speex_warning("Could not resize input buffer: truncating oversize input");
180 } else {
181 speex_warning("Do not own input buffer: truncating oversize input");
182 nchars=bits->buf_size;
186 speex_bits_flush(bits);
187 pos=bits->nbBits>>LOG2_BITS_PER_CHAR;
188 for (i=0;i<nchars;i++)
189 bits->chars[pos+i]=HTOLS(chars[i]);
190 bits->nbBits+=nchars<<LOG2_BITS_PER_CHAR;
192 #endif
194 #ifndef SPEEX_DISABLE_ENCODER
195 int speex_bits_write(SpeexBits *bits, char *chars, int max_nbytes)
197 int i;
198 int max_nchars = max_nbytes/BYTES_PER_CHAR;
199 int charPtr, bitPtr, nbBits;
201 /* Insert terminator, but save the data so we can put it back after */
202 bitPtr=bits->bitPtr;
203 charPtr=bits->charPtr;
204 nbBits=bits->nbBits;
205 speex_bits_insert_terminator(bits);
206 bits->bitPtr=bitPtr;
207 bits->charPtr=charPtr;
208 bits->nbBits=nbBits;
210 if (max_nchars > ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR))
211 max_nchars = ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
213 for (i=0;i<max_nchars;i++)
214 chars[i]=HTOLS(bits->chars[i]);
215 return max_nchars*BYTES_PER_CHAR;
218 int speex_bits_write_whole_bytes(SpeexBits *bits, char *chars, int max_nbytes)
220 int max_nchars = max_nbytes/BYTES_PER_CHAR;
221 int i;
222 if (max_nchars > ((bits->nbBits)>>LOG2_BITS_PER_CHAR))
223 max_nchars = ((bits->nbBits)>>LOG2_BITS_PER_CHAR);
224 for (i=0;i<max_nchars;i++)
225 chars[i]=HTOLS(bits->chars[i]);
227 if (bits->bitPtr>0)
228 bits->chars[0]=bits->chars[max_nchars];
229 else
230 bits->chars[0]=0;
231 bits->charPtr=0;
232 bits->nbBits &= (BITS_PER_CHAR-1);
233 return max_nchars*BYTES_PER_CHAR;
236 void speex_bits_pack(SpeexBits *bits, int data, int nbBits)
238 unsigned int d=data;
240 if (bits->charPtr+((nbBits+bits->bitPtr)>>LOG2_BITS_PER_CHAR) >= bits->buf_size)
242 speex_notify("Buffer too small to pack bits");
243 if (bits->owner)
245 int new_nchars = ((bits->buf_size+5)*3)>>1;
246 char *tmp = (char*)speex_realloc(bits->chars, new_nchars);
247 if (tmp)
249 bits->buf_size=new_nchars;
250 bits->chars=tmp;
251 } else {
252 speex_warning("Could not resize input buffer: not packing");
253 return;
255 } else {
256 speex_warning("Do not own input buffer: not packing");
257 return;
261 while(nbBits)
263 int bit;
264 bit = (d>>(nbBits-1))&1;
265 bits->chars[bits->charPtr] |= bit<<(BITS_PER_CHAR-1-bits->bitPtr);
266 bits->bitPtr++;
268 if (bits->bitPtr==BITS_PER_CHAR)
270 bits->bitPtr=0;
271 bits->charPtr++;
272 bits->chars[bits->charPtr] = 0;
274 bits->nbBits++;
275 nbBits--;
278 #endif /* SPEEX_DISABLE_ENCODER */
280 int speex_bits_unpack_signed(SpeexBits *bits, int nbBits)
282 unsigned int d=speex_bits_unpack_unsigned(bits,nbBits);
283 /* If number is negative */
284 if (d>>(nbBits-1))
286 d |= (-1)<<nbBits;
288 return d;
291 unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits)
293 unsigned int d=0;
294 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
295 bits->overflow=1;
296 if (bits->overflow)
297 return 0;
298 while(nbBits)
300 d<<=1;
301 d |= (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
302 bits->bitPtr++;
303 if (bits->bitPtr==BITS_PER_CHAR)
305 bits->bitPtr=0;
306 bits->charPtr++;
308 nbBits--;
310 return d;
313 unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits)
315 unsigned int d=0;
316 int bitPtr, charPtr;
317 char *chars;
319 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+nbBits>bits->nbBits)
320 bits->overflow=1;
321 if (bits->overflow)
322 return 0;
324 bitPtr=bits->bitPtr;
325 charPtr=bits->charPtr;
326 chars = bits->chars;
327 while(nbBits)
329 d<<=1;
330 d |= (chars[charPtr]>>(BITS_PER_CHAR-1 - bitPtr))&1;
331 bitPtr++;
332 if (bitPtr==BITS_PER_CHAR)
334 bitPtr=0;
335 charPtr++;
337 nbBits--;
339 return d;
342 int speex_bits_peek(SpeexBits *bits)
344 if ((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+1>bits->nbBits)
345 bits->overflow=1;
346 if (bits->overflow)
347 return 0;
348 return (bits->chars[bits->charPtr]>>(BITS_PER_CHAR-1 - bits->bitPtr))&1;
351 void speex_bits_advance(SpeexBits *bits, int n)
353 if (((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr+n>bits->nbBits) || bits->overflow){
354 bits->overflow=1;
355 return;
357 bits->charPtr += (bits->bitPtr+n) >> LOG2_BITS_PER_CHAR; /* divide by BITS_PER_CHAR */
358 bits->bitPtr = (bits->bitPtr+n) & (BITS_PER_CHAR-1); /* modulo by BITS_PER_CHAR */
361 int speex_bits_remaining(SpeexBits *bits)
363 if (bits->overflow)
364 return -1;
365 else
366 return bits->nbBits-((bits->charPtr<<LOG2_BITS_PER_CHAR)+bits->bitPtr);
369 int speex_bits_nbytes(SpeexBits *bits)
371 return ((bits->nbBits+BITS_PER_CHAR-1)>>LOG2_BITS_PER_CHAR);
374 #ifndef SPEEX_DISABLE_ENCODER
375 void speex_bits_insert_terminator(SpeexBits *bits)
377 if (bits->bitPtr)
378 speex_bits_pack(bits, 0, 1);
379 while (bits->bitPtr)
380 speex_bits_pack(bits, 1, 1);
382 #endif /* SPEEX_DISABLE_ENCODER */