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_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 if (len
> bits
->buf_size
)
98 speex_warning_int("Packet is larger than allocated buffer: ", len
);
101 char *tmp
= (char*)speex_realloc(bits
->chars
, len
);
108 speex_warning("Could not resize input buffer: truncating input");
111 speex_warning("Do not own input buffer: truncating input");
116 bits
->chars
[i
]=chars
[i
];
123 static void speex_bits_flush(SpeexBits
*bits
)
126 int nchars
= ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
129 for (i
=bits
->charPtr
;i
<nchars
; i
++)
130 bits
->chars
[i
-bits
->charPtr
]=bits
->chars
[i
];
132 bits
->nbBits
-= bits
->charPtr
<<LOG2_BITS_PER_CHAR
;
136 void speex_bits_read_whole_bytes(SpeexBits
*bits
, char *chars
, int nbytes
)
139 int nchars
= nbytes
/BYTES_PER_CHAR
;
141 if (((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
)+nchars
> bits
->buf_size
)
143 /* Packet is larger than allocated buffer */
146 char *tmp
= (char*)speex_realloc(bits
->chars
, (bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1);
149 bits
->buf_size
=(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1;
152 nchars
=bits
->buf_size
-(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)-1;
153 speex_warning("Could not resize input buffer: truncating input");
156 speex_warning("Do not own input buffer: truncating input");
157 nchars
=bits
->buf_size
;
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
;
168 int speex_bits_write(SpeexBits
*bits
, char *chars
, int max_nbytes
)
171 int max_nchars
= max_nbytes
/BYTES_PER_CHAR
;
172 int charPtr
, bitPtr
, nbBits
;
174 /* Insert terminator, but save the data so we can put it back after */
176 charPtr
=bits
->charPtr
;
178 speex_bits_insert_terminator(bits
);
180 bits
->charPtr
=charPtr
;
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
188 #define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
190 for (i
=0;i
<max_nchars
;i
++)
191 chars
[i
]=HTOLS(bits
->chars
[i
]);
192 return max_nchars
*BYTES_PER_CHAR
;
195 int speex_bits_write_whole_bytes(SpeexBits
*bits
, char *chars
, int max_nbytes
)
197 int max_nchars
= max_nbytes
/BYTES_PER_CHAR
;
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
];
205 bits
->chars
[0]=bits
->chars
[max_nchars
];
208 for (i
=1;i
<((bits
->nbBits
)>>LOG2_BITS_PER_CHAR
)+1;i
++)
211 bits
->nbBits
&= (BITS_PER_CHAR
-1);
212 return max_nchars
*BYTES_PER_CHAR
;
215 void speex_bits_pack(SpeexBits
*bits
, int data
, int nbBits
)
219 if (bits
->charPtr
+((nbBits
+bits
->bitPtr
)>>LOG2_BITS_PER_CHAR
) >= bits
->buf_size
)
221 speex_warning("Buffer too small to pack bits");
224 int new_nchars
= ((bits
->buf_size
+5)*3)>>1;
225 char *tmp
= (char*)speex_realloc(bits
->chars
, new_nchars
);
228 speex_memset_bytes(tmp
, 0, new_nchars
);
229 bits
->buf_size
=new_nchars
;
232 speex_warning("Could not resize input buffer: not packing");
236 speex_warning("Do not own input buffer: not packing");
244 bit
= (d
>>(nbBits
-1))&1;
245 bits
->chars
[bits
->charPtr
] |= bit
<<(BITS_PER_CHAR
-1-bits
->bitPtr
);
248 if (bits
->bitPtr
==BITS_PER_CHAR
)
252 bits
->chars
[bits
->charPtr
] = 0;
259 int speex_bits_unpack_signed(SpeexBits
*bits
, int nbBits
)
261 unsigned int d
=speex_bits_unpack_unsigned(bits
,nbBits
);
262 /* If number is negative */
270 unsigned int speex_bits_unpack_unsigned(SpeexBits
*bits
, int nbBits
)
273 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
280 d
|= (bits
->chars
[bits
->charPtr
]>>(BITS_PER_CHAR
-1 - bits
->bitPtr
))&1;
282 if (bits
->bitPtr
==BITS_PER_CHAR
)
292 unsigned int speex_bits_peek_unsigned(SpeexBits
*bits
, int nbBits
)
298 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
304 charPtr
=bits
->charPtr
;
309 d
|= (chars
[charPtr
]>>(BITS_PER_CHAR
-1 - bitPtr
))&1;
311 if (bitPtr
==BITS_PER_CHAR
)
321 int speex_bits_peek(SpeexBits
*bits
)
323 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+1>bits
->nbBits
)
327 return (bits
->chars
[bits
->charPtr
]>>(BITS_PER_CHAR
-1 - bits
->bitPtr
))&1;
330 void speex_bits_advance(SpeexBits
*bits
, int n
)
332 if (((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+n
>bits
->nbBits
) || bits
->overflow
){
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 */
340 int speex_bits_remaining(SpeexBits
*bits
)
345 return bits
->nbBits
-((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
);
348 int speex_bits_nbytes(SpeexBits
*bits
)
350 return ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
353 void speex_bits_insert_terminator(SpeexBits
*bits
)
356 speex_bits_pack(bits
, 0, 1);
358 speex_bits_pack(bits
, 1, 1);