stream_decoder.c 71 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
2
 * Copyright (C) 2000,2001,2002  Josh Coalson
Josh Coalson's avatar
Josh Coalson committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h> /* for malloc() */
Josh Coalson's avatar
Josh Coalson committed
22
#include <string.h> /* for memset/memcpy() */
23
#include "FLAC/assert.h"
24
#include "protected/stream_decoder.h"
Josh Coalson's avatar
Josh Coalson committed
25
#include "private/bitbuffer.h"
26
#include "private/cpu.h"
Josh Coalson's avatar
Josh Coalson committed
27
28
29
30
#include "private/crc.h"
#include "private/fixed.h"
#include "private/lpc.h"

31
32
33
34
35
36
/***********************************************************************
 *
 * Private static data
 *
 ***********************************************************************/

Josh Coalson's avatar
Josh Coalson committed
37
static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' };
38
39
40
41
42
43
44

/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

Josh Coalson's avatar
Josh Coalson committed
45
static FLAC__bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels);
46
static FLAC__bool stream_decoder_has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id);
Josh Coalson's avatar
Josh Coalson committed
47
48
49
50
51
52
53
54
55
56
57
static FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder);
static FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder);
static FLAC__bool stream_decoder_skip_id3v2_tag_(FLAC__StreamDecoder *decoder);
static FLAC__bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder);
static FLAC__bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame);
static FLAC__bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder);
static FLAC__bool stream_decoder_read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
static FLAC__bool stream_decoder_read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
static FLAC__bool stream_decoder_read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
static FLAC__bool stream_decoder_read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
static FLAC__bool stream_decoder_read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
58
static FLAC__bool stream_decoder_read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, FLAC__EntropyCodingMethod_PartitionedRice *partitioned_rice, FLAC__int32 *residual);
Josh Coalson's avatar
Josh Coalson committed
59
60
static FLAC__bool stream_decoder_read_zero_padding_(FLAC__StreamDecoder *decoder);
static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data);
61
62
63
64
65
66
67

/***********************************************************************
 *
 * Private class data
 *
 ***********************************************************************/

Josh Coalson's avatar
Josh Coalson committed
68
typedef struct FLAC__StreamDecoderPrivate {
Josh Coalson's avatar
Josh Coalson committed
69
70
	FLAC__StreamDecoderReadStatus (*read_callback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
	FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
Josh Coalson's avatar
Josh Coalson committed
71
72
	void (*metadata_callback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
	void (*error_callback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
Josh Coalson's avatar
Josh Coalson committed
73
74
	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[]);
Josh Coalson's avatar
Josh Coalson committed
75
	void *client_data;
76
	FLAC__BitBuffer *input;
Josh Coalson's avatar
Josh Coalson committed
77
78
	FLAC__int32 *output[FLAC__MAX_CHANNELS];
	FLAC__int32 *residual[FLAC__MAX_CHANNELS];
79
	unsigned output_capacity, output_channels;
Josh Coalson's avatar
Josh Coalson committed
80
81
82
	FLAC__uint32 last_frame_number;
	FLAC__uint64 samples_decoded;
	FLAC__bool has_stream_info, has_seek_table;
83
84
	FLAC__StreamMetaData stream_info;
	FLAC__StreamMetaData seek_table;
85
86
87
	FLAC__bool metadata_filter[FLAC__METADATA_TYPE_VORBIS_COMMENT+1];
	FLAC__byte *metadata_filter_ids;
	unsigned metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */
88
	FLAC__Frame frame;
Josh Coalson's avatar
Josh Coalson committed
89
	FLAC__bool cached; /* true if there is a byte in lookahead */
90
	FLAC__CPUInfo cpuinfo;
Josh Coalson's avatar
Josh Coalson committed
91
92
	FLAC__byte header_warmup[2]; /* contains the sync code and reserved bits */
	FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */
Josh Coalson's avatar
Josh Coalson committed
93
94
} FLAC__StreamDecoderPrivate;

95
96
97
98
99
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/
Josh Coalson's avatar
Josh Coalson committed
100

Josh Coalson's avatar
Josh Coalson committed
101
102
103
104
105
106
107
108
109
const char *FLAC__StreamDecoderStateString[] = {
	"FLAC__STREAM_DECODER_SEARCH_FOR_METADATA",
	"FLAC__STREAM_DECODER_READ_METADATA",
	"FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC",
	"FLAC__STREAM_DECODER_READ_FRAME",
	"FLAC__STREAM_DECODER_END_OF_STREAM",
	"FLAC__STREAM_DECODER_ABORTED",
	"FLAC__STREAM_DECODER_UNPARSEABLE_STREAM",
	"FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
110
	"FLAC__STREAM_DECODER_ALREADY_INITIALIZED",
111
	"FLAC__STREAM_DECODER_INVALID_CALLBACK",
Josh Coalson's avatar
Josh Coalson committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
	"FLAC__STREAM_DECODER_UNINITIALIZED"
};

const char *FLAC__StreamDecoderReadStatusString[] = {
	"FLAC__STREAM_DECODER_READ_CONTINUE",
	"FLAC__STREAM_DECODER_READ_END_OF_STREAM",
	"FLAC__STREAM_DECODER_READ_ABORT"
};

const char *FLAC__StreamDecoderWriteStatusString[] = {
	"FLAC__STREAM_DECODER_WRITE_CONTINUE",
	"FLAC__STREAM_DECODER_WRITE_ABORT"
};

const char *FLAC__StreamDecoderErrorStatusString[] = {
127
128
129
	"FLAC__STREAM_DECODER_ERROR_LOST_SYNC",
	"FLAC__STREAM_DECODER_ERROR_BAD_HEADER",
	"FLAC__STREAM_DECODER_ERROR_FRAME_CRC_MISMATCH"
Josh Coalson's avatar
Josh Coalson committed
130
131
};

132
133
134
135
136
137
/***********************************************************************
 *
 * Class constructor/destructor
 *
 ***********************************************************************/
FLAC__StreamDecoder *FLAC__stream_decoder_new()
Josh Coalson's avatar
Josh Coalson committed
138
{
139
140
141
142
143
144
145
	FLAC__StreamDecoder *decoder;

	FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */

	decoder = (FLAC__StreamDecoder*)malloc(sizeof(FLAC__StreamDecoder));
	if(decoder == 0) {
		return 0;
Josh Coalson's avatar
Josh Coalson committed
146
	}
147
148
	decoder->protected_ = (FLAC__StreamDecoderProtected*)malloc(sizeof(FLAC__StreamDecoderProtected));
	if(decoder->protected_ == 0) {
149
150
151
		free(decoder);
		return 0;
	}
152
153
154
	decoder->private_ = (FLAC__StreamDecoderPrivate*)malloc(sizeof(FLAC__StreamDecoderPrivate));
	if(decoder->private_ == 0) {
		free(decoder->protected_);
155
156
157
		free(decoder);
		return 0;
	}
158
159
160
161
162
163
164
	decoder->private_->input = FLAC__bitbuffer_new();
	if(decoder->private_->input == 0) {
		free(decoder->private_);
		free(decoder->protected_);
		free(decoder);
		return 0;
	}
165

166
	decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
167

168
169
170
171
172
	decoder->private_->read_callback = 0;
	decoder->private_->write_callback = 0;
	decoder->private_->metadata_callback = 0;
	decoder->private_->error_callback = 0;
	decoder->private_->client_data = 0;
173

Josh Coalson's avatar
Josh Coalson committed
174
175
176
	return decoder;
}

177
void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
178
{
179
	FLAC__ASSERT(decoder != 0);
180
181
	FLAC__ASSERT(decoder->protected_ != 0);
	FLAC__ASSERT(decoder->private_ != 0);
182
	FLAC__ASSERT(decoder->private_->input != 0);
183

184
	FLAC__bitbuffer_delete(decoder->private_->input);
185
186
	free(decoder->private_);
	free(decoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
187
188
189
	free(decoder);
}

190
191
192
193
194
195
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

196
FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
197
198
199
{
	unsigned i;

200
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
201

202
203
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED;
Josh Coalson's avatar
Josh Coalson committed
204

205
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
206

207
208
	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;
Josh Coalson's avatar
Josh Coalson committed
209

210
211
	if(!FLAC__bitbuffer_init(decoder->private_->input))
		return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
212

213
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
214
215
		decoder->private_->output[i] = 0;
		decoder->private_->residual[i] = 0;
216
	}
Josh Coalson's avatar
Josh Coalson committed
217

218
219
220
221
222
223
	decoder->private_->output_capacity = 0;
	decoder->private_->output_channels = 0;
	decoder->private_->last_frame_number = 0;
	decoder->private_->samples_decoded = 0;
	decoder->private_->has_stream_info = false;
	decoder->private_->has_seek_table = false;
224
225
226
227
228
229
230
231
232
233

	memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter));
	decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true;
	decoder->private_->metadata_filter_ids_capacity = 16;
	if(0 == (decoder->private_->metadata_filter_ids = malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) {
		decoder->private_->metadata_filter_ids_capacity = 0;
		return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
	}
	decoder->private_->metadata_filter_ids_count = 0;

234
	decoder->private_->cached = false;
Josh Coalson's avatar
Josh Coalson committed
235

236
237
238
	/*
	 * get the CPU info and set the function pointers
	 */
239
	FLAC__cpu_info(&decoder->private_->cpuinfo);
240
	/* first default to the non-asm routines */
241
242
	decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal;
	decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal;
243
	/* now override with asm where appropriate */
244
#ifndef FLAC__NO_ASM
245
	if(decoder->private_->cpuinfo.use_asm) {
246
#ifdef FLAC__CPU_IA32
247
		FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
248
#ifdef FLAC__HAS_NASM
249
250
251
		if(decoder->private_->cpuinfo.data.ia32.mmx) {
			decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32;
			decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx;
252
253
		}
		else {
254
255
			decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32;
			decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32;
256
		}
257
#endif
258
#endif
259
	}
260
261
#endif

262
	return decoder->protected_->state;
Josh Coalson's avatar
Josh Coalson committed
263
264
265
266
267
}

void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
{
	unsigned i;
268
	FLAC__ASSERT(decoder != 0);
269
	if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED)
Josh Coalson's avatar
Josh Coalson committed
270
		return;
271
272
273
	if(decoder->private_->has_seek_table) {
		free(decoder->private_->seek_table.data.seek_table.points);
		decoder->private_->seek_table.data.seek_table.points = 0;
274
	}
275
	FLAC__bitbuffer_free(decoder->private_->input);
276
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
277
		/* 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. */
278
279
280
		if(decoder->private_->output[i] != 0) {
			free(decoder->private_->output[i]-4);
			decoder->private_->output[i] = 0;
281
		}
282
283
284
		if(decoder->private_->residual[i] != 0) {
			free(decoder->private_->residual[i]);
			decoder->private_->residual[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
285
286
		}
	}
287
288
289
290
	if(decoder->private_->metadata_filter_ids != 0) {
		free(decoder->private_->metadata_filter_ids);
		decoder->private_->metadata_filter_ids = 0;
	}
291
292
293
	decoder->private_->output_capacity = 0;
	decoder->private_->output_channels = 0;
	decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
294
295
}

Josh Coalson's avatar
Josh Coalson committed
296
FLAC__bool FLAC__stream_decoder_set_read_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadStatus (*value)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data))
297
{
298
299
300
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
301
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
302
		return false;
303
	decoder->private_->read_callback = value;
304
305
306
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
307
FLAC__bool FLAC__stream_decoder_set_write_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteStatus (*value)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data))
308
{
309
310
311
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
312
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
313
		return false;
314
	decoder->private_->write_callback = value;
315
316
317
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
318
FLAC__bool FLAC__stream_decoder_set_metadata_callback(const FLAC__StreamDecoder *decoder, void (*value)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data))
319
{
320
321
322
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
323
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
324
		return false;
325
	decoder->private_->metadata_callback = value;
326
327
328
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
329
FLAC__bool FLAC__stream_decoder_set_error_callback(const FLAC__StreamDecoder *decoder, void (*value)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data))
330
{
331
332
333
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
334
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
335
		return false;
336
	decoder->private_->error_callback = value;
337
338
339
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
340
FLAC__bool FLAC__stream_decoder_set_client_data(const FLAC__StreamDecoder *decoder, void *value)
341
{
342
343
344
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
345
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
346
		return false;
347
	decoder->private_->client_data = value;
348
349
350
	return true;
}

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
FLAC__bool FLAC__stream_decoder_set_metadata_respond(const FLAC__StreamDecoder *decoder, FLAC__MetaDataType type)
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	FLAC__ASSERT(type <= FLAC__METADATA_TYPE_VORBIS_COMMENT);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->metadata_filter[type] = true;
	if(type == FLAC__METADATA_TYPE_APPLICATION)
		decoder->private_->metadata_filter_ids_count = 0;
	return true;
}

FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(const FLAC__StreamDecoder *decoder, FLAC__byte id[4])
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;

	if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION])
		return true;

	FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids);

	if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) {
		if(0 == (decoder->private_->metadata_filter_ids = realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2)))
			return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
		decoder->private_->metadata_filter_ids_capacity *= 2;
	}

	memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
	decoder->private_->metadata_filter_ids_count++;

	return true;
}

FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(const FLAC__StreamDecoder *decoder)
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	/* OK, technically 0x01010101 != true, but it still means true */
	memset(decoder->private_->metadata_filter, 1, sizeof(decoder->private_->metadata_filter));
	decoder->private_->metadata_filter_ids_count = 0;
	return true;
}

FLAC__bool FLAC__stream_decoder_set_metadata_ignore(const FLAC__StreamDecoder *decoder, FLAC__MetaDataType type)
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	FLAC__ASSERT(type <= FLAC__METADATA_TYPE_VORBIS_COMMENT);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private_->metadata_filter[type] = false;
	if(type == FLAC__METADATA_TYPE_APPLICATION)
		decoder->private_->metadata_filter_ids_count = 0;
	return true;
}

FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(const FLAC__StreamDecoder *decoder, FLAC__byte id[4])
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;

	if(!decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION])
		return true;

	FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids);

	if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) {
		if(0 == (decoder->private_->metadata_filter_ids = realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2)))
			return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
		decoder->private_->metadata_filter_ids_capacity *= 2;
	}

	memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
	decoder->private_->metadata_filter_ids_count++;

	return true;
}

FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(const FLAC__StreamDecoder *decoder)
{
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter));
	decoder->private_->metadata_filter_ids_count = 0;
	return true;
}

454
FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder)
455
{
456
457
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
458
	return decoder->protected_->state;
459
460
}

461
unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
462
{
463
464
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
465
	return decoder->protected_->channels;
466
467
}

468
FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder)
469
{
470
471
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
472
	return decoder->protected_->channel_assignment;
473
474
}

475
unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)
476
{
477
478
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
479
	return decoder->protected_->bits_per_sample;
480
481
}

482
unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)
483
{
484
485
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
486
	return decoder->protected_->sample_rate;
487
488
}

489
unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder)
490
{
491
492
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
493
	return decoder->protected_->blocksize;
Josh Coalson's avatar
Josh Coalson committed
494
495
}

Josh Coalson's avatar
Josh Coalson committed
496
FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
497
{
498
	FLAC__ASSERT(decoder != 0);
499
500
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
Josh Coalson's avatar
Josh Coalson committed
501

502
	if(!FLAC__bitbuffer_clear(decoder->private_->input)) {
503
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
504
505
		return false;
	}
506
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
507
508
509
510

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
511
FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
512
{
513
	FLAC__ASSERT(decoder != 0);
514
515
	FLAC__ASSERT(decoder->private_ != 0);
	FLAC__ASSERT(decoder->protected_ != 0);
Josh Coalson's avatar
Josh Coalson committed
516
517

	if(!FLAC__stream_decoder_flush(decoder)) {
518
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
519
520
		return false;
	}
521
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
522

523
	decoder->private_->samples_decoded = 0;
Josh Coalson's avatar
Josh Coalson committed
524

Josh Coalson's avatar
Josh Coalson committed
525
526
527
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
528
FLAC__bool FLAC__stream_decoder_process_whole_stream(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
529
{
Josh Coalson's avatar
Josh Coalson committed
530
	FLAC__bool dummy;
531
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
532

533
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
534
535
		return true;

536
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
537
538

	if(!FLAC__stream_decoder_reset(decoder)) {
539
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
540
541
542
543
		return false;
	}

	while(1) {
544
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
			case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
				if(!stream_decoder_find_metadata_(decoder))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_READ_METADATA:
				if(!stream_decoder_read_metadata_(decoder))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
				if(!stream_decoder_frame_sync_(decoder))
					return true; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_READ_FRAME:
				if(!stream_decoder_read_frame_(decoder, &dummy))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
564
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
565
566
567
568
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
569
FLAC__bool FLAC__stream_decoder_process_metadata(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
570
{
571
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
572

573
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
574
575
		return true;

576
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
577
578

	if(!FLAC__stream_decoder_reset(decoder)) {
579
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
580
581
582
583
		return false;
	}

	while(1) {
584
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
585
586
587
588
589
590
591
592
593
594
			case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
				if(!stream_decoder_find_metadata_(decoder))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_READ_METADATA:
				if(!stream_decoder_read_metadata_(decoder))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
				return true;
595
596
			case FLAC__STREAM_DECODER_READ_FRAME:
				return true;
Josh Coalson's avatar
Josh Coalson committed
597
598
599
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
600
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
601
602
603
604
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
605
FLAC__bool FLAC__stream_decoder_process_one_frame(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
606
{
Josh Coalson's avatar
Josh Coalson committed
607
	FLAC__bool got_a_frame;
608
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
609

610
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
611
612
		return true;

613
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
614
615

	while(1) {
616
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
617
618
619
620
621
622
623
624
625
626
627
628
629
			case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
				if(!stream_decoder_frame_sync_(decoder))
					return true; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_READ_FRAME:
				if(!stream_decoder_read_frame_(decoder, &got_a_frame))
					return false; /* above function sets the status for us */
				if(got_a_frame)
					return true; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
630
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
631
632
633
634
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
635
FLAC__bool FLAC__stream_decoder_process_remaining_frames(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
636
{
Josh Coalson's avatar
Josh Coalson committed
637
	FLAC__bool dummy;
638
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
639

640
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
641
642
		return true;

643
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
644
645

	while(1) {
646
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
647
648
649
650
651
652
653
654
655
656
657
			case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
				if(!stream_decoder_frame_sync_(decoder))
					return true; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_READ_FRAME:
				if(!stream_decoder_read_frame_(decoder, &dummy))
					return false; /* above function sets the status for us */
				break;
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
658
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
659
660
661
662
		}
	}
}

663
664
665
666
667
668
/***********************************************************************
 *
 * Protected class methods
 *
 ***********************************************************************/

669
unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
670
{
671
	FLAC__ASSERT(decoder != 0);
672
	return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input);
Josh Coalson's avatar
Josh Coalson committed
673
674
}

675
676
677
678
679
680
/***********************************************************************
 *
 * Private class methods
 *
 ***********************************************************************/

Josh Coalson's avatar
Josh Coalson committed
681
FLAC__bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels)
Josh Coalson's avatar
Josh Coalson committed
682
683
{
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
684
	FLAC__int32 *tmp;
Josh Coalson's avatar
Josh Coalson committed
685

686
	if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels)
Josh Coalson's avatar
Josh Coalson committed
687
688
		return true;

689
690
	/* @@@ should change to use realloc() */

Josh Coalson's avatar
Josh Coalson committed
691
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
692
693
694
		if(decoder->private_->output[i] != 0) {
			free(decoder->private_->output[i]);
			decoder->private_->output[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
695
		}
696
697
698
		if(decoder->private_->residual[i] != 0) {
			free(decoder->private_->residual[i]);
			decoder->private_->residual[i] = 0;
699
		}
Josh Coalson's avatar
Josh Coalson committed
700
701
	}

702
	for(i = 0; i < channels; i++) {
703
704
		/* 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. */
		tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*(size+4));
Josh Coalson's avatar
Josh Coalson committed
705
		if(tmp == 0) {
706
			decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
707
708
			return false;
		}
709
		memset(tmp, 0, sizeof(FLAC__int32)*4);
710
		decoder->private_->output[i] = tmp + 4;
711

Josh Coalson's avatar
Josh Coalson committed
712
		tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*size);
713
		if(tmp == 0) {
714
			decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
715
716
			return false;
		}
717
		decoder->private_->residual[i] = tmp;
Josh Coalson's avatar
Josh Coalson committed
718
719
	}

720
721
	decoder->private_->output_capacity = size;
	decoder->private_->output_channels = channels;
Josh Coalson's avatar
Josh Coalson committed
722
723
724
725

	return true;
}

726
727
728
729
730
731
732
733
734
735
736
737
738
739
FLAC__bool stream_decoder_has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id)
{
	unsigned i;

	FLAC__ASSERT(0 != decoder);
	FLAC__ASSERT(0 != decoder->private_);

	for(i = 0; i < decoder->private_->metadata_filter_ids_count; i++)
		if(0 == memcmp(decoder->private_->metadata_filter_ids + i * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)))
			return true;

	return false;
}

Josh Coalson's avatar
Josh Coalson committed
740
FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
741
{
Josh Coalson's avatar
Josh Coalson committed
742
	FLAC__uint32 x;
Josh Coalson's avatar
Josh Coalson committed
743
	unsigned i, id;
Josh Coalson's avatar
Josh Coalson committed
744
	FLAC__bool first = true;
Josh Coalson's avatar
Josh Coalson committed
745

746
	FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
Josh Coalson's avatar
Josh Coalson committed
747
748

	for(i = id = 0; i < 4; ) {
749
750
751
		if(decoder->private_->cached) {
			x = (FLAC__uint32)decoder->private_->lookahead;
			decoder->private_->cached = false;
752
753
		}
		else {
754
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
755
756
				return false; /* the read_callback_ sets the state for us */
		}
Josh Coalson's avatar
Josh Coalson committed
757
		if(x == FLAC__STREAM_SYNC_STRING[i]) {
758
			first = true;
Josh Coalson's avatar
Josh Coalson committed
759
760
761
762
763
764
765
766
767
768
769
770
771
772
			i++;
			id = 0;
			continue;
		}
		if(x == ID3V2_TAG_[id]) {
			id++;
			i = 0;
			if(id == 3) {
				if(!stream_decoder_skip_id3v2_tag_(decoder))
					return false; /* the read_callback_ sets the state for us */
			}
			continue;
		}
		if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
773
			decoder->private_->header_warmup[0] = (FLAC__byte)x;
774
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
775
				return false; /* the read_callback_ sets the state for us */
776
777
778
779

			/* 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 */
			/* else we have to check if the second byte is the end of a sync code */
			if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
780
781
				decoder->private_->lookahead = (FLAC__byte)x;
				decoder->private_->cached = true;
782
783
			}
			else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */
784
785
				decoder->private_->header_warmup[1] = (FLAC__byte)x;
				decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME;
Josh Coalson's avatar
Josh Coalson committed
786
787
788
789
790
				return true;
			}
		}
		i = 0;
		if(first) {
791
			decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private_->client_data);
792
			first = false;
Josh Coalson's avatar
Josh Coalson committed
793
794
795
		}
	}

796
	decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA;
Josh Coalson's avatar
Josh Coalson committed
797
798
799
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
800
FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
801
{
Josh Coalson's avatar
Josh Coalson committed
802
803
	FLAC__uint32 i, x, last_block, type, length;
	FLAC__uint64 xx;
Josh Coalson's avatar
Josh Coalson committed
804

805
	FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
Josh Coalson's avatar
Josh Coalson committed
806

807
	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &last_block, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
808
		return false; /* the read_callback_ sets the state for us */
809
	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
810
		return false; /* the read_callback_ sets the state for us */
811
	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
812
		return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
813
	if(type == FLAC__METADATA_TYPE_STREAMINFO) {
814
		unsigned used_bits = 0;
815
816
817
		decoder->private_->stream_info.type = type;
		decoder->private_->stream_info.is_last = last_block;
		decoder->private_->stream_info.length = length;
818

819
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
820
			return false; /* the read_callback_ sets the state for us */
821
		decoder->private_->stream_info.data.stream_info.min_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
822
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
823

824
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
825
			return false; /* the read_callback_ sets the state for us */
826
		decoder->private_->stream_info.data.stream_info.max_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
827
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
828

829
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
830
			return false; /* the read_callback_ sets the state for us */
831
		decoder->private_->stream_info.data.stream_info.min_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
832
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
833

834
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
835
			return false; /* the read_callback_ sets the state for us */
836
		decoder->private_->stream_info.data.stream_info.max_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
837
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
838

839
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
840
			return false; /* the read_callback_ sets the state for us */
841
		decoder->private_->stream_info.data.stream_info.sample_rate = x;
Josh Coalson's avatar
Josh Coalson committed
842
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
843

844
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
845
			return false; /* the read_callback_ sets the state for us */
846
		decoder->private_->stream_info.data.stream_info.channels = x+1;
Josh Coalson's avatar
Josh Coalson committed
847
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
848

849
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
850
			return false; /* the read_callback_ sets the state for us */
851
		decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1;
Josh Coalson's avatar
Josh Coalson committed
852
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
853

854
		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))
Josh Coalson's avatar
Josh Coalson committed
855
			return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
856
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
857

858
859
860
		if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16, read_callback_, decoder))
			return false; /* the read_callback_ sets the state for us */
		used_bits += 16*8;
Josh Coalson's avatar
Josh Coalson committed
861

862
		/* skip the rest of the block */
863
		FLAC__ASSERT(used_bits % 8 == 0);
864
		length -= (used_bits / 8);
865
866
		if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, 0, length, read_callback_, decoder))
			return false; /* the read_callback_ sets the state for us */
867

868
		decoder->private_->has_stream_info = true;
869
870
		if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO])
			decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data);
871
872
	}
	else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
873
874
		unsigned real_points;

875
876
877
		decoder->private_->seek_table.type = type;
		decoder->private_->seek_table.is_last = last_block;
		decoder->private_->seek_table.length = length;
878

Josh Coalson's avatar
Josh Coalson committed
879
		decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
880

881
882
		if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetaData_SeekPoint*)malloc(decoder->private_->seek_table.data.seek_table.num_points * sizeof(FLAC__StreamMetaData_SeekPoint)))) {
			decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
883
884
			return false;
		}
885
		for(i = real_points = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) {
886
			if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
887
				return false; /* the read_callback_ sets the state for us */
888
			decoder->private_->seek_table.data.seek_table.points[real_points].sample_number = xx;
889

890
			if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder))
891
				return false; /* the read_callback_ sets the state for us */
892
			decoder->private_->seek_table.data.seek_table.points[real_points].stream_offset = xx;
893

894
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder))
895
				return false; /* the read_callback_ sets the state for us */
896
			decoder->private_->seek_table.data.seek_table.points[real_points].frame_samples = x;
Josh Coalson's avatar
Josh Coalson committed
897

898
			if(decoder->private_->seek_table.data.seek_table.points[real_points].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER)
Josh Coalson's avatar
Josh Coalson committed
899
				real_points++;
900
		}
901
		length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH);
902
		decoder->private_->seek_table.data.seek_table.num_points = real_points;
903

904
905
906
907
908
909
910
		/* if there is a partial point left, skip over it */
		if(length > 0) {
			/*@@@ do an error_callback() here?  there's an argument for either way */
			if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, 0, length, read_callback_, decoder))
				return false; /* the read_callback_ sets the state for us */
		}

911
		decoder->private_->has_seek_table = true;
912
913
		if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE])
			decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data);
Josh Coalson's avatar
Josh Coalson committed
914
915
	}
	else {
916
917
918
919
920
921
922
923
		FLAC__bool skip_it = !decoder->private_->metadata_filter[type];
		unsigned real_length = length;
		FLAC__StreamMetaData block;

		block.is_last = last_block;
		block.type = type;
		block.length = length;

924
		if(type == FLAC__METADATA_TYPE_APPLICATION) {
925
926
927
928
929
			if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder))
				return false; /* the read_callback_ sets the state for us */

			real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;

930
			if(decoder->private_->metadata_filter_ids_count > 0 && stream_decoder_has_id_filtered_(decoder, block.data.application.id))
931
932
933
934
935
				skip_it = !skip_it;
		}

		if(skip_it) {
			if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, 0, real_length, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
936
937
				return false; /* the read_callback_ sets the state for us */
		}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
		else {
			switch(type) {
				case FLAC__METADATA_TYPE_PADDING:
					/* skip the padding bytes */
					if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, 0, real_length, read_callback_, decoder))
						return false; /* the read_callback_ sets the state for us */
					break;
				case FLAC__METADATA_TYPE_APPLICATION:
					/* remember, we read the ID already */
					if(0 == (block.data.application.data = malloc(real_length))) {
						decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
						return false;
					}
					if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, block.data.application.data, real_length, read_callback_, decoder))
						return false; /* the read_callback_ sets the state for us */
					break;
				case FLAC__METADATA_TYPE_VORBIS_COMMENT:
					/* read vendor string */
					if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &block.data.vorbis_comment.vendor_string.length, FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, read_callback_, decoder))
						return false; /* the read_callback_ sets the state for us */
					if(block.data.vorbis_comment.vendor_string.length > 0) {
						if(0 == (block.data.vorbis_comment.vendor_string.entry = malloc(block.data.vorbis_comment.vendor_string.length))) {
							decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
							return false;
						}
						if(!FLAC__bitbuffer_read_byte_block_aligned(decoder->private_->input, block.data.vorbis_comment.vendor_string.entry, block.data.vorbis_comment.vendor_string.length, read_callback_, decoder))
							return false; /* the read_callback_ sets the state for us */
					}
					else
						block.data.vorbis_comment.vendor_string.entry = 0;

					/* read num comments */
					if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &block.data.vorbis_comment.num_comments, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN, read_callback_, decoder))
						return false; /* the read_callback_ sets the state for us */

					/* read comments */
					if(block.data.vorbis_comment.num_comments > 0) {
						if(0 <