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>
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)
48 EXPORT
void speex_bits_init(SpeexBits
*bits
)
50 bits
->chars
= (char*)speex_alloc(MAX_CHARS_PER_FRAME
);
54 bits
->buf_size
= MAX_CHARS_PER_FRAME
;
58 speex_bits_reset(bits
);
61 EXPORT
void speex_bits_init_buffer(SpeexBits
*bits
, void *buff
, int buf_size
)
63 bits
->chars
= (char*)buff
;
64 bits
->buf_size
= buf_size
;
68 speex_bits_reset(bits
);
71 EXPORT
void speex_bits_set_bit_buffer(SpeexBits
*bits
, void *buff
, int buf_size
)
73 bits
->chars
= (char*)buff
;
74 bits
->buf_size
= buf_size
;
78 bits
->nbBits
=buf_size
<<LOG2_BITS_PER_CHAR
;
85 EXPORT
void speex_bits_destroy(SpeexBits
*bits
)
88 speex_free(bits
->chars
);
89 /* Will do something once the allocation is dynamic */
92 EXPORT
void speex_bits_reset(SpeexBits
*bits
)
94 /* We only need to clear the first byte now */
102 EXPORT
void speex_bits_rewind(SpeexBits
*bits
)
109 EXPORT
void speex_bits_read_from(SpeexBits
*bits
, char *chars
, int len
)
112 int nchars
= len
/ BYTES_PER_CHAR
;
113 if (nchars
> bits
->buf_size
)
115 speex_notify("Packet is larger than allocated buffer");
118 char *tmp
= (char*)speex_realloc(bits
->chars
, nchars
);
121 bits
->buf_size
=nchars
;
124 nchars
=bits
->buf_size
;
125 speex_warning("Could not resize input buffer: truncating input");
128 speex_warning("Do not own input buffer: truncating oversize input");
129 nchars
=bits
->buf_size
;
132 #if (BYTES_PER_CHAR==2)
133 /* Swap bytes to proper endian order (could be done externally) */
134 #define HTOLS(A) ((((A) >> 8)&0xff)|(((A) & 0xff)<<8))
138 for (i
=0;i
<nchars
;i
++)
139 bits
->chars
[i
]=HTOLS(chars
[i
]);
141 bits
->nbBits
=nchars
<<LOG2_BITS_PER_CHAR
;
147 static void speex_bits_flush(SpeexBits
*bits
)
149 int nchars
= ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
151 SPEEX_MOVE(bits
->chars
, &bits
->chars
[bits
->charPtr
], nchars
-bits
->charPtr
);
152 bits
->nbBits
-= bits
->charPtr
<<LOG2_BITS_PER_CHAR
;
156 EXPORT
void speex_bits_read_whole_bytes(SpeexBits
*bits
, char *chars
, int nbytes
)
159 int nchars
= nbytes
/BYTES_PER_CHAR
;
161 if (((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
)+nchars
> bits
->buf_size
)
163 /* Packet is larger than allocated buffer */
166 char *tmp
= (char*)speex_realloc(bits
->chars
, (bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1);
169 bits
->buf_size
=(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1;
172 nchars
=bits
->buf_size
-(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)-1;
173 speex_warning("Could not resize input buffer: truncating oversize input");
176 speex_warning("Do not own input buffer: truncating oversize input");
177 nchars
=bits
->buf_size
;
181 speex_bits_flush(bits
);
182 pos
=bits
->nbBits
>>LOG2_BITS_PER_CHAR
;
183 for (i
=0;i
<nchars
;i
++)
184 bits
->chars
[pos
+i
]=HTOLS(chars
[i
]);
185 bits
->nbBits
+=nchars
<<LOG2_BITS_PER_CHAR
;
188 EXPORT
int speex_bits_write(SpeexBits
*bits
, char *chars
, int max_nbytes
)
191 int max_nchars
= max_nbytes
/BYTES_PER_CHAR
;
192 int charPtr
, bitPtr
, nbBits
;
194 /* Insert terminator, but save the data so we can put it back after */
196 charPtr
=bits
->charPtr
;
198 speex_bits_insert_terminator(bits
);
200 bits
->charPtr
=charPtr
;
203 if (max_nchars
> ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
))
204 max_nchars
= ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
206 for (i
=0;i
<max_nchars
;i
++)
207 chars
[i
]=HTOLS(bits
->chars
[i
]);
208 return max_nchars
*BYTES_PER_CHAR
;
211 EXPORT
int speex_bits_write_whole_bytes(SpeexBits
*bits
, char *chars
, int max_nbytes
)
213 int max_nchars
= max_nbytes
/BYTES_PER_CHAR
;
215 if (max_nchars
> ((bits
->nbBits
)>>LOG2_BITS_PER_CHAR
))
216 max_nchars
= ((bits
->nbBits
)>>LOG2_BITS_PER_CHAR
);
217 for (i
=0;i
<max_nchars
;i
++)
218 chars
[i
]=HTOLS(bits
->chars
[i
]);
221 bits
->chars
[0]=bits
->chars
[max_nchars
];
225 bits
->nbBits
&= (BITS_PER_CHAR
-1);
226 return max_nchars
*BYTES_PER_CHAR
;
229 EXPORT
void speex_bits_pack(SpeexBits
*bits
, int data
, int nbBits
)
233 if (bits
->charPtr
+((nbBits
+bits
->bitPtr
)>>LOG2_BITS_PER_CHAR
) >= bits
->buf_size
)
235 speex_notify("Buffer too small to pack bits");
238 int new_nchars
= ((bits
->buf_size
+5)*3)>>1;
239 char *tmp
= (char*)speex_realloc(bits
->chars
, new_nchars
);
242 bits
->buf_size
=new_nchars
;
245 speex_warning("Could not resize input buffer: not packing");
249 speex_warning("Do not own input buffer: not packing");
257 bit
= (d
>>(nbBits
-1))&1;
258 bits
->chars
[bits
->charPtr
] |= bit
<<(BITS_PER_CHAR
-1-bits
->bitPtr
);
261 if (bits
->bitPtr
==BITS_PER_CHAR
)
265 bits
->chars
[bits
->charPtr
] = 0;
272 EXPORT
int speex_bits_unpack_signed(SpeexBits
*bits
, int nbBits
)
274 unsigned int d
=speex_bits_unpack_unsigned(bits
,nbBits
);
275 /* If number is negative */
283 EXPORT
unsigned int speex_bits_unpack_unsigned(SpeexBits
*bits
, int nbBits
)
286 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
293 d
|= (bits
->chars
[bits
->charPtr
]>>(BITS_PER_CHAR
-1 - bits
->bitPtr
))&1;
295 if (bits
->bitPtr
==BITS_PER_CHAR
)
305 EXPORT
unsigned int speex_bits_peek_unsigned(SpeexBits
*bits
, int nbBits
)
311 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
317 charPtr
=bits
->charPtr
;
322 d
|= (chars
[charPtr
]>>(BITS_PER_CHAR
-1 - bitPtr
))&1;
324 if (bitPtr
==BITS_PER_CHAR
)
334 EXPORT
int speex_bits_peek(SpeexBits
*bits
)
336 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+1>bits
->nbBits
)
340 return (bits
->chars
[bits
->charPtr
]>>(BITS_PER_CHAR
-1 - bits
->bitPtr
))&1;
343 EXPORT
void speex_bits_advance(SpeexBits
*bits
, int n
)
345 if (((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+n
>bits
->nbBits
) || bits
->overflow
){
349 bits
->charPtr
+= (bits
->bitPtr
+n
) >> LOG2_BITS_PER_CHAR
; /* divide by BITS_PER_CHAR */
350 bits
->bitPtr
= (bits
->bitPtr
+n
) & (BITS_PER_CHAR
-1); /* modulo by BITS_PER_CHAR */
353 EXPORT
int speex_bits_remaining(SpeexBits
*bits
)
358 return bits
->nbBits
-((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
);
361 EXPORT
int speex_bits_nbytes(SpeexBits
*bits
)
363 return ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
366 EXPORT
void speex_bits_insert_terminator(SpeexBits
*bits
)
369 speex_bits_pack(bits
, 0, 1);
371 speex_bits_pack(bits
, 1, 1);