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.
36 #include "config-speex.h"
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 #ifndef ROCKBOX_VOICE_CODEC
49 void speex_bits_init(SpeexBits
*bits
)
51 bits
->chars
= (char*)speex_alloc(MAX_CHARS_PER_FRAME
);
55 bits
->buf_size
= MAX_CHARS_PER_FRAME
;
59 speex_bits_reset(bits
);
63 void speex_bits_init_buffer(SpeexBits
*bits
, void *buff
, int buf_size
)
65 bits
->chars
= (char*)buff
;
66 bits
->buf_size
= buf_size
;
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
;
80 bits
->nbBits
=buf_size
<<LOG2_BITS_PER_CHAR
;
87 #ifndef ROCKBOX_VOICE_CODEC
88 void speex_bits_destroy(SpeexBits
*bits
)
91 speex_free(bits
->chars
);
92 /* Will do something once the allocation is dynamic */
96 void speex_bits_reset(SpeexBits
*bits
)
98 /* We only need to clear the first byte now */
106 void speex_bits_rewind(SpeexBits
*bits
)
113 #if !defined(SPEEX_VOICE_ENCODER) && !defined(ROCKBOX_VOICE_CODEC)
114 void speex_bits_read_from(SpeexBits
*bits
, char *chars
, int len
)
117 int nchars
= len
/ BYTES_PER_CHAR
;
118 if (nchars
> bits
->buf_size
)
120 speex_notify("Packet is larger than allocated buffer");
123 char *tmp
= (char*)speex_realloc(bits
->chars
, nchars
);
126 bits
->buf_size
=nchars
;
129 nchars
=bits
->buf_size
;
130 speex_warning("Could not resize input buffer: truncating input");
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))
143 for (i
=0;i
<nchars
;i
++)
144 bits
->chars
[i
]=HTOLS(chars
[i
]);
146 bits
->nbBits
=nchars
<<LOG2_BITS_PER_CHAR
;
152 static void speex_bits_flush(SpeexBits
*bits
)
154 int nchars
= ((bits
->nbBits
+BITS_PER_CHAR
-1)>>LOG2_BITS_PER_CHAR
);
156 SPEEX_MOVE(bits
->chars
, &bits
->chars
[bits
->charPtr
], nchars
-bits
->charPtr
);
157 bits
->nbBits
-= bits
->charPtr
<<LOG2_BITS_PER_CHAR
;
161 void speex_bits_read_whole_bytes(SpeexBits
*bits
, char *chars
, int nbytes
)
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 */
171 char *tmp
= (char*)speex_realloc(bits
->chars
, (bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1);
174 bits
->buf_size
=(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)+nchars
+1;
177 nchars
=bits
->buf_size
-(bits
->nbBits
>>LOG2_BITS_PER_CHAR
)-1;
178 speex_warning("Could not resize input buffer: truncating oversize input");
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
;
194 #ifndef SPEEX_DISABLE_ENCODER
195 int speex_bits_write(SpeexBits
*bits
, char *chars
, int max_nbytes
)
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 */
203 charPtr
=bits
->charPtr
;
205 speex_bits_insert_terminator(bits
);
207 bits
->charPtr
=charPtr
;
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
;
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
]);
228 bits
->chars
[0]=bits
->chars
[max_nchars
];
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
)
240 if (bits
->charPtr
+((nbBits
+bits
->bitPtr
)>>LOG2_BITS_PER_CHAR
) >= bits
->buf_size
)
242 speex_notify("Buffer too small to pack bits");
245 int new_nchars
= ((bits
->buf_size
+5)*3)>>1;
246 char *tmp
= (char*)speex_realloc(bits
->chars
, new_nchars
);
249 bits
->buf_size
=new_nchars
;
252 speex_warning("Could not resize input buffer: not packing");
256 speex_warning("Do not own input buffer: not packing");
264 bit
= (d
>>(nbBits
-1))&1;
265 bits
->chars
[bits
->charPtr
] |= bit
<<(BITS_PER_CHAR
-1-bits
->bitPtr
);
268 if (bits
->bitPtr
==BITS_PER_CHAR
)
272 bits
->chars
[bits
->charPtr
] = 0;
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 */
291 unsigned int speex_bits_unpack_unsigned(SpeexBits
*bits
, int nbBits
)
294 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
301 d
|= (bits
->chars
[bits
->charPtr
]>>(BITS_PER_CHAR
-1 - bits
->bitPtr
))&1;
303 if (bits
->bitPtr
==BITS_PER_CHAR
)
313 unsigned int speex_bits_peek_unsigned(SpeexBits
*bits
, int nbBits
)
319 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+nbBits
>bits
->nbBits
)
325 charPtr
=bits
->charPtr
;
330 d
|= (chars
[charPtr
]>>(BITS_PER_CHAR
-1 - bitPtr
))&1;
332 if (bitPtr
==BITS_PER_CHAR
)
342 int speex_bits_peek(SpeexBits
*bits
)
344 if ((bits
->charPtr
<<LOG2_BITS_PER_CHAR
)+bits
->bitPtr
+1>bits
->nbBits
)
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
){
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
)
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
)
378 speex_bits_pack(bits
, 0, 1);
380 speex_bits_pack(bits
, 1, 1);
382 #endif /* SPEEX_DISABLE_ENCODER */