Esempio n. 1
0
File: float.c Progetto: AGenews/GUI
		/* lg(2048/2047) = */ 0x0002e2d7,
		/* lg(4096/4095) = */ 0x00017160,
		/* lg(8192/8191) = */ 0x0000b8ad,
		/* lg(16384/16383) = */ 0x00005c56,
		/* lg(32768/32767) = */ 0x00002e2b
	}
};

#if 0
static const FLAC__uint64 log2_lookup_wide[] = {
	{
		/*
		 * 32 fraction bits
		 */
		/* undefined */ 0x00000000,
		/* lg(2/1) = */ FLAC__U64L(0x100000000),
		/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6),
		/* lg(8/7) = */ FLAC__U64L(0x31513015),
		/* lg(16/15) = */ FLAC__U64L(0x17d60497),
		/* lg(32/31) = */ FLAC__U64L(0x0bb9ca65),
		/* lg(64/63) = */ FLAC__U64L(0x05d0fba2),
		/* lg(128/127) = */ FLAC__U64L(0x02e58f74),
		/* lg(256/255) = */ FLAC__U64L(0x01720d9c),
		/* lg(512/511) = */ FLAC__U64L(0x00b8d875),
		/* lg(1024/1023) = */ FLAC__U64L(0x005c60aa),
		/* lg(2048/2047) = */ FLAC__U64L(0x002e2d72),
		/* lg(4096/4095) = */ FLAC__U64L(0x00171600),
		/* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2),
		/* lg(16384/16383) = */ FLAC__U64L(0x0005c55d),
		/* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac)
	},
FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
{
	FLAC__uint64 first_frame_offset, lower_bound, upper_bound;
	FLAC__int64 pos = -1, last_pos = -1;
	int i, lower_seek_point = -1, upper_seek_point = -1;
	unsigned approx_bytes_per_frame;
	FLAC__uint64 last_frame_sample = FLAC__U64L(0xffffffffffffffff);
	FLAC__bool needs_seek;
	const FLAC__uint64 total_samples = decoder->private_->stream_info.total_samples;
	const unsigned min_blocksize = decoder->private_->stream_info.min_blocksize;
	const unsigned max_blocksize = decoder->private_->stream_info.max_blocksize;
	const unsigned max_framesize = decoder->private_->stream_info.max_framesize;
	const unsigned channels = FLAC__seekable_stream_decoder_get_channels(decoder);
	const unsigned bps = FLAC__seekable_stream_decoder_get_bits_per_sample(decoder);

	/* we are just guessing here, but we want to guess high, not low */
	if(max_framesize > 0) {
		approx_bytes_per_frame = max_framesize;
	}
	/*
	 * Check if it's a known fixed-blocksize stream.  Note that though
	 * the spec doesn't allow zeroes in the STREAMINFO block, we may
	 * never get a STREAMINFO block when decoding so the value of
	 * min_blocksize might be zero.
	 */
	else if(min_blocksize == max_blocksize && min_blocksize > 0) {
		/* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */
		approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64;
	}
	else
		approx_bytes_per_frame = 4608 * channels * bps/8 + 64;

	/*
	 * The decode position is currently at the first frame since we
	 * rewound and processed metadata.
	 */
	if(!FLAC__seekable_stream_decoder_get_decode_position(decoder, &first_frame_offset)) {
		decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
		return false;
	}

	/*
	 * First, we set an upper and lower bound on where in the
	 * stream we will search.  For now we assume the worst case
	 * scenario, which is our best guess at the beginning of
	 * the first and last frames.
	 */
	lower_bound = first_frame_offset;

	/* calc the upper_bound, beyond which we never want to seek */
	if(max_framesize > 0)
		upper_bound = stream_length - (max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */
	else
		upper_bound = stream_length - ((channels * bps * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2);

	/*
	 * Now we refine the bounds if we have a seektable with
	 * suitable points.  Note that according to the spec they
	 * must be ordered by ascending sample number.
	 */
	if(0 != decoder->private_->seek_table) {
		/* find the closest seek point <= target_sample, if it exists */
		for(i = (int)decoder->private_->seek_table->num_points - 1; i >= 0; i--) {
			if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number <= target_sample)
				break;
		}
		if(i >= 0) { /* i.e. we found a suitable seek point... */
			lower_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset;
			lower_seek_point = i;
		}

		/* find the closest seek point > target_sample, if it exists */
		for(i = 0; i < (int)decoder->private_->seek_table->num_points; i++) {
			if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number > target_sample)
				break;
		}
		if(i < (int)decoder->private_->seek_table->num_points) { /* i.e. we found a suitable seek point... */
			upper_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset;
			upper_seek_point = i;
		}
	}

	/*
	 * Now guess at where within those bounds our target
	 * sample will be.
	 */
	if(lower_seek_point >= 0) {
		/* first see if our sample is within a few frames of the lower seekpoint */
		if(decoder->private_->seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < decoder->private_->seek_table->points[lower_seek_point].sample_number + (decoder->private_->seek_table->points[lower_seek_point].frame_samples * 4)) {
			pos = (FLAC__int64)lower_bound;
		}
		else if(upper_seek_point >= 0) {
			const FLAC__uint64 target_offset = target_sample - decoder->private_->seek_table->points[lower_seek_point].sample_number;
			const FLAC__uint64 range_samples = decoder->private_->seek_table->points[upper_seek_point].sample_number - decoder->private_->seek_table->points[lower_seek_point].sample_number;
			const FLAC__uint64 range_bytes = upper_bound - lower_bound;
#if defined _MSC_VER || defined __MINGW32__
			/* with VC++ you have to spoon feed it the casting */
			pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)(FLAC__int64)target_offset / (double)(FLAC__int64)range_samples * (double)(FLAC__int64)(range_bytes-1)) - approx_bytes_per_frame;
#else
			pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)target_offset / (double)range_samples * (double)(range_bytes-1)) - approx_bytes_per_frame;
#endif
		}
	}

	/*
	 * If there's no seek table, we need to use the metadata (if we
	 * have it) and the filelength to estimate the position of the
	 * frame with the correct sample.
	 */
	if(pos < 0 && total_samples > 0) {
#if defined _MSC_VER || defined __MINGW32__
		/* with VC++ you have to spoon feed it the casting */
		pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((double)(FLAC__int64)target_sample / (double)(FLAC__int64)total_samples * (double)(FLAC__int64)(stream_length-first_frame_offset-1)) - approx_bytes_per_frame;
#else
		pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((double)target_sample / (double)total_samples * (double)(stream_length-first_frame_offset-1)) - approx_bytes_per_frame;
#endif
	}

	/*
	 * If there's no seek table and total_samples is unknown, we
	 * don't even bother trying to figure out a target, we just use
	 * our current position.
	 */
	if(pos < 0) {
		FLAC__uint64 upos;
		if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) {
			decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
			return false;
		}
		pos = (FLAC__int64)upos;
		needs_seek = false;
	}
	else
		needs_seek = true;

	/* clip the position to the bounds, lower bound takes precedence */
	if(pos >= (FLAC__int64)upper_bound) {
		pos = (FLAC__int64)upper_bound-1;
		needs_seek = true;
	}
	if(pos < (FLAC__int64)lower_bound) {
		pos = (FLAC__int64)lower_bound;
		needs_seek = true;
	}

	decoder->private_->target_sample = target_sample;
	while(1) {
		if(needs_seek) {
			if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
				decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
				return false;
			}
			if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
				decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
				return false;
			}
		}
		/* Now we need to get a frame.  It is possible for our seek
		 * to land in the middle of audio data that looks exactly like
		 * a frame header from a future version of an encoder.  When
		 * that happens, FLAC__stream_decoder_process_single() will
		 * return false and the state will be
		 * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM.  But there is a
		 * remote possibility that it is properly synced at such a
		 * "future-codec frame", so to make sure, we wait to see
		 * several "unparseable" errors in a row before bailing out.
		 */
		{
			unsigned unparseable_count;
			FLAC__bool got_a_frame = false;
			for (unparseable_count = 0; !got_a_frame && unparseable_count < 10; unparseable_count++) {
				if(FLAC__stream_decoder_process_single(decoder->private_->stream_decoder))
					got_a_frame = true;
				else if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_UNPARSEABLE_STREAM)
					/* try again.  we don't want to flush the decoder since that clears the bitbuffer */
					decoder->private_->stream_decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
				else /* it's a real error */
					break;
			}
			if (!got_a_frame) {
				decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
				return false;
			}
		}
		/* our write callback will change the state when it gets to the target frame */
		if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
			break;
		}
		else { /* we need to narrow the search */
			const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
			FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
			if(this_frame_sample == last_frame_sample && pos < last_pos) {
				/* our last move backwards wasn't big enough, double it */
				pos -= (last_pos - pos);
				needs_seek = true;
			}
			else {
				if(target_sample < this_frame_sample) {
					last_pos = pos;
					approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * channels * bps/8 + 64;
					pos -= approx_bytes_per_frame;
					needs_seek = true;
				}
				else { /* target_sample >= this_frame_sample + this frame's blocksize */
					FLAC__uint64 upos;
					if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) {
						decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
						return false;
					}
					last_pos = pos;
					pos = (FLAC__int64)upos;
					pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
					needs_seek = false;
					/*
					 * if we haven't hit the target frame yet and our position hasn't changed,
					 * it means we're at the end of the stream and the seek target does not exist.
					 */
					if(last_pos == pos) {
						decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
						return false;
					}
				}
			}
			if(pos < (FLAC__int64)lower_bound)
				pos = (FLAC__int64)lower_bound;
			last_frame_sample = this_frame_sample;
		}
	}

	return true;
}
Esempio n. 3
0
FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw)
{
	unsigned i, j;
	const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);

	if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN))
		return false;

	if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN))
		return false;

	/*
	 * First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string
	 */
	i = metadata->length;
	if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
		FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry);
		i -= metadata->data.vorbis_comment.vendor_string.length;
		i += vendor_string_length;
	}
	FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
	/* double protection */
	if(i >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
		return false;
	if(!FLAC__bitwriter_write_raw_uint32(bw, i, FLAC__STREAM_METADATA_LENGTH_LEN))
		return false;

	switch(metadata->type) {
		case FLAC__METADATA_TYPE_STREAMINFO:
			FLAC__ASSERT(metadata->data.stream_info.min_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.max_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.min_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_framesize, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.max_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_framesize, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN))
				return false;
			FLAC__ASSERT(FLAC__format_sample_rate_is_valid(metadata->data.stream_info.sample_rate));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.sample_rate, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.channels > 0);
			FLAC__ASSERT(metadata->data.stream_info.channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.channels-1, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.bits_per_sample > 0);
			FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN))
				return false;
			FLAC__ASSERT(metadata->data.stream_info.total_samples < (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
			if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
				return false;
			if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16))
				return false;
			break;
		case FLAC__METADATA_TYPE_PADDING:
			if(!FLAC__bitwriter_write_zeroes(bw, metadata->length * 8))
				return false;
			break;
		case FLAC__METADATA_TYPE_APPLICATION:
			if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8))
				return false;
			if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.data, metadata->length - (FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)))
				return false;
			break;
		case FLAC__METADATA_TYPE_SEEKTABLE:
			for(i = 0; i < metadata->data.seek_table.num_points; i++) {
				if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].sample_number, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].stream_offset, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.seek_table.points[i].frame_samples, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN))
					return false;
			}
			break;
		case FLAC__METADATA_TYPE_VORBIS_COMMENT:
			if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, vendor_string_length))
				return false;
			if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)FLAC__VENDOR_STRING, vendor_string_length))
				return false;
			if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.num_comments))
				return false;
			for(i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
				if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.comments[i].length))
					return false;
				if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length))
					return false;
			}
			break;
		case FLAC__METADATA_TYPE_CUESHEET:
			FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
			if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.cue_sheet.media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8))
				return false;
			if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.cue_sheet.lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN))
				return false;
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.is_cd? 1 : 0, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN))
				return false;
			if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN))
				return false;
			if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.num_tracks, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN))
				return false;
			for(i = 0; i < metadata->data.cue_sheet.num_tracks; i++) {
				const FLAC__StreamMetadata_CueSheet_Track *track = metadata->data.cue_sheet.tracks + i;

				if(!FLAC__bitwriter_write_raw_uint64(bw, track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, track->number, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN))
					return false;
				FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
				if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, track->type, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, track->pre_emphasis, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN))
					return false;
				if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, track->num_indices, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN))
					return false;
				for(j = 0; j < track->num_indices; j++) {
					const FLAC__StreamMetadata_CueSheet_Index *indx = track->indices + j;

					if(!FLAC__bitwriter_write_raw_uint64(bw, indx->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN))
						return false;
					if(!FLAC__bitwriter_write_raw_uint32(bw, indx->number, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN))
						return false;
					if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN))
						return false;
				}
			}
			break;
		case FLAC__METADATA_TYPE_PICTURE:
			{
				size_t len;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
					return false;
				len = strlen(metadata->data.picture.mime_type);
				if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
					return false;
				if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.picture.mime_type, len))
					return false;
				len = strlen((const char *)metadata->data.picture.description);
				if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
					return false;
				if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.description, len))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN))
					return false;
				if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
					return false;
				if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.data, metadata->data.picture.data_length))
					return false;
			}
			break;
		default:
			if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.unknown.data, metadata->length))
				return false;
			break;
	}

	FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
	return true;
}
FLAC__bool test_bitwriter(void)
{
	FLAC__BitWriter *bw;
	FLAC__bool ok;
	unsigned i, j;
#if WORDS_BIGENDIAN
	static bwword test_pattern1[5] = { 0xaaf0aabe, 0xaaaaaaa8, 0x300aaaaa, 0xaaadeadb, 0x00eeface };
#else
	static bwword test_pattern1[5] = { 0xbeaaf0aa, 0xa8aaaaaa, 0xaaaa0a30, 0xdbeaadaa, 0x00eeface };
#endif
	unsigned words, bits; /* what we think bw->words and bw->bits should be */

	printf("\n+++ libFLAC unit test: bitwriter\n\n");

	/*
	 * test new -> delete
	 */
	printf("testing new... ");
	bw = FLAC__bitwriter_new();
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitwriter_delete(bw);
	printf("OK\n");

	/*
	 * test new -> init -> delete
	 */
	printf("testing new... ");
	bw = FLAC__bitwriter_new();
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	FLAC__bitwriter_init(bw);
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitwriter_delete(bw);
	printf("OK\n");

	/*
	 * test new -> init -> clear -> delete
	 */
	printf("testing new... ");
	bw = FLAC__bitwriter_new();
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	FLAC__bitwriter_init(bw);
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing clear... ");
	FLAC__bitwriter_clear(bw);
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitwriter_delete(bw);
	printf("OK\n");

	/*
	 * test normal usage
	 */
	printf("testing new... ");
	bw = FLAC__bitwriter_new();
	if(0 == bw) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	ok = FLAC__bitwriter_init(bw);
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok)
		return false;

	printf("testing clear... ");
	FLAC__bitwriter_clear(bw);
	printf("OK\n");

	words = bits = 0;

	printf("capacity = %u\n", bw->capacity);

	printf("testing zeroes, raw_uint32*... ");
	ok =
		FLAC__bitwriter_write_raw_uint32(bw, 0x1, 1) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0x1, 2) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0xa, 5) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0xf0, 8) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0x2aa, 10) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0xf, 4) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0xaaaaaaaa, 32) &&
		FLAC__bitwriter_write_zeroes(bw, 4) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0x3, 2) &&
		FLAC__bitwriter_write_zeroes(bw, 8) &&
		FLAC__bitwriter_write_raw_uint64(bw, FLAC__U64L(0xaaaaaaaadeadbeef), 64) &&
		FLAC__bitwriter_write_raw_uint32(bw, 0xace, 12)
	;
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	words = 4;
	bits = 24;
	if(bw->words != words) {
		printf("FAILED byte count %u != %u\n", bw->words, words);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if(bw->bits != bits) {
		printf("FAILED bit count %u != %u\n", bw->bits, bits);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if(memcmp(bw->buffer, test_pattern1, sizeof(bwword)*words) != 0) {
		printf("FAILED pattern match (buffer)\n");
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if((bw->accum & 0x00ffffff) != test_pattern1[words]) {
		printf("FAILED pattern match (bw->accum=%08X != %08X)\n", bw->accum&0x00ffffff, test_pattern1[words]);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitwriter_dump(bw, stdout);

	printf("testing raw_uint32 some more... ");
	ok = FLAC__bitwriter_write_raw_uint32(bw, 0x3d, 6);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	bits += 6;
	test_pattern1[words] <<= 6;
	test_pattern1[words] |= 0x3d;
	if(bw->words != words) {
		printf("FAILED byte count %u != %u\n", bw->words, words);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if(bw->bits != bits) {
		printf("FAILED bit count %u != %u\n", bw->bits, bits);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if(memcmp(bw->buffer, test_pattern1, sizeof(bwword)*words) != 0) {
		printf("FAILED pattern match (buffer)\n");
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	if((bw->accum & 0x3fffffff) != test_pattern1[words]) {
		printf("FAILED pattern match (bw->accum=%08X != %08X)\n", bw->accum&0x3fffffff, test_pattern1[words]);
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitwriter_dump(bw, stdout);

	printf("testing utf8_uint32(0x00000000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x00000000);
	ok = TOTAL_BITS(bw) == 8 && (bw->accum & 0xff) == 0;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x0000007F)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x0000007F);
	ok = TOTAL_BITS(bw) == 8 && (bw->accum & 0xff) == 0x7F;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00000080)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x00000080);
	ok = TOTAL_BITS(bw) == 16 && (bw->accum & 0xffff) == 0xC280;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x000007FF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x000007FF);
	ok = TOTAL_BITS(bw) == 16 && (bw->accum & 0xffff) == 0xDFBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00000800)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x00000800);
	ok = TOTAL_BITS(bw) == 24 && (bw->accum & 0xffffff) == 0xE0A080;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x0000FFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x0000FFFF);
	ok = TOTAL_BITS(bw) == 24 && (bw->accum & 0xffffff) == 0xEFBFBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00010000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x00010000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xF0908080;
#else
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0x808090F0;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x001FFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x001FFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xF7BFBFBF;
#else
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xBFBFBFF7;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00200000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x00200000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xF8888080 && (bw->accum & 0xff) == 0x80;
#else
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0x808088F8 && (bw->accum & 0xff) == 0x80;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x03FFFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x03FFFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xFBBFBFBF && (bw->accum & 0xff) == 0xBF;
#else
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xBFBFBFFB && (bw->accum & 0xff) == 0xBF;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x04000000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x04000000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xFC848080 && (bw->accum & 0xffff) == 0x8080;
#else
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0x808084FC && (bw->accum & 0xffff) == 0x8080;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x7FFFFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint32(bw, 0x7FFFFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xFDBFBFBF && (bw->accum & 0xffff) == 0xBFBF;
#else
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xBFBFBFFD && (bw->accum & 0xffff) == 0xBFBF;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000000000000);
	ok = TOTAL_BITS(bw) == 8 && (bw->accum & 0xff) == 0;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000000000007F)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x000000000000007F);
	ok = TOTAL_BITS(bw) == 8 && (bw->accum & 0xff) == 0x7F;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000080)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000000000080);
	ok = TOTAL_BITS(bw) == 16 && (bw->accum & 0xffff) == 0xC280;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x00000000000007FF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x00000000000007FF);
	ok = TOTAL_BITS(bw) == 16 && (bw->accum & 0xffff) == 0xDFBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000800)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000000000800);
	ok = TOTAL_BITS(bw) == 24 && (bw->accum & 0xffffff) == 0xE0A080;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000000000FFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x000000000000FFFF);
	ok = TOTAL_BITS(bw) == 24 && (bw->accum & 0xffffff) == 0xEFBFBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000010000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000000010000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xF0908080;
#else
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0x808090F0;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x00000000001FFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x00000000001FFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xF7BFBFBF;
#else
	ok = TOTAL_BITS(bw) == 32 && bw->buffer[0] == 0xBFBFBFF7;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000200000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000000200000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xF8888080 && (bw->accum & 0xff) == 0x80;
#else
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0x808088F8 && (bw->accum & 0xff) == 0x80;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000003FFFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000003FFFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xFBBFBFBF && (bw->accum & 0xff) == 0xBF;
#else
	ok = TOTAL_BITS(bw) == 40 && bw->buffer[0] == 0xBFBFBFFB && (bw->accum & 0xff) == 0xBF;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000004000000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000004000000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xFC848080 && (bw->accum & 0xffff) == 0x8080;
#else
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0x808084FC && (bw->accum & 0xffff) == 0x8080;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000007FFFFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x000000007FFFFFFF);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xFDBFBFBF && (bw->accum & 0xffff) == 0xBFBF;
#else
	ok = TOTAL_BITS(bw) == 48 && bw->buffer[0] == 0xBFBFBFFD && (bw->accum & 0xffff) == 0xBFBF;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000080000000)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, 0x0000000080000000);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 56 && bw->buffer[0] == 0xFE828080 && (bw->accum & 0xffffff) == 0x808080;
#else
	ok = TOTAL_BITS(bw) == 56 && bw->buffer[0] == 0x808082FE && (bw->accum & 0xffffff) == 0x808080;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000FFFFFFFFF)... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_utf8_uint64(bw, FLAC__U64L(0x0000000FFFFFFFFF));
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == 56 && bw->buffer[0] == 0xFEBFBFBF && (bw->accum & 0xffffff) == 0xBFBFBF;
#else
	ok = TOTAL_BITS(bw) == 56 && bw->buffer[0] == 0xBFBFBFFE && (bw->accum & 0xffffff) == 0xBFBFBF;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}

	printf("testing grow... ");
	FLAC__bitwriter_clear(bw);
	FLAC__bitwriter_write_raw_uint32(bw, 0x5, 4);
	j = bw->capacity;
	for(i = 0; i < j; i++)
		FLAC__bitwriter_write_raw_uint32(bw, 0xaaaaaaaa, 32);
#if WORDS_BIGENDIAN
	ok = TOTAL_BITS(bw) == i*32+4 && bw->buffer[0] == 0x5aaaaaaa && (bw->accum & 0xf) == 0xa;
#else
	ok = TOTAL_BITS(bw) == i*32+4 && bw->buffer[0] == 0xaaaaaa5a && (bw->accum & 0xf) == 0xa;
#endif
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitwriter_dump(bw, stdout);
		return false;
	}
	printf("capacity = %u\n", bw->capacity);

	printf("testing free... ");
	FLAC__bitwriter_free(bw);
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitwriter_delete(bw);
	printf("OK\n");

	printf("\nPASSED!\n");
	return true;
}
Esempio n. 5
0
FLAC__bool test_bitbuffer()
{
	FLAC__BitBuffer *bb, *bb_zero, *bb_one, *bbcopy;
	FLAC__bool ok;
	unsigned i, j;
	static FLAC__byte test_pattern1[19] = { 0xaa, 0xf0, 0xaa, 0xbe, 0xaa, 0xaa, 0xaa, 0xa8, 0x30, 0x0a, 0xaa, 0xaa, 0xaa, 0xad, 0xea, 0xdb, 0xee, 0xfa, 0xce };

	FLAC__ASSERT(FLAC__BITS_PER_BLURB == 8);

	printf("\n+++ libFLAC unit test: bitbuffer\n\n");

	/*
	 * test new -> delete
	 */
	printf("testing new... ");
	bb = FLAC__bitbuffer_new();
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitbuffer_delete(bb);
	printf("OK\n");

	/*
	 * test new -> init -> delete
	 */
	printf("testing new... ");
	bb = FLAC__bitbuffer_new();
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	FLAC__bitbuffer_init(bb);
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitbuffer_delete(bb);
	printf("OK\n");

	/*
	 * test new -> init -> clear -> delete
	 */
	printf("testing new... ");
	bb = FLAC__bitbuffer_new();
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	FLAC__bitbuffer_init(bb);
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing clear... ");
	FLAC__bitbuffer_clear(bb);
	if(0 == bb) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitbuffer_delete(bb);
	printf("OK\n");

	/*
	 * test normal usage
	 */
	printf("testing new... ");
	bb = FLAC__bitbuffer_new();
	bb_zero = FLAC__bitbuffer_new();
	bb_one = FLAC__bitbuffer_new();
	bbcopy = FLAC__bitbuffer_new();
	if(0 == bb || 0 == bb_zero || 0 == bb_one || 0 == bbcopy) {
		printf("FAILED, returned NULL\n");
		return false;
	}
	printf("OK\n");

	printf("testing init... ");
	ok = FLAC__bitbuffer_init(bb) && FLAC__bitbuffer_init(bb_zero) && FLAC__bitbuffer_init(bb_one) && FLAC__bitbuffer_init(bbcopy);
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok)
		return false;

	printf("testing clear... ");
	ok = FLAC__bitbuffer_clear(bb) && FLAC__bitbuffer_clear(bb_zero) && FLAC__bitbuffer_clear(bb_one) && FLAC__bitbuffer_clear(bbcopy);
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok)
		return false;

	printf("setting up bb_one... ");
	ok = FLAC__bitbuffer_write_raw_uint32(bb_one, 1, 7) && FLAC__bitbuffer_read_raw_uint32(bb_one, &i, 6, dummy_read_callback, 0);
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok)
		return false;
	FLAC__bitbuffer_dump(bb_one, stdout);

	printf("capacity = %u\n", bb->capacity);

	printf("testing zeroes, raw_uint32*... ");
	ok =
		FLAC__bitbuffer_write_raw_uint32(bb, 0x1, 1) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0x1, 2) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0xa, 5) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0xf0, 8) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0x2aa, 10) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0xf, 4) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0xaaaaaaaa, 32) &&
		FLAC__bitbuffer_write_zeroes(bb, 4) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0x3, 2) &&
		FLAC__bitbuffer_write_zeroes(bb, 8) &&
		FLAC__bitbuffer_write_raw_uint64(bb, FLAC__U64L(0xaaaaaaaadeadbeef), 64) &&
		FLAC__bitbuffer_write_raw_uint32(bb, 0xace, 12)
	;
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1));
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 0) {
		printf("FAILED bit count %u != 0\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing raw_uint32 some more... ");
	ok = FLAC__bitbuffer_write_raw_uint32(bb, 0x3d, 6);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1));
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 6) {
		printf("FAILED bit count %u != 6\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs] != 0x3d) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_zero)... ");
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_zero);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1));
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 6) {
		printf("FAILED bit count %u != 6\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs] != 0x3d) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_one)... ");
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_one);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1));
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 7) {
		printf("FAILED bit count %u != 7\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs] != 0x7b) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_one again)... ");
	(void)FLAC__bitbuffer_write_raw_uint32(bb_one, 1, 1);
	(void)FLAC__bitbuffer_read_raw_uint32(bb_one, &i, 1, dummy_read_callback, 0);
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_one);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)+1) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1)+1);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 0) {
		printf("FAILED bit count %u != 0\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs-1] != 0xf7) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_four)... ");
	(void)FLAC__bitbuffer_clear(bb_one);
	(void)FLAC__bitbuffer_write_raw_uint32(bb_one, 8, 4);
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_one);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)+1) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1)+1);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 4) {
		printf("FAILED bit count %u != 4\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs] != 0x08) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_eight)... ");
	(void)FLAC__bitbuffer_read_raw_uint32(bb_one, &i, 4, dummy_read_callback, 0);
	(void)FLAC__bitbuffer_write_raw_uint32(bb_one, 0xaa, 8);
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_one);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)+2) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1)+2);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 4) {
		printf("FAILED bit count %u != 4\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs-1] != 0x8a || bb->buffer[bb->blurbs] != 0x0a) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing concatenate_aligned (bb_seventeen)... ");
	(void)FLAC__bitbuffer_write_raw_uint32(bb_one, 0x155, 9);
	ok = FLAC__bitbuffer_concatenate_aligned(bb, bb_one);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->blurbs != sizeof(test_pattern1)+4) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, (unsigned)sizeof(test_pattern1)+4);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->bits != 5) {
		printf("FAILED bit count %u != 5\n", bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(bb->total_bits != 8*bb->blurbs+bb->bits) {
		printf("FAILED total_bits count %u != %u (%u:%u)\n", bb->total_bits, 8*bb->blurbs+bb->bits, bb->blurbs, bb->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	if(memcmp(bb->buffer, test_pattern1, sizeof(FLAC__byte)*sizeof(test_pattern1)) != 0 || bb->buffer[bb->blurbs-3] != 0x8a || bb->buffer[bb->blurbs-2] != 0xaa || bb->buffer[bb->blurbs-1] != 0xaa || bb->buffer[bb->blurbs] != 0x15) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("OK\n");
	FLAC__bitbuffer_dump(bb, stdout);

	printf("testing utf8_uint32(0x00000000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x00000000);
	ok = bb->total_bits == 8 && bb->buffer[0] == 0;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x0000007F)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x0000007F);
	ok = bb->total_bits == 8 && bb->buffer[0] == 0x7F;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00000080)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x00000080);
	ok = bb->total_bits == 16 && bb->buffer[0] == 0xC2 && bb->buffer[1] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x000007FF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x000007FF);
	ok = bb->total_bits == 16 && bb->buffer[0] == 0xDF && bb->buffer[1] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00000800)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x00000800);
	ok = bb->total_bits == 24 && bb->buffer[0] == 0xE0 && bb->buffer[1] == 0xA0 && bb->buffer[2] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x0000FFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x0000FFFF);
	ok = bb->total_bits == 24 && bb->buffer[0] == 0xEF && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00010000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x00010000);
	ok = bb->total_bits == 32 && bb->buffer[0] == 0xF0 && bb->buffer[1] == 0x90 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x001FFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x001FFFFF);
	ok = bb->total_bits == 32 && bb->buffer[0] == 0xF7 && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x00200000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x00200000);
	ok = bb->total_bits == 40 && bb->buffer[0] == 0xF8 && bb->buffer[1] == 0x88 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80 && bb->buffer[4] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x03FFFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x03FFFFFF);
	ok = bb->total_bits == 40 && bb->buffer[0] == 0xFB && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF && bb->buffer[4] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x04000000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x04000000);
	ok = bb->total_bits == 48 && bb->buffer[0] == 0xFC && bb->buffer[1] == 0x84 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80 && bb->buffer[4] == 0x80 && bb->buffer[5] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint32(0x7FFFFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint32(bb, 0x7FFFFFFF);
	ok = bb->total_bits == 48 && bb->buffer[0] == 0xFD && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF && bb->buffer[4] == 0xBF && bb->buffer[5] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000000000000);
	ok = bb->total_bits == 8 && bb->buffer[0] == 0;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000000000007F)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x000000000000007F);
	ok = bb->total_bits == 8 && bb->buffer[0] == 0x7F;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000080)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000000000080);
	ok = bb->total_bits == 16 && bb->buffer[0] == 0xC2 && bb->buffer[1] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x00000000000007FF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x00000000000007FF);
	ok = bb->total_bits == 16 && bb->buffer[0] == 0xDF && bb->buffer[1] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000000800)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000000000800);
	ok = bb->total_bits == 24 && bb->buffer[0] == 0xE0 && bb->buffer[1] == 0xA0 && bb->buffer[2] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000000000FFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x000000000000FFFF);
	ok = bb->total_bits == 24 && bb->buffer[0] == 0xEF && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000010000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000000010000);
	ok = bb->total_bits == 32 && bb->buffer[0] == 0xF0 && bb->buffer[1] == 0x90 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x00000000001FFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x00000000001FFFFF);
	ok = bb->total_bits == 32 && bb->buffer[0] == 0xF7 && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000000200000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000000200000);
	ok = bb->total_bits == 40 && bb->buffer[0] == 0xF8 && bb->buffer[1] == 0x88 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80 && bb->buffer[4] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000003FFFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000003FFFFFF);
	ok = bb->total_bits == 40 && bb->buffer[0] == 0xFB && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF && bb->buffer[4] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000004000000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000004000000);
	ok = bb->total_bits == 48 && bb->buffer[0] == 0xFC && bb->buffer[1] == 0x84 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80 && bb->buffer[4] == 0x80 && bb->buffer[5] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x000000007FFFFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x000000007FFFFFFF);
	ok = bb->total_bits == 48 && bb->buffer[0] == 0xFD && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF && bb->buffer[4] == 0xBF && bb->buffer[5] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000080000000)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, 0x0000000080000000);
	ok = bb->total_bits == 56 && bb->buffer[0] == 0xFE && bb->buffer[1] == 0x82 && bb->buffer[2] == 0x80 && bb->buffer[3] == 0x80 && bb->buffer[4] == 0x80 && bb->buffer[5] == 0x80 && bb->buffer[6] == 0x80;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing utf8_uint64(0x0000000FFFFFFFFF)... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_utf8_uint64(bb, FLAC__U64L(0x0000000FFFFFFFFF));
	ok = bb->total_bits == 56 && bb->buffer[0] == 0xFE && bb->buffer[1] == 0xBF && bb->buffer[2] == 0xBF && bb->buffer[3] == 0xBF && bb->buffer[4] == 0xBF && bb->buffer[5] == 0xBF && bb->buffer[6] == 0xBF;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}

	printf("testing grow... ");
	FLAC__bitbuffer_clear(bb);
	FLAC__bitbuffer_write_raw_uint32(bb, 0xa, 4);
	j = bb->capacity;
	for(i = 0; i < j; i++)
		FLAC__bitbuffer_write_raw_uint32(bb, 0xaa, 8);
	ok = bb->total_bits = i*8+4 && bb->buffer[0] == 0xaa && bb->buffer[i] == 0xa;
	printf("%s\n", ok?"OK":"FAILED");
	if(!ok) {
		FLAC__bitbuffer_dump(bb, stdout);
		return false;
	}
	printf("capacity = %u\n", bb->capacity);

	printf("testing clone... ");
	ok = FLAC__bitbuffer_clone(bbcopy, bb);
	if(!ok) {
		printf("FAILED\n");
		FLAC__bitbuffer_dump(bb, stdout);
		FLAC__bitbuffer_dump(bbcopy, stdout);
		return false;
	}
	if(bb->blurbs != bbcopy->blurbs) {
		printf("FAILED byte count %u != %u\n", bb->blurbs, bbcopy->blurbs);
		FLAC__bitbuffer_dump(bb, stdout);
		FLAC__bitbuffer_dump(bbcopy, stdout);
		return false;
	}
	if(bb->bits != bbcopy->bits) {
		printf("FAILED bit count %u != %u\n", bb->bits, bbcopy->bits);
		FLAC__bitbuffer_dump(bb, stdout);
		FLAC__bitbuffer_dump(bbcopy, stdout);
		return false;
	}
	if(bb->total_bits != bbcopy->total_bits) {
		printf("FAILED total_bits count %u != %u\n", bb->total_bits, bbcopy->total_bits);
		FLAC__bitbuffer_dump(bb, stdout);
		FLAC__bitbuffer_dump(bbcopy, stdout);
		return false;
	}
	if(memcmp(bb->buffer, bbcopy->buffer, sizeof(FLAC__byte)*bb->capacity) != 0) {
		printf("FAILED pattern match\n");
		FLAC__bitbuffer_dump(bb, stdout);
		FLAC__bitbuffer_dump(bbcopy, stdout);
		return false;
	}
	printf("OK\n");

	printf("testing free... ");
	FLAC__bitbuffer_free(bb);
	FLAC__bitbuffer_free(bbcopy);
	printf("OK\n");

	printf("testing delete... ");
	FLAC__bitbuffer_delete(bb);
	FLAC__bitbuffer_delete(bb_zero);
	FLAC__bitbuffer_delete(bb_one);
	FLAC__bitbuffer_delete(bbcopy);
	printf("OK\n");

	printf("\nPASSED!\n");
	return true;
}