#include "private/bitmath.h"
#include "private/crc.h"
+/*
+ * Along the way you will see two versions of some functions, selected
+ * by a FLAC__NO_MANUAL_INLINING macro. One is the simplified, more
+ * readable, and slow version, and the other is the same function
+ * where crucial parts have been manually inlined and are much faster.
+ *
+ */
+
/* This should be at least twice as large as the largest number of bytes required to represent any 'number' (in any encoding) you are going to read. */
static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = 65536; /* bytes */
}
}
-bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, uint32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, uint32 *val, const unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
#ifdef FLAC__NO_MANUAL_INLINING
{
unsigned i;
FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
bb->consumed_bytes++;
bb->consumed_bits = 0;
+ /* we hold off updating bb->total_consumed_bits until the end */
}
else {
*val = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits)) >> (i-bits_);
FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
bb->consumed_bytes++;
/* bb->consumed_bits is already 0 */
+ /* we hold off updating bb->total_consumed_bits until the end */
}
if(bits_ > 0) {
v <<= bits_;
v |= (bb->buffer[bb->consumed_bytes] >> (8-bits_));
bb->consumed_bits = bits_;
+ /* we hold off updating bb->total_consumed_bits until the end */
}
bb->total_consumed_bits += bits;
*val = v;
}
#endif
-bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, int32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, int32 *val, const unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+#ifdef FLAC__NO_MANUAL_INLINING
{
unsigned i;
- uint32 x;
+ uint32 v;
assert(bb != 0);
assert(bb->buffer != 0);
assert(bits <= 32);
- x = 0;
+ v = 0;
for(i = 0; i < bits; i++) {
- if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &x, read_callback, client_data))
+ if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data))
return false;
}
+
+ /* fix the sign */
+ i = 32 - bits;
+ if(i) {
+ v <<= i;
+ *val = (int32)v;
+ *val >>= i;
+ }
+ else
+ *val = (int32)v;
+
+ return true;
+}
+#else
+{
+ unsigned i, bits_ = bits;
+ uint32 v = 0;
+
+ assert(bb != 0);
+ assert(bb->buffer != 0);
+
+ assert(bits <= 32);
+ assert((bb->capacity*8) * 2 >= bits);
+
+ while(bb->total_consumed_bits + bits > bb->total_bits) {
+ if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
+ return false;
+ }
+ if(bb->consumed_bits) {
+ i = 8 - bb->consumed_bits;
+ if(i <= bits_) {
+ v = bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits);
+ bits_ -= i;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ else {
+ *val = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits)) >> (i-bits_);
+ bb->consumed_bits += bits_;
+ bb->total_consumed_bits += bits_;
+ return true;
+ }
+ }
+ while(bits_ >= 8) {
+ v <<= 8;
+ v |= bb->buffer[bb->consumed_bytes];
+ bits_ -= 8;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ /* bb->consumed_bits is already 0 */
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ if(bits_ > 0) {
+ v <<= bits_;
+ v |= (bb->buffer[bb->consumed_bytes] >> (8-bits_));
+ bb->consumed_bits = bits_;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ bb->total_consumed_bits += bits;
+
/* fix the sign */
i = 32 - bits;
if(i) {
- x <<= i;
- *val = (int32)x;
+ v <<= i;
+ *val = (int32)v;
*val >>= i;
}
else
- *val = (int32)x;
+ *val = (int32)v;
return true;
}
+#endif
-bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, uint64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, uint64 *val, const unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+#ifdef FLAC__NO_MANUAL_INLINING
{
unsigned i;
}
return true;
}
+#else
+{
+ unsigned i, bits_ = bits;
+ uint64 v = 0;
+
+ assert(bb != 0);
+ assert(bb->buffer != 0);
-bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, int64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+ assert(bits <= 64);
+ assert((bb->capacity*8) * 2 >= bits);
+
+ while(bb->total_consumed_bits + bits > bb->total_bits) {
+ if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
+ return false;
+ }
+ if(bb->consumed_bits) {
+ i = 8 - bb->consumed_bits;
+ if(i <= bits_) {
+ v = bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits);
+ bits_ -= i;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ else {
+ *val = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits)) >> (i-bits_);
+ bb->consumed_bits += bits_;
+ bb->total_consumed_bits += bits_;
+ return true;
+ }
+ }
+ while(bits_ >= 8) {
+ v <<= 8;
+ v |= bb->buffer[bb->consumed_bytes];
+ bits_ -= 8;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ /* bb->consumed_bits is already 0 */
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ if(bits_ > 0) {
+ v <<= bits_;
+ v |= (bb->buffer[bb->consumed_bytes] >> (8-bits_));
+ bb->consumed_bits = bits_;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ bb->total_consumed_bits += bits;
+ *val = v;
+ return true;
+}
+#endif
+
+bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, int64 *val, const unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+#ifdef FLAC__NO_MANUAL_INLINING
{
unsigned i;
- uint64 x;
+ uint64 v;
assert(bb != 0);
assert(bb->buffer != 0);
assert(bits <= 64);
- x = 0;
+ v = 0;
for(i = 0; i < bits; i++) {
- if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &x, read_callback, client_data))
+ if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data))
+ return false;
+ }
+ /* fix the sign */
+ i = 64 - bits;
+ if(i) {
+ v <<= i;
+ *val = (int64)v;
+ *val >>= i;
+ }
+ else
+ *val = (int64)v;
+
+ return true;
+}
+#else
+{
+ unsigned i, bits_ = bits;
+ uint64 v = 0;
+
+ assert(bb != 0);
+ assert(bb->buffer != 0);
+
+ assert(bits <= 64);
+ assert((bb->capacity*8) * 2 >= bits);
+
+ while(bb->total_consumed_bits + bits > bb->total_bits) {
+ if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
return false;
}
+ if(bb->consumed_bits) {
+ i = 8 - bb->consumed_bits;
+ if(i <= bits_) {
+ v = bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits);
+ bits_ -= i;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ else {
+ *val = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits)) >> (i-bits_);
+ bb->consumed_bits += bits_;
+ bb->total_consumed_bits += bits_;
+ return true;
+ }
+ }
+ while(bits_ >= 8) {
+ v <<= 8;
+ v |= bb->buffer[bb->consumed_bytes];
+ bits_ -= 8;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ /* bb->consumed_bits is already 0 */
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ if(bits_ > 0) {
+ v <<= bits_;
+ v |= (bb->buffer[bb->consumed_bytes] >> (8-bits_));
+ bb->consumed_bits = bits_;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ bb->total_consumed_bits += bits;
+
/* fix the sign */
i = 64 - bits;
if(i) {
- x <<= i;
- *val = (int64)x;
+ v <<= i;
+ *val = (int64)v;
*val >>= i;
}
else
- *val = (int64)x;
+ *val = (int64)v;
return true;
}
+#endif
bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
+#ifdef FLAC__NO_MANUAL_INLINING
{
unsigned bit, val_ = 0;
*val = val_;
return true;
}
+#else
+{
+ unsigned i, val_ = 0;
+ unsigned total_bytes_ = (bb->total_bits + 7) / 8;
+ byte b;
+
+ assert(bb != 0);
+ assert(bb->buffer != 0);
+
+ if(bb->consumed_bits) {
+ b = bb->buffer[bb->consumed_bytes] << bb->consumed_bits;
+ if(b) {
+ for(i = 0; !(b & 0x80); i++)
+ b <<= 1;
+ *val = i;
+ i++;
+ bb->consumed_bits += i;
+ bb->total_consumed_bits += i;
+ if(bb->consumed_bits == 8) {
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ }
+ return true;
+ }
+ else {
+ val_ = 8 - bb->consumed_bits;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ }
+ while(1) {
+ if(bb->consumed_bytes >= total_bytes_) {
+ if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
+ return false;
+ total_bytes_ = (bb->total_bits + 7) / 8;
+ }
+ b = bb->buffer[bb->consumed_bytes];
+ if(b) {
+ for(i = 0; !(b & 0x80); i++)
+ b <<= 1;
+ val_ += i;
+ i++;
+ bb->consumed_bits = i;
+ *val = val_;
+ if(i == 8) {
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ bb->consumed_bits = 0;
+ }
+ bb->total_consumed_bits += (++val_);
+ return true;
+ }
+ else {
+ val_ += 8;
+ FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
+ bb->consumed_bytes++;
+ /* bb->consumed_bits is already 0 */
+ /* we hold off updating bb->total_consumed_bits until the end */
+ }
+ }
+ return true;
+}
+#endif
bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
{
uint32 sign = 0, lsbs = 0, msbs = 0;
- unsigned bit;
assert(bb != 0);
assert(bb->buffer != 0);
assert(parameter <= 31);
/* read the unary MSBs and end bit */
- while(1) {
- if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data))
- return false;
- if(bit)
- break;
- else
- msbs++;
- }
+ if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data))
+ return false;
+
/* read the sign bit */
if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &sign, read_callback, client_data))
return false;
+
/* read the binary LSBs */
if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data))
return false;
bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
{
uint32 lsbs = 0, msbs = 0;
- unsigned bit, uval;
+ unsigned uval;
assert(bb != 0);
assert(bb->buffer != 0);
assert(parameter <= 31);
/* read the unary MSBs and end bit */
- while(1) {
- if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data))
- return false;
- if(bit)
- break;
- else
- msbs++;
- }
+ if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data))
+ return false;
+
/* read the binary LSBs */
if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data))
return false;
+
/* compose the value */
uval = (msbs << parameter) | lsbs;
if(uval & 1)
k = FLAC__bitmath_ilog2(parameter);
/* read the unary MSBs and end bit */
- while(1) {
- if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data))
- return false;
- if(bit)
- break;
- else
- msbs++;
- }
+ if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data))
+ return false;
+
/* read the binary LSBs */
if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data))
return false;
k = FLAC__bitmath_ilog2(parameter);
/* read the unary MSBs and end bit */
- while(1) {
- if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data))
- return false;
- if(bit)
- break;
- else
- msbs++;
- }
+ if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data))
+ return false;
+
/* read the binary LSBs */
if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data))
return false;