new blurb-based bitbuffer design changes
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 12 Mar 2002 16:19:54 +0000 (16:19 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 12 Mar 2002 16:19:54 +0000 (16:19 +0000)
src/libFLAC/bitbuffer.c
src/libFLAC/include/private/bitbuffer.h
src/libFLAC/stream_decoder.c
src/libFLAC/stream_encoder.c
src/libFLAC/stream_encoder_framing.c

index b10436c..b084961 100644 (file)
  *
  */
 
-/* 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 */
+/*
+ * This should be at least twice as large as the largest number of blurbs
+ * required to represent any 'number' (in any encoding) you are going to
+ * read.  With FLAC this is on the order of maybe a few hundred bits.
+ * If the buffer is smaller than that, the decoder won't be able to read
+ * in a whole number that is in a variable length encoding (e.g. Rice).
+ *
+ * The number we are actually using here is based on what would be the
+ * approximate maximum size of a verbatim frame at the default block size,
+ * for CD audio (4096 sample * 4 bytes per sample), plus some wiggle room.
+ * 32kbytes sounds reasonable.  For kicks we subtract out 64 bytes for any
+ * alignment or malloc overhead.
+ *
+ * Increase this number to decrease the number of read callbacks, at the
+ * expense of using more memory.  Or decrease for the reverse effect,
+ * keeping in mind the limit from the first paragraph.
+ */
+static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = ((65536 - 64) * 8) / FLAC__BITS_PER_BLURB; /* blurbs */
+
+#if FLAC__BITS_PER_BLURB == 8
+#define FLAC__BITS_PER_BLURB_LOG2 3
+#define FLAC__BYTES_PER_BLURB 1
+#define FLAC__BLURB_ALL_ONES ((FLAC__byte)0xff)
+#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__byte)0x80)
+#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)'\x80') >> (b))
+#define CRC16_UPDATE_BLURB(bb, blurb, crc) FLAC__CRC16_UPDATE((blurb), (crc));
+#elif FLAC__BITS_PER_BLURB == 32
+#define FLAC__BITS_PER_BLURB_LOG2 5
+#define FLAC__BYTES_PER_BLURB 4
+#define FLAC__BLURB_ALL_ONES ((FLAC__uint32)0xffffffff)
+#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__uint32)0x80000000)
+#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)0x80000000) >> (b))
+#define CRC16_UPDATE_BLURB(bb, blurb, crc) crc16_update_blurb((bb), (blurb));
+#else
+/* ERROR, only sizes of 8 and 32 are supported */
+#endif
 
-#define BYTE_BIT_TO_MASK(b) (((FLAC__byte)'\x80') >> (b))
+#define FLAC__BLURBS_TO_BITS(blurbs) ((blurbs) << FLAC__BITS_PER_BLURB_LOG2)
 
 #ifdef min
 #undef min
@@ -50,9 +84,58 @@ static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = 65536; /* bytes */
 #define FLaC__INLINE
 #endif
 
+struct FLAC__BitBuffer {
+       FLAC__blurb *buffer;
+       unsigned capacity; /* in blurbs */
+       unsigned blurbs, bits;
+       unsigned total_bits; /* must always == FLAC__BITS_PER_BLURB*blurbs+bits */
+       unsigned consumed_blurbs, consumed_bits;
+       unsigned total_consumed_bits; /* must always == FLAC__BITS_PER_BLURB*consumed_blurbs+consumed_bits */
+       FLAC__uint16 read_crc16;
+#if FLAC__BITS_PER_BLURB == 32
+       unsigned crc16_align;
+#endif
+       FLAC__blurb save_head, save_tail;
+};
+
+static void crc16_update_blurb(FLAC__BitBuffer *bb, FLAC__blurb blurb)
+{
+#if FLAC__BITS_PER_BLURB == 32
+       if(bb->crc16_align == 0) {
+               FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16);
+               FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16);
+               FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16);
+               FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16);
+       }
+       else if(bb->crc16_align == 8) {
+               FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16);
+               FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16);
+               FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16);
+       }
+       else if(bb->crc16_align == 16) {
+               FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16);
+               FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16);
+       }
+       else if(bb->crc16_align == 24) {
+               FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16);
+       }
+       bb->crc16_align = 0;
+#else
+       (void)bb; (void)blurb;
+       FLAC__ASSERT(false);
+#endif
+}
+
+/*
+ * WATCHOUT: The current implentation is not friendly to shrinking, i.e. it
+ * does not shift left what is consumed, it just chops off the end, whether
+ * there is unconsumed data there or not.  This is OK because currently we
+ * never shrink the buffer, but if this ever changes, we'll have to do some
+ * fixups here.
+ */
 static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity)
 {
-       FLAC__byte *new_buffer;
+       FLAC__blurb *new_buffer;
 
        FLAC__ASSERT(bb != 0);
        FLAC__ASSERT(bb->buffer != 0);
@@ -60,20 +143,20 @@ static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity)
        if(bb->capacity == new_capacity)
                return true;
 
-       new_buffer = (FLAC__byte*)malloc(sizeof(FLAC__byte) * new_capacity);
+       new_buffer = (FLAC__blurb*)malloc(sizeof(FLAC__blurb) * new_capacity);
        if(new_buffer == 0)
                return false;
-       memset(new_buffer, 0, new_capacity);
-       memcpy(new_buffer, bb->buffer, sizeof(FLAC__byte)*min(bb->bytes+(bb->bits?1:0), new_capacity));
-       if(new_capacity < bb->bytes+(bb->bits?1:0)) {
-               bb->bytes = new_capacity;
+       memset(new_buffer, 0, sizeof(FLAC__blurb) * new_capacity);
+       memcpy(new_buffer, bb->buffer, sizeof(FLAC__blurb)*min(bb->blurbs+(bb->bits?1:0), new_capacity));
+       if(new_capacity < bb->blurbs+(bb->bits?1:0)) {
+               bb->blurbs = new_capacity;
                bb->bits = 0;
-               bb->total_bits = (new_capacity<<3);
+               bb->total_bits = FLAC__BLURBS_TO_BITS(new_capacity);
        }
-       if(new_capacity < bb->consumed_bytes+(bb->consumed_bits?1:0)) {
-               bb->consumed_bytes = new_capacity;
+       if(new_capacity < bb->consumed_blurbs+(bb->consumed_bits?1:0)) {
+               bb->consumed_blurbs = new_capacity;
                bb->consumed_bits = 0;
-               bb->total_consumed_bits = (new_capacity<<3);
+               bb->total_consumed_bits = FLAC__BLURBS_TO_BITS(new_capacity);
        }
        free(bb->buffer); // we've already asserted above that (bb->buffer != 0)
        bb->buffer = new_buffer;
@@ -81,13 +164,13 @@ static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity)
        return true;
 }
 
-static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_bytes_to_add)
+static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_blurbs_to_add)
 {
        unsigned new_capacity;
 
-       FLAC__ASSERT(min_bytes_to_add > 0);
+       FLAC__ASSERT(min_blurbs_to_add > 0);
 
-       new_capacity = max(bb->capacity * 4, bb->capacity + min_bytes_to_add);
+       new_capacity = max(bb->capacity * 2, bb->capacity + min_blurbs_to_add);
        return bitbuffer_resize_(bb, new_capacity);
 }
 
@@ -96,8 +179,8 @@ static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_a
        FLAC__ASSERT(bb != 0);
        FLAC__ASSERT(bb->buffer != 0);
 
-       if((bb->capacity<<3) < bb->total_bits + bits_to_add)
-               return bitbuffer_grow_(bb, (bits_to_add>>3)+2);
+       if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits_to_add)
+               return bitbuffer_grow_(bb, (bits_to_add >> FLAC__BITS_PER_BLURB_LOG2) + 2);
        else
                return true;
 }
@@ -105,74 +188,123 @@ static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_a
 static FLAC__bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data)
 {
        unsigned bytes;
+       FLAC__byte *target;
 
        /* first shift the unconsumed buffer data toward the front as much as possible */
-       if(bb->total_consumed_bits >= 8) {
-               unsigned l = 0, r = bb->consumed_bytes, r_end = bb->bytes;
+       if(bb->total_consumed_bits >= FLAC__BITS_PER_BLURB) {
+               unsigned l = 0, r = bb->consumed_blurbs, r_end = bb->blurbs + (bb->bits? 1:0);
                for( ; r < r_end; l++, r++)
                        bb->buffer[l] = bb->buffer[r];
                for( ; l < r_end; l++)
                        bb->buffer[l] = 0;
-               bb->bytes -= bb->consumed_bytes;
-               bb->total_bits -= (bb->consumed_bytes<<3);
-               bb->consumed_bytes = 0;
+               bb->blurbs -= bb->consumed_blurbs;
+               bb->total_bits -= FLAC__BLURBS_TO_BITS(bb->consumed_blurbs);
+               bb->consumed_blurbs = 0;
                bb->total_consumed_bits = bb->consumed_bits;
        }
+
        /* grow if we need to */
        if(bb->capacity <= 1) {
                if(!bitbuffer_resize_(bb, 16))
                        return false;
        }
+
+       /* set the target for reading, taking into account blurb alignment */
+#if FLAC__BITS_PER_BLURB == 8
+       /* blurb == byte, so no gyrations necessary: */
+       target = bb->buffer + bb->blurbs;
+       bytes = bb->capacity - bb->blurbs;
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       FLAC__ASSERT((bb->bits & 7) == 0);
+       target = (FLAC__byte*)(bb->buffer + bb->blurbs) + (bb->bits >> 3);
+       bytes = ((bb->capacity - bb->blurbs) << 2) - (bb->bits >> 3); /* i.e. (bb->capacity - bb->blurbs) * FLAC__BYTES_PER_BLURB - (bb->bits / 8) */
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+
        /* finally, read in some data */
-       bytes = bb->capacity - bb->bytes;
-       if(!read_callback(bb->buffer+bb->bytes, &bytes, client_data))
+       if(!read_callback(target, &bytes, client_data))
                return false;
-       bb->bytes += bytes;
-       bb->total_bits += (bytes<<3);
+
+       /* now we have to handle partial blurb cases: */
+#if FLAC__BITS_PER_BLURB == 8
+       /* blurb == byte, so no gyrations necessary: */
+       bb->blurbs += bytes;
+       bb->total_bits += FLAC__BLURBS_TO_BITS(bytes);
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       {
+               const unsigned aligned_bytes = (bb->bits >> 3) + bytes;
+               bb->blurbs += (aligned_bytes >> 2); /* i.e. aligned_bytes / FLAC__BYTES_PER_BLURB */
+               bb->bits = (aligned_bytes & 3u) << 3; /* i.e. (aligned_bytes % FLAC__BYTES_PER_BLURB) * 8 */
+               bb->total_bits += (bytes << 3);
+       }
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
        return true;
 }
 
-void FLAC__bitbuffer_init(FLAC__BitBuffer *bb)
+/***********************************************************************
+ *
+ * Class constructor/destructor
+ *
+ ***********************************************************************/
+
+FLAC__BitBuffer *FLAC__bitbuffer_new()
+{
+       return (FLAC__BitBuffer*)malloc(sizeof(FLAC__BitBuffer));
+}
+
+void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb)
 {
        FLAC__ASSERT(bb != 0);
 
-       bb->buffer = 0;
-       bb->capacity = 0;
-       bb->bytes = bb->bits = bb->total_bits = 0;
-       bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
+       FLAC__bitbuffer_free(bb);
+       free(bb);
 }
 
-FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes)
+/***********************************************************************
+ *
+ * Public class methods
+ *
+ ***********************************************************************/
+
+FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb)
 {
        FLAC__ASSERT(bb != 0);
-       FLAC__bitbuffer_init(bb);
 
-       if(bytes == 0)
-               return true;
-       else {
-               FLAC__ASSERT(buffer != 0);
-               bb->buffer = (FLAC__byte*)malloc(sizeof(FLAC__byte)*bytes);
-               if(bb->buffer == 0)
-                       return false;
-               memcpy(bb->buffer, buffer, sizeof(FLAC__byte)*bytes);
-               bb->capacity = bb->bytes = bytes;
-               bb->bits = 0;
-               bb->total_bits = (bytes<<3);
-               bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
-               return true;
-       }
+       bb->buffer = 0;
+       bb->capacity = 0;
+       bb->blurbs = bb->bits = bb->total_bits = 0;
+       bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0;
+
+       return FLAC__bitbuffer_clear(bb);
 }
 
-void FLAC__bitbuffer_init_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed)
+FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes)
 {
        FLAC__ASSERT(bb != 0);
+       FLAC__ASSERT(bytes > 0);
 
-       bb->read_crc16 = seed;
+       if(!FLAC__bitbuffer_init(bb))
+               return false;
+
+       if(!bitbuffer_ensure_size_(bb, bytes << 3))
+               return false;
+
+       FLAC__ASSERT(buffer != 0);
+       /* @@@ WATCHOUT: code currently only works for 8-bits-per-blurb inclusive-or big-endian: */
+       memcpy((FLAC__byte*)bb->buffer, buffer, sizeof(FLAC__byte)*bytes);
+       bb->blurbs = bytes / FLAC__BYTES_PER_BLURB;
+       bb->bits = (bytes % FLAC__BYTES_PER_BLURB) << 3;
+       bb->total_bits = bytes << 3;
+       return true;
 }
 
 FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src)
 {
-       static const FLAC__byte mask_[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
        unsigned bits_to_add = src->total_bits - src->total_consumed_bits;
 
        FLAC__ASSERT(dest != 0);
@@ -185,20 +317,20 @@ FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC
        if(!bitbuffer_ensure_size_(dest, bits_to_add))
                return false;
        if(dest->bits == 0) {
-               memcpy(dest->buffer+dest->bytes, src->buffer+src->consumed_bytes, src->bytes-src->consumed_bytes + ((src->bits)? 1:0));
+               memcpy(dest->buffer+dest->blurbs, src->buffer+src->consumed_blurbs, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs + ((src->bits)? 1:0)));
        }
-       else if(dest->bits + bits_to_add > 8) {
-               dest->buffer[dest->bytes] <<= (8 - dest->bits);
-               dest->buffer[dest->bytes] |= (src->buffer[src->consumed_bytes] & mask_[8-dest->bits]);
-               memcpy(dest->buffer+dest->bytes+1, src->buffer+src->consumed_bytes+1, src->bytes-src->consumed_bytes-1 + ((src->bits)? 1:0));
+       else if(dest->bits + bits_to_add > FLAC__BITS_PER_BLURB) {
+               dest->buffer[dest->blurbs] <<= (FLAC__BITS_PER_BLURB - dest->bits);
+               dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << (FLAC__BITS_PER_BLURB-dest->bits)) - 1));
+               memcpy(dest->buffer+dest->blurbs+1, src->buffer+src->consumed_blurbs+1, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs-1 + ((src->bits)? 1:0)));
        }
        else {
-               dest->buffer[dest->bytes] <<= bits_to_add;
-               dest->buffer[dest->bytes] |= (src->buffer[src->consumed_bytes] & mask_[bits_to_add]);
+               dest->buffer[dest->blurbs] <<= bits_to_add;
+               dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << bits_to_add) - 1));
        }
        dest->bits = src->bits;
        dest->total_bits += bits_to_add;
-       dest->bytes = dest->total_bits / 8;
+       dest->blurbs = dest->total_bits / FLAC__BITS_PER_BLURB;
 
        return true;
 }
@@ -211,24 +343,24 @@ void FLAC__bitbuffer_free(FLAC__BitBuffer *bb)
                free(bb->buffer);
        bb->buffer = 0;
        bb->capacity = 0;
-       bb->bytes = bb->bits = bb->total_bits = 0;
-       bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
+       bb->blurbs = bb->bits = bb->total_bits = 0;
+       bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0;
 }
 
 FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb)
 {
        if(bb->buffer == 0) {
                bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY;
-               bb->buffer = (FLAC__byte*)malloc(sizeof(FLAC__byte) * bb->capacity);
+               bb->buffer = (FLAC__blurb*)malloc(sizeof(FLAC__blurb) * bb->capacity);
                if(bb->buffer == 0)
                        return false;
                memset(bb->buffer, 0, bb->capacity);
        }
        else {
-               memset(bb->buffer, 0, bb->bytes + (bb->bits?1:0));
+               memset(bb->buffer, 0, bb->blurbs + (bb->bits?1:0));
        }
-       bb->bytes = bb->bits = bb->total_bits = 0;
-       bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
+       bb->blurbs = bb->bits = bb->total_bits = 0;
+       bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0;
        return true;
 }
 
@@ -242,17 +374,162 @@ FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *s
        if(dest->capacity < src->capacity)
                if(!bitbuffer_resize_(dest, src->capacity))
                        return false;
-       memcpy(dest->buffer, src->buffer, sizeof(FLAC__byte)*min(src->capacity, src->bytes+1));
-       dest->bytes = src->bytes;
+       memcpy(dest->buffer, src->buffer, sizeof(FLAC__blurb)*min(src->capacity, src->blurbs+1));
+       dest->blurbs = src->blurbs;
        dest->bits = src->bits;
        dest->total_bits = src->total_bits;
-       dest->consumed_bytes = src->consumed_bytes;
+       dest->consumed_blurbs = src->consumed_blurbs;
        dest->consumed_bits = src->consumed_bits;
        dest->total_consumed_bits = src->total_consumed_bits;
        dest->read_crc16 = src->read_crc16;
        return true;
 }
 
+void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed)
+{
+       FLAC__ASSERT(bb != 0);
+       FLAC__ASSERT(bb->buffer != 0);
+       FLAC__ASSERT((bb->consumed_bits & 7) == 0);
+
+       bb->read_crc16 = seed;
+#if FLAC__BITS_PER_BLURB == 8
+       /* no need to do anything */
+#elif FLAC__BITS_PER_BLURB == 32
+       bb->crc16_align = bb->consumed_bits;
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+}
+
+FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb)
+{
+       FLAC__ASSERT(bb != 0);
+       FLAC__ASSERT(bb->buffer != 0);
+       FLAC__ASSERT((bb->bits & 7) == 0);
+       FLAC__ASSERT((bb->consumed_bits & 7) == 0);
+
+#if FLAC__BITS_PER_BLURB == 8
+       /* no need to do anything */
+#elif FLAC__BITS_PER_BLURB == 32
+       /*@@@ BUG: even though this probably can't happen with FLAC, need to fix the case where we are called here for the very first blurb and crc16_align is > 0 */
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) {
+               if(bb->consumed_bits == 8) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16);
+               }
+               else if(bb->consumed_bits == 16) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16);
+               }
+               else if(bb->consumed_bits == 24) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16);
+               }
+       }
+       else {
+               if(bb->consumed_bits == 8) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16);
+               }
+               else if(bb->consumed_bits == 16) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16);
+               }
+               else if(bb->consumed_bits == 24) {
+                       const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs];
+                       FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16);
+                       FLAC__CRC16_UPDATE((blurb >> (bb->bits-24)) & 0xff, bb->read_crc16);
+               }
+       }
+       bb->crc16_align = bb->consumed_bits;
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+       return bb->read_crc16;
+}
+
+FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb)
+{
+       FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */
+
+#if FLAC__BITS_PER_BLURB == 8
+       return FLAC__crc16(bb->buffer, bb->blurbs);
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       return FLAC__crc16((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3));
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+}
+
+FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb)
+{
+       FLAC__ASSERT(bb->blurbs == 0);
+       FLAC__ASSERT(bb->buffer[0] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */
+       FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */
+#if FLAC__BITS_PER_BLURB == 8
+       return FLAC__crc8(bb->buffer, bb->blurbs);
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       return FLAC__crc8((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3));
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+}
+
+FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb)
+{
+       return ((bb->bits & 7) == 0);
+}
+
+FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb)
+{
+       return ((bb->consumed_bits & 7) == 0);
+}
+
+unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb)
+{
+       return 8 - (bb->consumed_bits & 7);
+}
+
+unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb)
+{
+       FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0);
+       return (bb->total_bits - bb->total_consumed_bits) >> 3;
+}
+
+void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes)
+{
+       FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0);
+#if FLAC__BITS_PER_BLURB == 8
+       *buffer = bb->buffer + bb->consumed_blurbs;
+       *bytes = bb->blurbs - bb->consumed_blurbs;
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       *buffer = (FLAC__byte*)(bb->buffer + bb->consumed_blurbs) + (bb->consumed_bits >> 3);
+       *bytes = (bb->total_bits - bb->total_consumed_bits) >> 3;
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+}
+
+void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb)
+{
+#if FLAC__BITS_PER_BLURB == 8
+       (void)bb;
+#elif FLAC__BITS_PER_BLURB == 32
+       /* @@@ WATCHOUT: code currently only works for big-endian: */
+       (void)bb;
+#else
+       FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */
+#endif
+}
+
 FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits)
 {
        unsigned n;
@@ -266,12 +543,12 @@ FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits)
                return false;
        bb->total_bits += bits;
        while(bits > 0) {
-               n = min(8 - bb->bits, bits);
-               bb->buffer[bb->bytes] <<= n;
+               n = min(FLAC__BITS_PER_BLURB - bb->bits, bits);
+               bb->buffer[bb->blurbs] <<= n;
                bits -= n;
                bb->bits += n;
-               if(bb->bits == 8) {
-                       bb->bytes++;
+               if(bb->bits == FLAC__BITS_PER_BLURB) {
+                       bb->blurbs++;
                        bb->bits = 0;
                }
        }
@@ -289,7 +566,7 @@ FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FL
        if(bits == 0)
                return true;
        /* inline the size check so we don't incure a function call unnecessarily */
-       if((bb->capacity<<3) < bb->total_bits + bits) {
+       if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits) {
                if(!bitbuffer_ensure_size_(bb, bits))
                        return false;
        }
@@ -297,29 +574,30 @@ FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FL
                val &= (~(0xffffffff << bits)); /* zero-out unused bits */
        bb->total_bits += bits;
        while(bits > 0) {
-               n = 8 - bb->bits;
-               if(n == 8) { /* i.e. bb->bits == 0 */
-                       if(bits < 8) {
-                               bb->buffer[bb->bytes] = (FLAC__byte)val;
+               n = FLAC__BITS_PER_BLURB - bb->bits;
+               if(n == FLAC__BITS_PER_BLURB) { /* i.e. bb->bits == 0 */
+                       if(bits < FLAC__BITS_PER_BLURB) {
+                               bb->buffer[bb->blurbs] = (FLAC__blurb)val;
                                bb->bits = bits;
                                break;
                        }
-                       else if(bits == 8) {
-                               bb->buffer[bb->bytes++] = (FLAC__byte)val;
+                       else if(bits == FLAC__BITS_PER_BLURB) {
+                               bb->buffer[bb->blurbs++] = (FLAC__blurb)val;
                                break;
                        }
                        else {
-                               k = bits - 8;
-                               bb->buffer[bb->bytes++] = (FLAC__byte)(val >> k);
+                               k = bits - FLAC__BITS_PER_BLURB;
+                               bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k);
+                               /* we know k < 32 so no need to protect against the gcc bug mentioned above */
                                val &= (~(0xffffffff << k));
-                               bits -= 8;
+                               bits -= FLAC__BITS_PER_BLURB;
                        }
                }
                else if(bits <= n) {
-                       bb->buffer[bb->bytes] <<= bits;
-                       bb->buffer[bb->bytes] |= val;
+                       bb->buffer[bb->blurbs] <<= bits;
+                       bb->buffer[bb->blurbs] |= val;
                        if(bits == n) {
-                               bb->bytes++;
+                               bb->blurbs++;
                                bb->bits = 0;
                        }
                        else
@@ -328,11 +606,12 @@ FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FL
                }
                else {
                        k = bits - n;
-                       bb->buffer[bb->bytes] <<= n;
-                       bb->buffer[bb->bytes] |= (val>>k);
+                       bb->buffer[bb->blurbs] <<= n;
+                       bb->buffer[bb->blurbs] |= (val >> k);
+                       /* we know n > 0 so k < 32 so no need to protect against the gcc bug mentioned above */
                        val &= (~(0xffffffff << k));
                        bits -= n;
-                       bb->bytes++;
+                       bb->blurbs++;
                        bb->bits = 0;
                }
        }
@@ -380,32 +659,34 @@ FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 va
        bb->total_bits += bits;
        while(bits > 0) {
                if(bb->bits == 0) {
-                       if(bits < 8) {
-                               bb->buffer[bb->bytes] = (FLAC__byte)val;
+                       if(bits < FLAC__BITS_PER_BLURB) {
+                               bb->buffer[bb->blurbs] = (FLAC__blurb)val;
                                bb->bits = bits;
                                break;
                        }
-                       else if(bits == 8) {
-                               bb->buffer[bb->bytes++] = (FLAC__byte)val;
+                       else if(bits == FLAC__BITS_PER_BLURB) {
+                               bb->buffer[bb->blurbs++] = (FLAC__blurb)val;
                                break;
                        }
                        else {
-                               k = bits - 8;
-                               bb->buffer[bb->bytes++] = (FLAC__byte)(val >> k);
+                               k = bits - FLAC__BITS_PER_BLURB;
+                               bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k);
+                               /* we know k < 64 so no need to protect against the gcc bug mentioned above */
                                val &= (~(0xffffffffffffffff << k));
-                               bits -= 8;
+                               bits -= FLAC__BITS_PER_BLURB;
                        }
                }
                else {
-                       n = min(8 - bb->bits, bits);
+                       n = min(FLAC__BITS_PER_BLURB - bb->bits, bits);
                        k = bits - n;
-                       bb->buffer[bb->bytes] <<= n;
-                       bb->buffer[bb->bytes] |= (val>>k);
+                       bb->buffer[bb->blurbs] <<= n;
+                       bb->buffer[bb->blurbs] |= (val >> k);
+                       /* we know n > 0 so k < 64 so no need to protect against the gcc bug mentioned above */
                        val &= (~(0xffffffffffffffff << k));
                        bits -= n;
                        bb->bits += n;
-                       if(bb->bits == 8) {
-                               bb->bytes++;
+                       if(bb->bits == FLAC__BITS_PER_BLURB) {
+                               bb->blurbs++;
                                bb->bits = 0;
                        }
                }
@@ -451,6 +732,7 @@ unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter)
        return 1 + parameter + msbs;
 }
 
+#if 0 /* UNUSED */
 unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter)
 {
        unsigned bits, msbs, uval;
@@ -516,7 +798,9 @@ unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned uval, unsigned parameter)
        }
        return bits;
 }
+#endif /* UNUSED */
 
+#ifdef FLAC__SYMMETRIC_RICE
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter)
 {
        unsigned total_bits, interesting_bits, msbs;
@@ -555,6 +839,7 @@ FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int
        return true;
 }
 
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow)
 {
        unsigned total_bits, interesting_bits, msbs;
@@ -598,6 +883,7 @@ FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *
        }
        return true;
 }
+#endif /* UNUSED */
 
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter)
 {
@@ -633,6 +919,7 @@ FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *b
        }
        return true;
 }
+#endif /* ifdef FLAC__SYMMETRIC_RICE */
 
 FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter)
 {
@@ -674,6 +961,7 @@ FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsig
        return true;
 }
 
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow)
 {
        unsigned total_bits, interesting_bits, msbs, uval;
@@ -719,7 +1007,9 @@ FLAC__bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int va
        }
        return true;
 }
+#endif /* UNUSED */
 
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter)
 {
        unsigned total_bits, msbs, uval;
@@ -845,6 +1135,7 @@ FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned u
        }
        return true;
 }
+#endif /* UNUSED */
 
 FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val)
 {
@@ -950,8 +1241,8 @@ FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 v
 FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb)
 {
        /* 0-pad to byte boundary */
-       if(bb->bits != 0)
-               return FLAC__bitbuffer_write_zeroes(bb, 8 - bb->bits);
+       if(bb->bits & 7u)
+               return FLAC__bitbuffer_write_zeroes(bb, 8 - (bb->bits & 7u));
        else
                return true;
 }
@@ -966,7 +1257,7 @@ FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bo
 
        while(1) {
                if(bb->total_consumed_bits < bb->total_bits) {
-                       *val = (bb->buffer[bb->consumed_bytes] & BYTE_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
+                       *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
                        return true;
                }
                else {
@@ -986,11 +1277,11 @@ FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bo
 
        while(1) {
                if(bb->total_consumed_bits < bb->total_bits) {
-                       *val = (bb->buffer[bb->consumed_bytes] & BYTE_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
+                       *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
                        bb->consumed_bits++;
-                       if(bb->consumed_bits == 8) {
-                               FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
-                               bb->consumed_bytes++;
+                       if(bb->consumed_bits == FLAC__BITS_PER_BLURB) {
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
                                bb->consumed_bits = 0;
                        }
                        bb->total_consumed_bits++;
@@ -1014,11 +1305,11 @@ FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32
        while(1) {
                if(bb->total_consumed_bits < bb->total_bits) {
                        *val <<= 1;
-                       *val |= (bb->buffer[bb->consumed_bytes] & BYTE_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
+                       *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
                        bb->consumed_bits++;
-                       if(bb->consumed_bits == 8) {
-                               FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
-                               bb->consumed_bytes++;
+                       if(bb->consumed_bits == FLAC__BITS_PER_BLURB) {
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
                                bb->consumed_bits = 0;
                        }
                        bb->total_consumed_bits++;
@@ -1042,11 +1333,11 @@ FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64
        while(1) {
                if(bb->total_consumed_bits < bb->total_bits) {
                        *val <<= 1;
-                       *val |= (bb->buffer[bb->consumed_bytes] & BYTE_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
+                       *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0;
                        bb->consumed_bits++;
-                       if(bb->consumed_bits == 8) {
-                               FLAC__CRC16_UPDATE(bb->buffer[bb->consumed_bytes], bb->read_crc16);
-                               bb->consumed_bytes++;
+                       if(bb->consumed_bits == FLAC__BITS_PER_BLURB) {
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
                                bb->consumed_bits = 0;
                        }
                        bb->total_consumed_bits++;
@@ -1085,46 +1376,77 @@ FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLA
        FLAC__ASSERT(bb->buffer != 0);
 
        FLAC__ASSERT(bits <= 32);
-       FLAC__ASSERT((bb->capacity*8) * 2 >= bits);
+       FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits);
+
+       if(bits == 0) {
+               *val = 0;
+               return true;
+       }
 
        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 */
+#if FLAC__BITS_PER_BLURB > 8
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { //@@@ comment on why this is here
+#endif
+               if(bb->consumed_bits) {
+                       i = FLAC__BITS_PER_BLURB - bb->consumed_bits;
+                       if(i <= bits_) {
+                               v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits);
+                               bits_ -= i;
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
+                               bb->consumed_bits = 0;
+                               /* we hold off updating bb->total_consumed_bits until the end */
+                       }
+                       else {
+                               *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_);
+                               bb->consumed_bits += bits_;
+                               bb->total_consumed_bits += bits_;
+                               return true;
+                       }
                }
-               else {
-                       *val = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits)) >> (i-bits_);
-                       bb->consumed_bits += bits_;
-                       bb->total_consumed_bits += bits_;
+#if FLAC__BITS_PER_BLURB == 32
+               /* note that we know bits_ cannot be > 32 because of previous assertions */
+               if(bits_ == FLAC__BITS_PER_BLURB) {
+                       v = bb->buffer[bb->consumed_blurbs];
+                       CRC16_UPDATE_BLURB(bb, v, bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 0 */
+                       bb->total_consumed_bits += bits;
+                       *val = v;
                        return true;
                }
+#else
+               while(bits_ >= FLAC__BITS_PER_BLURB) {
+                       v <<= FLAC__BITS_PER_BLURB;
+                       v |= bb->buffer[bb->consumed_blurbs];
+                       bits_ -= FLAC__BITS_PER_BLURB;
+                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 0 */
+                       /* we hold off updating bb->total_consumed_bits until the end */
+               }
+#endif
+               if(bits_ > 0) {
+                       v <<= bits_;
+                       v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_));
+                       bb->consumed_bits = bits_;
+                       /* we hold off updating bb->total_consumed_bits until the end */
+               }
+               bb->total_consumed_bits += bits;
+               *val = v;
+#if FLAC__BITS_PER_BLURB > 8
        }
-       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;
+       else {
+               *val = 0;
+               for(i = 0; i < bits; i++) {
+                       if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data))
+                               return false;
+               }
+       }
+#endif
        return true;
 }
 #endif
@@ -1172,7 +1494,7 @@ FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val,
        FLAC__ASSERT(bb->buffer != 0);
 
        FLAC__ASSERT(bits <= 32);
-       FLAC__ASSERT((bb->capacity*8) * 2 >= bits);
+       FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits);
 
        if(bits == 0) {
                *val = 0;
@@ -1183,43 +1505,67 @@ FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val,
                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;
+#if FLAC__BITS_PER_BLURB > 8
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { //@@@ comment on why this is here
+#endif
+               if(bb->consumed_bits) {
+                       i = FLAC__BITS_PER_BLURB - bb->consumed_bits;
+                       if(i <= bits_) {
+                               v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits);
+                               bits_ -= i;
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
+                               bb->consumed_bits = 0;
+                               /* we hold off updating bb->total_consumed_bits until the end */
+                       }
+                       else {
+                               /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */
+                               v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits));
+                               v <<= (32-i);
+                               *val = (FLAC__int32)v;
+                               *val >>= (32-bits_);
+                               bb->consumed_bits += bits_;
+                               bb->total_consumed_bits += bits_;
+                               return true;
+                       }
+               }
+#if FLAC__BITS_PER_BLURB == 32
+               /* note that we know bits_ cannot be > 32 because of previous assertions */
+               if(bits_ == FLAC__BITS_PER_BLURB) {
+                       v = bb->buffer[bb->consumed_blurbs];
+                       bits_ = 0;
+                       CRC16_UPDATE_BLURB(bb, v, bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 0 */
                        /* we hold off updating bb->total_consumed_bits until the end */
                }
-               else {
-                       /* bits_ must be < 7 if we get to here */
-                       v = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits));
-                       v <<= (32-i);
-                       *val = (FLAC__int32)v;
-                       *val >>= (32-bits_);
-                       bb->consumed_bits += bits_;
-                       bb->total_consumed_bits += bits_;
-                       return true;
+#else
+               while(bits_ >= FLAC__BITS_PER_BLURB) {
+                       v <<= FLAC__BITS_PER_BLURB;
+                       v |= bb->buffer[bb->consumed_blurbs];
+                       bits_ -= FLAC__BITS_PER_BLURB;
+                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 0 */
+                       /* we hold off updating bb->total_consumed_bits until the end */
                }
+#endif
+               if(bits_ > 0) {
+                       v <<= bits_;
+                       v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_));
+                       bb->consumed_bits = bits_;
+                       /* we hold off updating bb->total_consumed_bits until the end */
+               }
+               bb->total_consumed_bits += bits;
+#if FLAC__BITS_PER_BLURB > 8
        }
-       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 */
+       else {
+               for(i = 0; i < bits; i++) {
+                       if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data))
+                               return false;
+               }
        }
-       bb->total_consumed_bits += bits;
+#endif
 
        /* fix the sign */
        i = 32 - bits;
@@ -1261,46 +1607,64 @@ FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *va
        FLAC__ASSERT(bb->buffer != 0);
 
        FLAC__ASSERT(bits <= 64);
-       FLAC__ASSERT((bb->capacity*8) * 2 >= bits);
+       FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits);
+
+       if(bits == 0) {
+               *val = 0;
+               return true;
+       }
 
        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;
+#if FLAC__BITS_PER_BLURB > 8
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { //@@@ comment on why this is here
+#endif
+               if(bb->consumed_bits) {
+                       i = FLAC__BITS_PER_BLURB - bb->consumed_bits;
+                       if(i <= bits_) {
+                               v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits);
+                               bits_ -= i;
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
+                               bb->consumed_bits = 0;
+                               /* we hold off updating bb->total_consumed_bits until the end */
+                       }
+                       else {
+                               *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_);
+                               bb->consumed_bits += bits_;
+                               bb->total_consumed_bits += bits_;
+                               return true;
+                       }
+               }
+               while(bits_ >= FLAC__BITS_PER_BLURB) {
+                       v <<= FLAC__BITS_PER_BLURB;
+                       v |= bb->buffer[bb->consumed_blurbs];
+                       bits_ -= FLAC__BITS_PER_BLURB;
+                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 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;
+               if(bits_ > 0) {
+                       v <<= bits_;
+                       v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_));
+                       bb->consumed_bits = bits_;
+                       /* we hold off updating bb->total_consumed_bits until the end */
                }
+               bb->total_consumed_bits += bits;
+               *val = v;
+#if FLAC__BITS_PER_BLURB > 8
        }
-       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;
+       else {
+               *val = 0;
+               for(i = 0; i < bits; i++) {
+                       if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data))
+                               return false;
+               }
+       }
+#endif
        return true;
 }
 #endif
@@ -1342,49 +1706,66 @@ FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val,
        FLAC__ASSERT(bb->buffer != 0);
 
        FLAC__ASSERT(bits <= 64);
-       FLAC__ASSERT((bb->capacity*8) * 2 >= bits);
+       FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits);
+
+       if(bits == 0) {
+               *val = 0;
+               return true;
+       }
 
        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;
+#if FLAC__BITS_PER_BLURB > 8
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { //@@@ comment on why this is here
+#endif
+               if(bb->consumed_bits) {
+                       i = FLAC__BITS_PER_BLURB - bb->consumed_bits;
+                       if(i <= bits_) {
+                               v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits);
+                               bits_ -= i;
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
+                               bb->consumed_bits = 0;
+                               /* we hold off updating bb->total_consumed_bits until the end */
+                       }
+                       else {
+                               /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */
+                               v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits));
+                               v <<= (64-i);
+                               *val = (FLAC__int64)v;
+                               *val >>= (64-bits_);
+                               bb->consumed_bits += bits_;
+                               bb->total_consumed_bits += bits_;
+                               return true;
+                       }
+               }
+               while(bits_ >= FLAC__BITS_PER_BLURB) {
+                       v <<= FLAC__BITS_PER_BLURB;
+                       v |= bb->buffer[bb->consumed_blurbs];
+                       bits_ -= FLAC__BITS_PER_BLURB;
+                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                       bb->consumed_blurbs++;
+                       /* bb->consumed_bits is already 0 */
                        /* we hold off updating bb->total_consumed_bits until the end */
                }
-               else {
-                       /* bits_ must be < 7 if we get to here */
-                       v = (bb->buffer[bb->consumed_bytes] & (0xff >> bb->consumed_bits));
-                       v <<= (64-i);
-                       *val = (FLAC__int64)v;
-                       *val >>= (64-bits_);
-                       bb->consumed_bits += bits_;
-                       bb->total_consumed_bits += bits_;
-                       return true;
+               if(bits_ > 0) {
+                       v <<= bits_;
+                       v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_));
+                       bb->consumed_bits = bits_;
+                       /* we hold off updating bb->total_consumed_bits until the end */
                }
+               bb->total_consumed_bits += bits;
+#if FLAC__BITS_PER_BLURB > 8
        }
-       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 */
+       else {
+               for(i = 0; i < bits; i++) {
+                       if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data))
+                               return false;
+               }
        }
-       bb->total_consumed_bits += bits;
+#endif
 
        /* fix the sign */
        i = 64 - bits;
@@ -1422,70 +1803,88 @@ FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb,
 #else
 {
        unsigned i, val_ = 0;
-       unsigned total_bytes_ = (bb->total_bits + 7) / 8;
-       FLAC__byte b;
+       unsigned total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB;
+       FLAC__blurb b;
 
        FLAC__ASSERT(bb != 0);
        FLAC__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++;
+#if FLAC__BITS_PER_BLURB > 8
+       if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { //@@@ comment on why this is here
+#endif
+               if(bb->consumed_bits) {
+                       b = bb->buffer[bb->consumed_blurbs] << bb->consumed_bits;
+                       if(b) {
+                               for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++)
+                                       b <<= 1;
+                               *val = i;
+                               i++;
+                               bb->consumed_bits += i;
+                               bb->total_consumed_bits += i;
+                               if(bb->consumed_bits == FLAC__BITS_PER_BLURB) {
+                                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                                       bb->consumed_blurbs++;
+                                       bb->consumed_bits = 0;
+                               }
+                               return true;
+                       }
+                       else {
+                               val_ = FLAC__BITS_PER_BLURB - bb->consumed_bits;
+                               CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                               bb->consumed_blurbs++;
                                bb->consumed_bits = 0;
+                               bb->total_consumed_bits += val_;
                        }
-                       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;
-                       bb->total_consumed_bits += val_;
+               while(1) {
+                       if(bb->consumed_blurbs >= total_blurbs_) {
+                               if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
+                                       return false;
+                               total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB;
+                       }
+                       b = bb->buffer[bb->consumed_blurbs];
+                       if(b) {
+                               for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++)
+                                       b <<= 1;
+                               val_ += i;
+                               i++;
+                               bb->consumed_bits = i;
+                               *val = val_;
+                               if(i == FLAC__BITS_PER_BLURB) {
+                                       CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16);
+                                       bb->consumed_blurbs++;
+                                       bb->consumed_bits = 0;
+                               }
+                               bb->total_consumed_bits += i;
+                               return true;
+                       }
+                       else {
+                               val_ += FLAC__BITS_PER_BLURB;
+                               CRC16_UPDATE_BLURB(bb, 0, bb->read_crc16);
+                               bb->consumed_blurbs++;
+                               /* bb->consumed_bits is already 0 */
+                               bb->total_consumed_bits += FLAC__BITS_PER_BLURB;
+                       }
                }
+#if FLAC__BITS_PER_BLURB > 8
        }
-       while(1) {
-               if(bb->consumed_bytes >= total_bytes_) {
-                       if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
+       else {
+               while(1) {
+                       if(!FLAC__bitbuffer_read_bit(bb, &i, 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 += i;
-                       return true;
-               }
-               else {
-                       val_ += 8;
-                       FLAC__CRC16_UPDATE(0, bb->read_crc16);
-                       bb->consumed_bytes++;
-                       /* bb->consumed_bits is already 0 */
-                       /* we hold off updating bb->total_consumed_bits until the end */
-                       bb->total_consumed_bits += 8;
+                       if(i)
+                               break;
+                       else
+                               val_++;
                }
+               *val = val_;
+               return true;
        }
+#endif
 }
 #endif
 
+#ifdef FLAC__SYMMETRIC_RICE
 FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data)
 {
        FLAC__uint32 sign = 0, lsbs = 0, msbs = 0;
@@ -1513,6 +1912,7 @@ FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *
 
        return true;
 }
+#endif /* ifdef FLAC__SYMMETRIC_RICE */
 
 FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data)
 {
@@ -1541,6 +1941,7 @@ FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsig
        return true;
 }
 
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data)
 {
        FLAC__uint32 lsbs = 0, msbs = 0;
@@ -1622,6 +2023,7 @@ FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *v
 
        return true;
 }
+#endif /* UNUSED */
 
 /* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */
 FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen)
@@ -1744,20 +2146,20 @@ void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out)
                fprintf(out, "bitbuffer is NULL\n");
        }
        else {
-               fprintf(out, "bitbuffer: capacity=%u bytes=%u bits=%u total_bits=%u consumed: bytes=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->bytes, bb->bits, bb->total_bits, bb->consumed_bytes, bb->consumed_bits, bb->total_consumed_bits);
-               for(i = 0; i < bb->bytes; i++) {
+               fprintf(out, "bitbuffer: capacity=%u blurbs=%u bits=%u total_bits=%u consumed: blurbs=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->blurbs, bb->bits, bb->total_bits, bb->consumed_blurbs, bb->consumed_bits, bb->total_consumed_bits);
+               for(i = 0; i < bb->blurbs; i++) {
                        fprintf(out, "%08X: ", i);
-                       for(j = 0; j < 8; j++)
-                               if(i*8+j < bb->total_consumed_bits)
+                       for(j = 0; j < FLAC__BITS_PER_BLURB; j++)
+                               if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits)
                                        fprintf(out, ".");
                                else
-                                       fprintf(out, "%01u", bb->buffer[i] & (1 << (8-j-1)) ? 1:0);
+                                       fprintf(out, "%01u", bb->buffer[i] & (1 << (FLAC__BITS_PER_BLURB-j-1)) ? 1:0);
                        fprintf(out, "\n");
                }
                if(bb->bits > 0) {
                        fprintf(out, "%08X: ", i);
                        for(j = 0; j < bb->bits; j++)
-                               if(i*8+j < bb->total_consumed_bits)
+                               if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits)
                                        fprintf(out, ".");
                                else
                                        fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0);
index d8764f1..43ead8e 100644 (file)
 #include <stdio.h> /* for FILE */
 #include "FLAC/ordinals.h"
 
-typedef struct {
-       FLAC__byte *buffer;
-       unsigned capacity; /* in bytes */
-       unsigned bytes, bits;
-       unsigned total_bits; /* must always == 8*bytes+bits */
-       unsigned consumed_bytes, consumed_bits;
-       unsigned total_consumed_bits; /* must always == 8*consumed_bytes+consumed_bits */
-       FLAC__uint16 read_crc16;
-} FLAC__BitBuffer;
+/* @@@ This should be configurable. Valid values are currently 8 and 32. */
+/* @@@ WATCHOUT!  do not use 32 with a little endian system yet. */
+#define FLAC__BITS_PER_BLURB 8
 
-void FLAC__bitbuffer_init(FLAC__BitBuffer *bb);
+#if FLAC__BITS_PER_BLURB == 8
+typedef FLAC__byte FLAC__blurb;
+#elif FLAC__BITS_PER_BLURB == 32
+typedef FLAC__uint32 FLAC__blurb;
+#else
+/* ERROR, only sizes of 8 and 32 are supported */
+#endif
+
+/*
+ * opaque structure definition
+ */
+struct FLAC__BitBuffer;
+typedef struct FLAC__BitBuffer FLAC__BitBuffer;
+
+/*
+ * construction, deletion, initialization, cloning functions
+ */
+FLAC__BitBuffer *FLAC__bitbuffer_new();
+void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb);
+FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb);
 FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes);
-void FLAC__bitbuffer_init_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed);
 FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src);
 void FLAC__bitbuffer_free(FLAC__BitBuffer *bb); /* does not 'free(buffer)' */
 FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb);
 FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src);
+
+/*
+ * CRC functions
+ */
+void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed);
+FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb);
+FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb);
+FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb);
+
+/*
+ * info functions
+ */
+FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb);
+FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb);
+unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb);
+unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb); /* do not call unless byte-aligned */
+
+/*
+ * direct buffer access
+ */
+void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes);
+void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb);
+
+/*
+ * write functions
+ */
 FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits);
 FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits);
 FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits);
@@ -47,20 +85,34 @@ FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 va
 FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits);
 FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val);
 unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter);
+#if 0 /* UNUSED */
 unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter);
 unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned val, unsigned parameter);
+#endif
+#ifdef FLAC__SYMMETRIC_RICE
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter);
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow);
+#endif
 FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter);
+#endif
 FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter);
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow);
+#endif
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter);
 FLAC__bool FLAC__bitbuffer_write_golomb_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow);
 FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned val, unsigned parameter);
 FLAC__bool FLAC__bitbuffer_write_golomb_unsigned_guarded(FLAC__BitBuffer *bb, unsigned val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow);
+#endif
 FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val);
 FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val);
 FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb);
+
+/*
+ * read functions
+ */
 FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
 FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
 FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
@@ -70,10 +122,14 @@ FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val,
 FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
 FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
 FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
+#ifdef FLAC__SYMMETRIC_RICE
 FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
+#endif
 FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
+#if 0 /* UNUSED */
 FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
 FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data);
+#endif
 FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen);
 FLAC__bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen);
 void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out);
index 2f5da20..abe8613 100644 (file)
@@ -72,7 +72,7 @@ typedef struct FLAC__StreamDecoderPrivate {
        void (*local_lpc_restore_signal)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
        void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
        void *client_data;
-       FLAC__BitBuffer input;
+       FLAC__BitBuffer *input;
        FLAC__int32 *output[FLAC__MAX_CHANNELS];
        FLAC__int32 *residual[FLAC__MAX_CHANNELS];
        unsigned output_capacity, output_channels;
@@ -151,6 +151,13 @@ FLAC__StreamDecoder *FLAC__stream_decoder_new()
                free(decoder);
                return 0;
        }
+       decoder->private_->input = FLAC__bitbuffer_new();
+       if(decoder->private_->input == 0) {
+               free(decoder->private_);
+               free(decoder->protected_);
+               free(decoder);
+               return 0;
+       }
 
        decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
 
@@ -168,7 +175,9 @@ void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
        FLAC__ASSERT(decoder != 0);
        FLAC__ASSERT(decoder->protected_ != 0);
        FLAC__ASSERT(decoder->private_ != 0);
+       FLAC__ASSERT(decoder->private_->input != 0);
 
+       FLAC__bitbuffer_delete(decoder->private_->input);
        free(decoder->private_);
        free(decoder->protected_);
        free(decoder);
@@ -194,7 +203,8 @@ FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder)
        if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
                return decoder->protected_->state = FLAC__STREAM_DECODER_INVALID_CALLBACK;
 
-       FLAC__bitbuffer_init(&decoder->private_->input);
+       if(!FLAC__bitbuffer_init(decoder->private_->input))
+               return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
 
        for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
                decoder->private_->output[i] = 0;
@@ -248,7 +258,7 @@ void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
                free(decoder->private_->seek_table.data.seek_table.points);
                decoder->private_->seek_table.data.seek_table.points = 0;
        }
-       FLAC__bitbuffer_free(&decoder->private_->input);
+       FLAC__bitbuffer_free(decoder->private_->input);
        for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
                /* WATCHOUT: FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the output arrays have a buffer of up to 3 zeroes in front (at negative indices) for alignment purposes; we use 4 to keep the data well-aligned. */
                if(decoder->private_->output[i] != 0) {
@@ -339,7 +349,7 @@ FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(decoder != 0);
 
-       if(!FLAC__bitbuffer_clear(&decoder->private_->input)) {
+       if(!FLAC__bitbuffer_clear(decoder->private_->input)) {
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -507,7 +517,7 @@ FLAC__bool FLAC__stream_decoder_process_remaining_frames(FLAC__StreamDecoder *de
 unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(decoder != 0);
-       return decoder->private_->input.bytes - decoder->private_->input.consumed_bytes;
+       return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input);
 }
 
 /***********************************************************************
@@ -567,7 +577,7 @@ FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
        unsigned i, id;
        FLAC__bool first = true;
 
-       FLAC__ASSERT(decoder->private_->input.consumed_bits == 0); /* make sure we're byte aligned */
+       FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
 
        for(i = id = 0; i < 4; ) {
                if(decoder->private_->cached) {
@@ -575,7 +585,7 @@ FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
                        decoder->private_->cached = false;
                }
                else {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                }
                if(x == FLAC__STREAM_SYNC_STRING[i]) {
@@ -595,7 +605,7 @@ FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
                }
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        decoder->private_->header_warmup[0] = (FLAC__byte)x;
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
 
                        /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
@@ -626,13 +636,13 @@ FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
        FLAC__uint32 i, x, last_block, type, length;
        FLAC__uint64 xx;
 
-       FLAC__ASSERT(decoder->private_->input.consumed_bits == 0); /* make sure we're byte aligned */
+       FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
 
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &last_block, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &last_block, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        if(type == FLAC__METADATA_TYPE_STREAMINFO) {
                unsigned used_bits = 0;
@@ -640,47 +650,47 @@ FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
                decoder->private_->stream_info.is_last = last_block;
                decoder->private_->stream_info.length = length;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.min_blocksize = x;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.max_blocksize = x;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.min_framesize = x;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.max_framesize = x;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.sample_rate = x;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.channels = x+1;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1;
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
 
-               if(!FLAC__bitbuffer_read_raw_uint64(&decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                used_bits += FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
 
                for(i = 0; i < 16; i++) {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        decoder->private_->stream_info.data.stream_info.md5sum[i] = (FLAC__byte)x;
                }
@@ -690,7 +700,7 @@ FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
                FLAC__ASSERT(used_bits % 8 == 0);
                length -= (used_bits / 8);
                for(i = 0; i < length; i++) {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                }
 
@@ -711,15 +721,15 @@ FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
                        return false;
                }
                for(i = real_points = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) {
-                       if(!FLAC__bitbuffer_read_raw_uint64(&decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        decoder->private_->seek_table.data.seek_table.points[real_points].sample_number = xx;
 
-                       if(!FLAC__bitbuffer_read_raw_uint64(&decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        decoder->private_->seek_table.data.seek_table.points[real_points].stream_offset = xx;
 
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        decoder->private_->seek_table.data.seek_table.points[real_points].frame_samples = x;
 
@@ -734,7 +744,7 @@ FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
        else {
                /* skip other metadata blocks */
                for(i = 0; i < length; i++) {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                }
        }
@@ -751,19 +761,19 @@ FLAC__bool stream_decoder_skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
        unsigned i, skip;
 
        /* skip the version and flags bytes */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 24, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        /* get the size (in bytes) to skip */
        skip = 0;
        for(i = 0; i < 4; i++) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                skip <<= 7;
                skip |= (x & 0x7f);
        }
        /* skip the rest of the tag */
        for(i = 0; i < skip; i++) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
        }
        return true;
@@ -784,8 +794,8 @@ FLAC__bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder)
        }
 
        /* make sure we're byte aligned */
-       if(decoder->private_->input.consumed_bits != 0) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8-decoder->private_->input.consumed_bits, read_callback_, decoder))
+       if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) {
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
        }
 
@@ -795,12 +805,12 @@ FLAC__bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder)
                        decoder->private_->cached = false;
                }
                else {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                }
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        decoder->private_->header_warmup[0] = (FLAC__byte)x;
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
 
                        /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
@@ -838,7 +848,7 @@ FLAC__bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *
        frame_crc = 0;
        FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc);
        FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc);
-       FLAC__bitbuffer_init_read_crc16(&decoder->private_->input, frame_crc);
+       FLAC__bitbuffer_reset_read_crc16(decoder->private_->input, frame_crc);
 
        if(!stream_decoder_read_frame_header_(decoder))
                return false;
@@ -889,8 +899,8 @@ FLAC__bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *
        /*
         * Read the frame CRC-16 from the footer and check
         */
-       frame_crc = decoder->private_->input.read_crc16;
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder))
+       frame_crc = FLAC__bitbuffer_get_read_crc16(decoder->private_->input);
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        if(frame_crc == (FLAC__uint16)x) {
                /* Undo any special channel coding */
@@ -967,7 +977,7 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
        const FLAC__bool is_known_variable_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize);
        const FLAC__bool is_known_fixed_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize);
 
-       FLAC__ASSERT(decoder->private_->input.consumed_bits == 0); /* make sure we're byte aligned */
+       FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
 
        /* init the raw header with the saved bits from synchronization */
        raw_header[0] = decoder->private_->header_warmup[0];
@@ -991,7 +1001,7 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
         * read in the raw header as bytes so we can CRC it, and parse it on the way
         */
        for(i = 0; i < 2; i++) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */
@@ -1149,7 +1159,7 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
        }
 
        if(blocksize_hint && is_known_variable_blocksize_stream) {
-               if(!FLAC__bitbuffer_read_utf8_uint64(&decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len))
+               if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len))
                        return false; /* the read_callback_ sets the state for us */
                if(xx == 0xffffffffffffffff) { /* i.e. non-UTF8 code... */
                        decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
@@ -1162,7 +1172,7 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
                decoder->private_->frame.header.number.sample_number = xx;
        }
        else {
-               if(!FLAC__bitbuffer_read_utf8_uint32(&decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len))
+               if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len))
                        return false; /* the read_callback_ sets the state for us */
                if(x == 0xffffffff) { /* i.e. non-UTF8 code... */
                        decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
@@ -1182,12 +1192,12 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
        }
 
        if(blocksize_hint) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                raw_header[raw_header_len++] = (FLAC__byte)x;
                if(blocksize_hint == 7) {
                        FLAC__uint32 _x;
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &_x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        raw_header[raw_header_len++] = (FLAC__byte)_x;
                        x = (x << 8) | _x;
@@ -1196,12 +1206,12 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
        }
 
        if(sample_rate_hint) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                raw_header[raw_header_len++] = (FLAC__byte)x;
                if(sample_rate_hint != 12) {
                        FLAC__uint32 _x;
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &_x, 8, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        raw_header[raw_header_len++] = (FLAC__byte)_x;
                        x = (x << 8) | _x;
@@ -1215,7 +1225,7 @@ FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
        }
 
        /* read the CRC-8 byte */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        crc8 = (FLAC__byte)x;
 
@@ -1238,7 +1248,7 @@ FLAC__bool stream_decoder_read_subframe_(FLAC__StreamDecoder *decoder, unsigned
        FLAC__uint32 x;
        FLAC__bool wasted_bits;
 
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */
                return false; /* the read_callback_ sets the state for us */
 
        wasted_bits = (x & 1);
@@ -1246,7 +1256,7 @@ FLAC__bool stream_decoder_read_subframe_(FLAC__StreamDecoder *decoder, unsigned
 
        if(wasted_bits) {
                unsigned u;
-               if(!FLAC__bitbuffer_read_unary_unsigned(&decoder->private_->input, &u, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_unary_unsigned(decoder->private_->input, &u, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                decoder->private_->frame.subframes[channel].wasted_bits = u+1;
                bps -= decoder->private_->frame.subframes[channel].wasted_bits;
@@ -1306,7 +1316,7 @@ FLAC__bool stream_decoder_read_subframe_constant_(FLAC__StreamDecoder *decoder,
 
        decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT;
 
-       if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &x, bps, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
 
        subframe->value = x;
@@ -1332,18 +1342,18 @@ FLAC__bool stream_decoder_read_subframe_fixed_(FLAC__StreamDecoder *decoder, uns
 
        /* read warm-up samples */
        for(u = 0; u < order; u++) {
-               if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &i32, bps, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                subframe->warmup[u] = i32;
        }
 
        /* read entropy coding method info */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        subframe->entropy_coding_method.type = u32;
        switch(subframe->entropy_coding_method.type) {
                case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        subframe->entropy_coding_method.data.partitioned_rice.order = u32;
                        break;
@@ -1383,13 +1393,13 @@ FLAC__bool stream_decoder_read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsig
 
        /* read warm-up samples */
        for(u = 0; u < order; u++) {
-               if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &i32, bps, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                subframe->warmup[u] = i32;
        }
 
        /* read qlp coeff precision */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) {
                decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private_->client_data);
@@ -1399,24 +1409,24 @@ FLAC__bool stream_decoder_read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsig
        subframe->qlp_coeff_precision = u32+1;
 
        /* read qlp shift */
-       if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        subframe->quantization_level = i32;
 
        /* read quantized lp coefficiencts */
        for(u = 0; u < order; u++) {
-               if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                subframe->qlp_coeff[u] = i32;
        }
 
        /* read entropy coding method info */
-       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
+       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
                return false; /* the read_callback_ sets the state for us */
        subframe->entropy_coding_method.type = u32;
        switch(subframe->entropy_coding_method.type) {
                case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        subframe->entropy_coding_method.data.partitioned_rice.order = u32;
                        break;
@@ -1456,7 +1466,7 @@ FLAC__bool stream_decoder_read_subframe_verbatim_(FLAC__StreamDecoder *decoder,
        subframe->data = residual;
 
        for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
-               if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &x, bps, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                residual[i] = x;
        }
@@ -1478,27 +1488,27 @@ FLAC__bool stream_decoder_read_residual_partitioned_rice_(FLAC__StreamDecoder *d
 
        sample = 0;
        for(partition = 0; partition < partitions; partition++) {
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                partitioned_rice->parameters[partition] = rice_parameter;
                if(rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
                        for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) {
 #ifdef FLAC__SYMMETRIC_RICE
-                               if(!FLAC__bitbuffer_read_symmetric_rice_signed(&decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
+                               if(!FLAC__bitbuffer_read_symmetric_rice_signed(decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
                                        return false; /* the read_callback_ sets the state for us */
 #else
-                               if(!FLAC__bitbuffer_read_rice_signed(&decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
+                               if(!FLAC__bitbuffer_read_rice_signed(decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
                                        return false; /* the read_callback_ sets the state for us */
 #endif
                                residual[sample] = i;
                        }
                }
                else {
-                       if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder))
+                       if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder))
                                return false; /* the read_callback_ sets the state for us */
                        partitioned_rice->raw_bits[partition] = rice_parameter;
                        for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) {
-                               if(!FLAC__bitbuffer_read_raw_int32(&decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
+                               if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
                                        return false; /* the read_callback_ sets the state for us */
                                residual[sample] = i;
                        }
@@ -1510,9 +1520,9 @@ FLAC__bool stream_decoder_read_residual_partitioned_rice_(FLAC__StreamDecoder *d
 
 FLAC__bool stream_decoder_read_zero_padding_(FLAC__StreamDecoder *decoder)
 {
-       if(decoder->private_->input.consumed_bits != 0) {
+       if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) {
                FLAC__uint32 zero = 0;
-               if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private_->input, &zero, 8-decoder->private_->input.consumed_bits, read_callback_, decoder))
+               if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder))
                        return false; /* the read_callback_ sets the state for us */
                if(zero != 0) {
                        decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private_->client_data);
@@ -1526,6 +1536,7 @@ FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_dat
 {
        FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data;
        FLAC__StreamDecoderReadStatus status;
+
        status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data);
        if(status == FLAC__STREAM_DECODER_READ_END_OF_STREAM)
                decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
index 200f67d..c0012fd 100644 (file)
@@ -97,7 +97,7 @@ typedef struct FLAC__StreamEncoderPrivate {
        FLAC__uint32 *abs_residual;                       /* workspace where abs(candidate residual) is stored */
        FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
        unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
-       FLAC__BitBuffer frame;                            /* the current frame being worked on */
+       FLAC__BitBuffer *frame;                           /* the current frame being worked on */
        double loose_mid_side_stereo_frames_exact;        /* exact number of frames the encoder will use before trying both independent and mid/side frames again */
        unsigned loose_mid_side_stereo_frames;            /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
        unsigned loose_mid_side_stereo_frame_count;       /* number of frames using the current channel assignment */
@@ -195,6 +195,13 @@ FLAC__StreamEncoder *FLAC__stream_encoder_new()
                free(encoder);
                return 0;
        }
+       encoder->private_->frame = FLAC__bitbuffer_new();
+       if(encoder->private_->frame == 0) {
+               free(encoder->private_);
+               free(encoder->protected_);
+               free(encoder);
+               return 0;
+       }
 
        encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
 
@@ -230,7 +237,9 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
        FLAC__ASSERT(encoder != 0);
        FLAC__ASSERT(encoder->protected_ != 0);
        FLAC__ASSERT(encoder->private_ != 0);
+       FLAC__ASSERT(encoder->private_->frame != 0);
 
+       FLAC__bitbuffer_delete(encoder->private_->frame);
        free(encoder->private_);
        free(encoder->protected_);
        free(encoder);
@@ -421,15 +430,14 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
                /* the above function sets the state for us in case of an error */
                return encoder->protected_->state;
        }
-       FLAC__bitbuffer_init(&encoder->private_->frame);
+
+       if(!FLAC__bitbuffer_init(encoder->private_->frame))
+               return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
 
        /*
         * write the stream header
         */
-
-       if(!FLAC__bitbuffer_clear(&encoder->private_->frame))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
-       if(!FLAC__bitbuffer_write_raw_uint32(&encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
+       if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
                return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
 
        encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
@@ -445,7 +453,7 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
        memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
        MD5Init(&encoder->private_->md5context);
-       if(!FLAC__add_metadata_block(&encoder->private_->metadata, &encoder->private_->frame))
+       if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
                return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
 
        if(0 != encoder->protected_->seek_table) {
@@ -455,7 +463,7 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
                seek_table_block.is_last = (encoder->protected_->padding == 0 && encoder->protected_->last_metadata_is_last);
                seek_table_block.length = encoder->protected_->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LEN;
                seek_table_block.data.seek_table = *encoder->protected_->seek_table;
-               if(!FLAC__add_metadata_block(&seek_table_block, &encoder->private_->frame))
+               if(!FLAC__add_metadata_block(&seek_table_block, encoder->private_->frame))
                        return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
        }
 
@@ -464,14 +472,22 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
                padding_block.type = FLAC__METADATA_TYPE_PADDING;
                padding_block.is_last = encoder->protected_->last_metadata_is_last;
                padding_block.length = encoder->protected_->padding;
-               if(!FLAC__add_metadata_block(&padding_block, &encoder->private_->frame))
+               if(!FLAC__add_metadata_block(&padding_block, encoder->private_->frame))
                        return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
        }
 
-       FLAC__ASSERT(encoder->private_->frame.bits == 0); /* assert that we're byte-aligned before writing */
-       FLAC__ASSERT(encoder->private_->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
-       if(encoder->private_->write_callback(encoder, encoder->private_->frame.buffer, encoder->private_->frame.bytes, 0, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_OK)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
+       FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
+       {
+               FLAC__byte *buffer;
+               unsigned bytes;
+
+               FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
+
+               if(encoder->private_->write_callback(encoder, buffer, bytes, 0, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_OK)
+                       return encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
+
+               FLAC__bitbuffer_release_buffer(encoder->private_->frame);
+       }
 
        /* now that the metadata block is written, we can init this to an absurdly-high value... */
        encoder->private_->metadata.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
@@ -542,7 +558,7 @@ void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
                free(encoder->private_->raw_bits_per_partition_unaligned);
                encoder->private_->raw_bits_per_partition_unaligned = 0;
        }
-       FLAC__bitbuffer_free(&encoder->private_->frame);
+       FLAC__bitbuffer_free(encoder->private_->frame);
 
        encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
 }
@@ -973,6 +989,9 @@ FLAC__bool stream_encoder_resize_buffers_(FLAC__StreamEncoder *encoder, unsigned
 
 FLAC__bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
 {
+       const FLAC__byte *buffer;
+       unsigned bytes;
+
        FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
 
        /*
@@ -995,7 +1014,7 @@ FLAC__bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, FLAC__boo
        /*
         * Zero-pad the frame to a byte_boundary
         */
-       if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(&encoder->private_->frame)) {
+       if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(encoder->private_->frame)) {
                encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -1003,17 +1022,18 @@ FLAC__bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, FLAC__boo
        /*
         * CRC-16 the whole thing
         */
-       FLAC__ASSERT(encoder->private_->frame.bits == 0); /* assert that we're byte-aligned */
-       FLAC__ASSERT(encoder->private_->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
-       FLAC__bitbuffer_write_raw_uint32(&encoder->private_->frame, FLAC__crc16(encoder->private_->frame.buffer, encoder->private_->frame.bytes), FLAC__FRAME_FOOTER_CRC_LEN);
+       FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(encoder->private_->frame));
+       FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__bitbuffer_get_write_crc16(encoder->private_->frame), FLAC__FRAME_FOOTER_CRC_LEN);
 
        /*
         * Write it
         */
-       if(encoder->private_->write_callback(encoder, encoder->private_->frame.buffer, encoder->private_->frame.bytes, encoder->protected_->blocksize, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_OK) {
+       FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes);
+       if(encoder->private_->write_callback(encoder, buffer, bytes, encoder->protected_->blocksize, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_OK) {
                encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
                return false;
        }
+       FLAC__bitbuffer_release_buffer(encoder->private_->frame);
 
        /*
         * Get ready for the next frame
@@ -1021,8 +1041,8 @@ FLAC__bool stream_encoder_process_frame_(FLAC__StreamEncoder *encoder, FLAC__boo
        encoder->private_->current_sample_number = 0;
        encoder->private_->current_frame_number++;
        encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
-       encoder->private_->metadata.data.stream_info.min_framesize = min(encoder->private_->frame.bytes, encoder->private_->metadata.data.stream_info.min_framesize);
-       encoder->private_->metadata.data.stream_info.max_framesize = max(encoder->private_->frame.bytes, encoder->private_->metadata.data.stream_info.max_framesize);
+       encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
+       encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
 
        return true;
 }
@@ -1054,7 +1074,7 @@ FLAC__bool stream_encoder_process_subframes_(FLAC__StreamEncoder *encoder, FLAC_
        /*
         * Setup the frame
         */
-       if(!FLAC__bitbuffer_clear(&encoder->private_->frame)) {
+       if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
                encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -1171,7 +1191,7 @@ FLAC__bool stream_encoder_process_subframes_(FLAC__StreamEncoder *encoder, FLAC_
 
                frame_header.channel_assignment = channel_assignment;
 
-               if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, &encoder->private_->frame)) {
+               if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
                        encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                        return false;
                }
@@ -1219,19 +1239,19 @@ FLAC__bool stream_encoder_process_subframes_(FLAC__StreamEncoder *encoder, FLAC_
                }
 
                /* note that encoder_add_subframe_ sets the state for us in case of an error */
-               if(!stream_encoder_add_subframe_(encoder, &frame_header, left_bps , left_subframe , &encoder->private_->frame))
+               if(!stream_encoder_add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
                        return false;
-               if(!stream_encoder_add_subframe_(encoder, &frame_header, right_bps, right_subframe, &encoder->private_->frame))
+               if(!stream_encoder_add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
                        return false;
        }
        else {
-               if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, &encoder->private_->frame)) {
+               if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, is_last_frame, encoder->private_->frame)) {
                        encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                        return false;
                }
 
                for(channel = 0; channel < encoder->protected_->channels; channel++) {
-                       if(!stream_encoder_add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], &encoder->private_->frame)) {
+                       if(!stream_encoder_add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame)) {
                                /* the above function sets the state for us in case of an error */
                                return false;
                        }
index 243ff1f..8e03e82 100644 (file)
@@ -114,12 +114,9 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetaData *metadata, FLAC__
 
 FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__bool streamable_subset, FLAC__bool is_last_block, FLAC__BitBuffer *bb)
 {
-       unsigned u, crc8_start, blocksize_hint, sample_rate_hint;
-       FLAC__byte crc8;
+       unsigned u, blocksize_hint, sample_rate_hint;
 
-       FLAC__ASSERT(bb->bits == 0); /* assert that we're byte-aligned before writing */
-
-       crc8_start = bb->bytes;
+       FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb));
 
        if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__FRAME_HEADER_SYNC, FLAC__FRAME_HEADER_SYNC_LEN))
                return false;
@@ -246,10 +243,7 @@ FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__bool st
        }
 
        /* write the CRC */
-       FLAC__ASSERT(bb->buffer[crc8_start] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */
-       FLAC__ASSERT(bb->bits == 0); /* assert that we're byte-aligned */
-       crc8 = FLAC__crc8(bb->buffer+crc8_start, bb->bytes-crc8_start);
-       if(!FLAC__bitbuffer_write_raw_uint32(bb, crc8, FLAC__FRAME_HEADER_CRC_LEN))
+       if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__bitbuffer_get_write_crc8(bb), FLAC__FRAME_HEADER_CRC_LEN))
                return false;
 
        return true;