stream_decoder.c 55.8 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
Josh Coalson's avatar
Josh Coalson committed
2
 * Copyright (C) 2000,2001  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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/***********************************************************************
 *
 * Private static data
 *
 ***********************************************************************/

static byte ID3V2_TAG_[3] = { 'I', 'D', '3' };

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

static bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels);
static bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder);
static bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder);
static bool stream_decoder_skip_id3v2_tag_(FLAC__StreamDecoder *decoder);
static bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder);
static bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, bool *got_a_frame);
static bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder);
static bool stream_decoder_read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
static bool stream_decoder_read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
static bool stream_decoder_read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
static bool stream_decoder_read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
static bool stream_decoder_read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
static bool stream_decoder_read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, int32 *residual);
static bool stream_decoder_read_zero_padding_(FLAC__StreamDecoder *decoder);
static bool read_callback_(byte buffer[], unsigned *bytes, void *client_data);

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

Josh Coalson's avatar
Josh Coalson committed
67
68
typedef struct FLAC__StreamDecoderPrivate {
	FLAC__StreamDecoderReadStatus (*read_callback)(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data);
69
	FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
Josh Coalson's avatar
Josh Coalson committed
70
71
	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);
72
	void (*local_lpc_restore_signal)(const int32 residual[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 data[]);
73
	void (*local_lpc_restore_signal_16bit)(const int32 residual[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 data[]);
Josh Coalson's avatar
Josh Coalson committed
74
75
76
	void *client_data;
	FLAC__BitBuffer input;
	int32 *output[FLAC__MAX_CHANNELS];
77
	int32 *residual[FLAC__MAX_CHANNELS];
78
	unsigned output_capacity, output_channels;
Josh Coalson's avatar
Josh Coalson committed
79
80
	uint32 last_frame_number;
	uint64 samples_decoded;
81
82
83
	bool has_stream_info, has_seek_table;
	FLAC__StreamMetaData stream_info;
	FLAC__StreamMetaData seek_table;
84
	FLAC__Frame frame;
85
86
	bool cached; /* true if there is a byte in lookahead */
	FLAC__CPUInfo cpuinfo;
87
88
	byte header_warmup[2]; /* contains the sync code and reserved bits */
	byte lookahead; /* temp storage when we need to look ahead one byte in the stream */
Josh Coalson's avatar
Josh Coalson committed
89
90
} FLAC__StreamDecoderPrivate;

91
92
93
94
95
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/
Josh Coalson's avatar
Josh Coalson committed
96

Josh Coalson's avatar
Josh Coalson committed
97
98
99
100
101
102
103
104
105
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",
106
	"FLAC__STREAM_DECODER_ALREADY_INITIALIZED",
107
	"FLAC__STREAM_DECODER_INVALID_CALLBACK",
Josh Coalson's avatar
Josh Coalson committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	"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[] = {
123
124
125
	"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
126
127
};

128
129
130
131
132
133
/***********************************************************************
 *
 * Class constructor/destructor
 *
 ***********************************************************************/
FLAC__StreamDecoder *FLAC__stream_decoder_new()
Josh Coalson's avatar
Josh Coalson committed
134
{
135
136
137
138
139
140
141
	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
142
	}
143
144
145
146
147
148
149
150
151
152
153
154
155
156
	decoder->protected = (FLAC__StreamDecoderProtected*)malloc(sizeof(FLAC__StreamDecoderProtected));
	if(decoder->protected == 0) {
		free(decoder);
		return 0;
	}
	decoder->private = (FLAC__StreamDecoderPrivate*)malloc(sizeof(FLAC__StreamDecoderPrivate));
	if(decoder->private == 0) {
		free(decoder->protected);
		free(decoder);
		return 0;
	}

	decoder->protected->state = FLAC__STREAM_DECODER_UNINITIALIZED;

157
158
159
160
161
162
	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;

Josh Coalson's avatar
Josh Coalson committed
163
164
165
	return decoder;
}

166
void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
167
{
168
169
170
171
172
173
	FLAC__ASSERT(decoder != 0);
	FLAC__ASSERT(decoder->protected != 0);
	FLAC__ASSERT(decoder->private != 0);

	free(decoder->private);
	free(decoder->protected);
Josh Coalson's avatar
Josh Coalson committed
174
175
176
	free(decoder);
}

177
178
179
180
181
182
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

183
FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
184
185
186
{
	unsigned i;

187
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
188

189
190
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return decoder->protected->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED;
Josh Coalson's avatar
Josh Coalson committed
191

192
	decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
193

194
195
	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
196

197
	FLAC__bitbuffer_init(&decoder->private->input);
Josh Coalson's avatar
Josh Coalson committed
198

199
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
200
201
		decoder->private->output[i] = 0;
		decoder->private->residual[i] = 0;
202
	}
Josh Coalson's avatar
Josh Coalson committed
203

204
205
206
207
208
209
210
	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;
	decoder->private->cached = false;
Josh Coalson's avatar
Josh Coalson committed
211

212
213
214
	/*
	 * get the CPU info and set the function pointers
	 */
215
	FLAC__cpu_info(&decoder->private->cpuinfo);
216
	/* first default to the non-asm routines */
217
218
	decoder->private->local_lpc_restore_signal = FLAC__lpc_restore_signal;
	decoder->private->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal;
219
	/* now override with asm where appropriate */
220
#ifndef FLAC__NO_ASM
221
	FLAC__ASSERT(decoder->private->cpuinfo.use_asm);
222
#ifdef FLAC__CPU_IA32
223
	FLAC__ASSERT(decoder->private->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
224
#ifdef FLAC__HAS_NASM
225
	if(decoder->private->cpuinfo.data.ia32.mmx) {
Josh Coalson's avatar
Josh Coalson committed
226
227
		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;
228
229
	}
	else {
Josh Coalson's avatar
Josh Coalson committed
230
231
		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;
232
	}
233
#endif
234
#endif
235
236
#endif

237
	return decoder->protected->state;
Josh Coalson's avatar
Josh Coalson committed
238
239
240
241
242
}

void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
{
	unsigned i;
243
	FLAC__ASSERT(decoder != 0);
244
	if(decoder->protected->state == FLAC__STREAM_DECODER_UNINITIALIZED)
Josh Coalson's avatar
Josh Coalson committed
245
		return;
246
247
248
249
250
251
252
253
254
	if(decoder->private->has_seek_table) {
		free(decoder->private->seek_table.data.seek_table.points);
		decoder->private->seek_table.data.seek_table.points = 0;
	}
	FLAC__bitbuffer_free(&decoder->private->input);
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
		if(decoder->private->output[i] != 0) {
			free(decoder->private->output[i]);
			decoder->private->output[i] = 0;
255
		}
256
257
258
		if(decoder->private->residual[i] != 0) {
			free(decoder->private->residual[i]);
			decoder->private->residual[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
259
260
		}
	}
261
262
263
	decoder->protected->state = FLAC__STREAM_DECODER_UNINITIALIZED;
}

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
bool FLAC__stream_decoder_set_read_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadStatus (*value)(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data))
{
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private->read_callback = value;
	return true;
}

bool FLAC__stream_decoder_set_write_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteStatus (*value)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data))
{
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private->write_callback = value;
	return true;
}

bool FLAC__stream_decoder_set_metadata_callback(const FLAC__StreamDecoder *decoder, void (*value)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data))
{
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private->metadata_callback = value;
	return true;
}

bool FLAC__stream_decoder_set_error_callback(const FLAC__StreamDecoder *decoder, void (*value)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data))
{
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private->error_callback = value;
	return true;
}

bool FLAC__stream_decoder_set_client_data(const FLAC__StreamDecoder *decoder, void *value)
{
	if(decoder->protected->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return false;
	decoder->private->client_data = value;
	return true;
}

FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder)
305
306
307
308
{
	return decoder->protected->state;
}

309
unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
310
311
312
313
{
	return decoder->protected->channels;
}

314
FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder)
315
316
317
318
{
	return decoder->protected->channel_assignment;
}

319
unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)
320
321
322
323
{
	return decoder->protected->bits_per_sample;
}

324
unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)
325
326
327
328
{
	return decoder->protected->sample_rate;
}

329
unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder)
330
331
{
	return decoder->protected->blocksize;
Josh Coalson's avatar
Josh Coalson committed
332
333
334
335
}

bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
{
336
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
337

338
339
	if(!FLAC__bitbuffer_clear(&decoder->private->input)) {
		decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
340
341
342
343
344
345
346
347
		return false;
	}

	return true;
}

bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
{
348
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
349
350

	if(!FLAC__stream_decoder_flush(decoder)) {
351
		decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
352
353
		return false;
	}
354
	decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
355

356
	decoder->private->samples_decoded = 0;
Josh Coalson's avatar
Josh Coalson committed
357

Josh Coalson's avatar
Josh Coalson committed
358
359
360
361
362
363
	return true;
}

bool FLAC__stream_decoder_process_whole_stream(FLAC__StreamDecoder *decoder)
{
	bool dummy;
364
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
365

366
	if(decoder->protected->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
367
368
		return true;

369
	FLAC__ASSERT(decoder->protected->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
370
371

	if(!FLAC__stream_decoder_reset(decoder)) {
372
		decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
373
374
375
376
		return false;
	}

	while(1) {
377
		switch(decoder->protected->state) {
Josh Coalson's avatar
Josh Coalson committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
			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:
397
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
398
399
400
401
402
403
		}
	}
}

bool FLAC__stream_decoder_process_metadata(FLAC__StreamDecoder *decoder)
{
404
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
405

406
	if(decoder->protected->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
407
408
		return true;

409
	FLAC__ASSERT(decoder->protected->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
410
411

	if(!FLAC__stream_decoder_reset(decoder)) {
412
		decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
413
414
415
416
		return false;
	}

	while(1) {
417
		switch(decoder->protected->state) {
Josh Coalson's avatar
Josh Coalson committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431
			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;
				break;
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
432
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
433
434
435
436
437
438
439
		}
	}
}

bool FLAC__stream_decoder_process_one_frame(FLAC__StreamDecoder *decoder)
{
	bool got_a_frame;
440
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
441

442
	if(decoder->protected->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
443
444
		return true;

445
	FLAC__ASSERT(decoder->protected->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
446
447

	while(1) {
448
		switch(decoder->protected->state) {
Josh Coalson's avatar
Josh Coalson committed
449
450
451
452
453
454
455
456
457
458
459
460
461
			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:
462
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
463
464
465
466
467
468
469
		}
	}
}

bool FLAC__stream_decoder_process_remaining_frames(FLAC__StreamDecoder *decoder)
{
	bool dummy;
470
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
471

472
	if(decoder->protected->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
473
474
		return true;

475
	FLAC__ASSERT(decoder->protected->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
476
477

	while(1) {
478
		switch(decoder->protected->state) {
Josh Coalson's avatar
Josh Coalson committed
479
480
481
482
483
484
485
486
487
488
489
			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:
490
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
491
492
493
494
		}
	}
}

495
496
497
498
499
500
/***********************************************************************
 *
 * Protected class methods
 *
 ***********************************************************************/

501
unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
502
{
503
	FLAC__ASSERT(decoder != 0);
504
	return decoder->private->input.bytes - decoder->private->input.consumed_bytes;
Josh Coalson's avatar
Josh Coalson committed
505
506
}

507
508
509
510
511
512
/***********************************************************************
 *
 * Private class methods
 *
 ***********************************************************************/

513
bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels)
Josh Coalson's avatar
Josh Coalson committed
514
515
516
517
{
	unsigned i;
	int32 *tmp;

518
	if(size <= decoder->private->output_capacity && channels <= decoder->private->output_channels)
Josh Coalson's avatar
Josh Coalson committed
519
520
		return true;

521
522
	/* @@@ should change to use realloc() */

Josh Coalson's avatar
Josh Coalson committed
523
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
524
525
526
		if(decoder->private->output[i] != 0) {
			free(decoder->private->output[i]);
			decoder->private->output[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
527
		}
528
529
530
		if(decoder->private->residual[i] != 0) {
			free(decoder->private->residual[i]);
			decoder->private->residual[i] = 0;
531
		}
Josh Coalson's avatar
Josh Coalson committed
532
533
	}

534
	for(i = 0; i < channels; i++) {
Josh Coalson's avatar
Josh Coalson committed
535
536
		tmp = (int32*)malloc(sizeof(int32)*size);
		if(tmp == 0) {
537
			decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
538
539
			return false;
		}
540
		decoder->private->output[i] = tmp;
541
542
543

		tmp = (int32*)malloc(sizeof(int32)*size);
		if(tmp == 0) {
544
			decoder->protected->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
545
546
			return false;
		}
547
		decoder->private->residual[i] = tmp;
Josh Coalson's avatar
Josh Coalson committed
548
549
	}

550
551
	decoder->private->output_capacity = size;
	decoder->private->output_channels = channels;
Josh Coalson's avatar
Josh Coalson committed
552
553
554
555
556
557
558
559

	return true;
}

bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
{
	uint32 x;
	unsigned i, id;
560
	bool first = true;
Josh Coalson's avatar
Josh Coalson committed
561

562
	FLAC__ASSERT(decoder->private->input.consumed_bits == 0); /* make sure we're byte aligned */
Josh Coalson's avatar
Josh Coalson committed
563
564

	for(i = id = 0; i < 4; ) {
565
566
567
		if(decoder->private->cached) {
			x = (uint32)decoder->private->lookahead;
			decoder->private->cached = false;
568
569
		}
		else {
570
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
571
572
				return false; /* the read_callback_ sets the state for us */
		}
Josh Coalson's avatar
Josh Coalson committed
573
		if(x == FLAC__STREAM_SYNC_STRING[i]) {
574
			first = true;
Josh Coalson's avatar
Josh Coalson committed
575
576
577
578
579
580
581
582
583
584
585
586
587
588
			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 */
589
590
			decoder->private->header_warmup[0] = (byte)x;
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
591
				return false; /* the read_callback_ sets the state for us */
592
593
594
595

			/* 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 */
596
597
				decoder->private->lookahead = (byte)x;
				decoder->private->cached = true;
598
599
			}
			else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */
600
601
				decoder->private->header_warmup[1] = (byte)x;
				decoder->protected->state = FLAC__STREAM_DECODER_READ_FRAME;
Josh Coalson's avatar
Josh Coalson committed
602
603
604
605
606
				return true;
			}
		}
		i = 0;
		if(first) {
607
			decoder->private->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private->client_data);
608
			first = false;
Josh Coalson's avatar
Josh Coalson committed
609
610
611
		}
	}

612
	decoder->protected->state = FLAC__STREAM_DECODER_READ_METADATA;
Josh Coalson's avatar
Josh Coalson committed
613
614
615
616
617
618
	return true;
}

bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
{
	uint32 i, x, last_block, type, length;
619
	uint64 xx;
Josh Coalson's avatar
Josh Coalson committed
620

621
	FLAC__ASSERT(decoder->private->input.consumed_bits == 0); /* make sure we're byte aligned */
Josh Coalson's avatar
Josh Coalson committed
622

623
	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
624
		return false; /* the read_callback_ sets the state for us */
625
	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
626
		return false; /* the read_callback_ sets the state for us */
627
	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
628
		return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
629
	if(type == FLAC__METADATA_TYPE_STREAMINFO) {
630
		unsigned used_bits = 0;
631
632
633
		decoder->private->stream_info.type = type;
		decoder->private->stream_info.is_last = last_block;
		decoder->private->stream_info.length = length;
634

635
		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
636
			return false; /* the read_callback_ sets the state for us */
637
		decoder->private->stream_info.data.stream_info.min_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
638
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
639

640
		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
641
			return false; /* the read_callback_ sets the state for us */
642
		decoder->private->stream_info.data.stream_info.max_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
643
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
644

645
		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
646
			return false; /* the read_callback_ sets the state for us */
647
		decoder->private->stream_info.data.stream_info.min_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
648
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
649

650
		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
651
			return false; /* the read_callback_ sets the state for us */
652
		decoder->private->stream_info.data.stream_info.max_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
653
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
654

655
		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
656
			return false; /* the read_callback_ sets the state for us */
657
		decoder->private->stream_info.data.stream_info.sample_rate = x;
Josh Coalson's avatar
Josh Coalson committed
658
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
659

660
		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
661
			return false; /* the read_callback_ sets the state for us */
662
		decoder->private->stream_info.data.stream_info.channels = x+1;
Josh Coalson's avatar
Josh Coalson committed
663
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
664

665
		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
666
			return false; /* the read_callback_ sets the state for us */
667
		decoder->private->stream_info.data.stream_info.bits_per_sample = x+1;
Josh Coalson's avatar
Josh Coalson committed
668
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
669

670
		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
671
			return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
672
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
673

Josh Coalson's avatar
Josh Coalson committed
674
		for(i = 0; i < 16; i++) {
675
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
676
				return false; /* the read_callback_ sets the state for us */
677
			decoder->private->stream_info.data.stream_info.md5sum[i] = (byte)x;
Josh Coalson's avatar
Josh Coalson committed
678
		}
679
		used_bits += i*8;
Josh Coalson's avatar
Josh Coalson committed
680

681
		/* skip the rest of the block */
682
		FLAC__ASSERT(used_bits % 8 == 0);
683
684
		length -= (used_bits / 8);
		for(i = 0; i < length; i++) {
685
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
686
687
688
				return false; /* the read_callback_ sets the state for us */
		}

689
690
		decoder->private->has_stream_info = true;
		decoder->private->metadata_callback(decoder, &decoder->private->stream_info, decoder->private->client_data);
691
692
	}
	else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
693
694
		unsigned real_points;

695
696
697
		decoder->private->seek_table.type = type;
		decoder->private->seek_table.is_last = last_block;
		decoder->private->seek_table.length = length;
698

699
		decoder->private->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LEN;
700

701
702
		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;
703
704
			return false;
		}
705
706
		for(i = real_points = 0; i < decoder->private->seek_table.data.seek_table.num_points; i++) {
			if(!FLAC__bitbuffer_read_raw_uint64(&decoder->private->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
707
				return false; /* the read_callback_ sets the state for us */
708
			decoder->private->seek_table.data.seek_table.points[real_points].sample_number = xx;
709

710
			if(!FLAC__bitbuffer_read_raw_uint64(&decoder->private->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder))
711
				return false; /* the read_callback_ sets the state for us */
712
			decoder->private->seek_table.data.seek_table.points[real_points].stream_offset = xx;
713

714
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder))
715
				return false; /* the read_callback_ sets the state for us */
716
			decoder->private->seek_table.data.seek_table.points[real_points].frame_samples = x;
Josh Coalson's avatar
Josh Coalson committed
717

718
			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
719
				real_points++;
720
		}
721
		decoder->private->seek_table.data.seek_table.num_points = real_points;
722

723
724
		decoder->private->has_seek_table = true;
		decoder->private->metadata_callback(decoder, &decoder->private->seek_table, decoder->private->client_data);
Josh Coalson's avatar
Josh Coalson committed
725
726
727
728
	}
	else {
		/* skip other metadata blocks */
		for(i = 0; i < length; i++) {
729
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
730
731
732
733
734
				return false; /* the read_callback_ sets the state for us */
		}
	}

	if(last_block)
735
		decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
736
737
738
739
740
741
742
743
744
745

	return true;
}

bool stream_decoder_skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
{
	uint32 x;
	unsigned i, skip;

	/* skip the version and flags bytes */
746
	if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 24, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
747
748
749
750
		return false; /* the read_callback_ sets the state for us */
	/* get the size (in bytes) to skip */
	skip = 0;
	for(i = 0; i < 4; i++) {
751
		if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
752
753
754
755
756
757
			return false; /* the read_callback_ sets the state for us */
		skip <<= 7;
		skip |= (x & 0x7f);
	}
	/* skip the rest of the tag */
	for(i = 0; i < skip; i++) {
758
		if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
759
760
761
762
763
764
765
766
			return false; /* the read_callback_ sets the state for us */
	}
	return true;
}

bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder)
{
	uint32 x;
767
	bool first = true;
Josh Coalson's avatar
Josh Coalson committed
768
769
770

	/* If we know the total number of samples in the stream, stop if we've read that many. */
	/* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */
771
772
773
	if(decoder->private->has_stream_info && decoder->private->stream_info.data.stream_info.total_samples) {
		if(decoder->private->samples_decoded >= decoder->private->stream_info.data.stream_info.total_samples) {
			decoder->protected->state = FLAC__STREAM_DECODER_END_OF_STREAM;
Josh Coalson's avatar
Josh Coalson committed
774
775
776
777
778
			return true;
		}
	}

	/* make sure we're byte aligned */
779
780
	if(decoder->private->input.consumed_bits != 0) {
		if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8-decoder->private->input.consumed_bits, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
781
782
783
784
			return false; /* the read_callback_ sets the state for us */
	}

	while(1) {
785
786
787
		if(decoder->private->cached) {
			x = (uint32)decoder->private->lookahead;
			decoder->private->cached = false;
788
789
		}
		else {
790
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
791
792
				return false; /* the read_callback_ sets the state for us */
		}
Josh Coalson's avatar
Josh Coalson committed
793
		if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
794
795
			decoder->private->header_warmup[0] = (byte)x;
			if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
796
				return false; /* the read_callback_ sets the state for us */
797
798
799
800

			/* 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 */
801
802
				decoder->private->lookahead = (byte)x;
				decoder->private->cached = true;
803
804
			}
			else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */
805
806
				decoder->private->header_warmup[1] = (byte)x;
				decoder->protected->state = FLAC__STREAM_DECODER_READ_FRAME;
Josh Coalson's avatar
Josh Coalson committed
807
808
809
810
				return true;
			}
		}
		if(first) {
811
			decoder->private->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private->client_data);
Josh Coalson's avatar
Josh Coalson committed
812
813
814
815
816
817
818
819
820
821
822
823
			first = 0;
		}
	}

	return true;
}

bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, bool *got_a_frame)
{
	unsigned channel;
	unsigned i;
	int32 mid, side, left, right;
824
825
	uint16 frame_crc; /* the one we calculate from the input stream */
	uint32 x;
Josh Coalson's avatar
Josh Coalson committed
826
827
828

	*got_a_frame = false;

829
830
	/* init the CRC */
	frame_crc = 0;
831
832
833
	FLAC__CRC16_UPDATE(decoder->private->header_warmup[0], frame_crc);
	FLAC__CRC16_UPDATE(decoder->private->header_warmup[1], frame_crc);
	FLAC__bitbuffer_init_read_crc16(&decoder->private->input, frame_crc);
834

Josh Coalson's avatar
Josh Coalson committed
835
836
	if(!stream_decoder_read_frame_header_(decoder))
		return false;
837
	if(decoder->protected->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC)
Josh Coalson's avatar
Josh Coalson committed
838
		return true;
839
	if(!stream_decoder_allocate_output_(decoder, decoder->private->frame.header.blocksize, decoder->private->frame.header.channels))
Josh Coalson's avatar
Josh Coalson committed
840
		return false;
841
	for(channel = 0; channel < decoder->private->frame.header.channels; channel++) {
842
843
844
		/*
		 * first figure the correct bits-per-sample of the subframe
		 */
845
846
		unsigned bps = decoder->private->frame.header.bits_per_sample;
		switch(decoder->private->frame.header.channel_assignment) {
847
848
849
850
			case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
				/* no adjustment needed */
				break;
			case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
851
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
852
853
854
855
				if(channel == 1)
					bps++;
				break;
			case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
856
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
857
858
859
860
				if(channel == 0)
					bps++;
				break;
			case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
861
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
862
863
864
865
				if(channel == 1)
					bps++;
				break;
			default:
866
				FLAC__ASSERT(0);
867
868
869
870
871
		}
		/*
		 * now read it
		 */
		if(!stream_decoder_read_subframe_(decoder, channel, bps))
Josh Coalson's avatar
Josh Coalson committed
872
			return false;
873
874
		if(decoder->protected->state != FLAC__STREAM_DECODER_READ_FRAME) {
			decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
875
876
877
878
879
880
			return true;
		}
	}
	if(!stream_decoder_read_zero_padding_(decoder))
		return false;

881
882
883
	/*
	 * Read the frame CRC-16 from the footer and check
	 */
884
885
	frame_crc = decoder->private->input.read_crc16;
	if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder))
886
887
888
		return false; /* the read_callback_ sets the state for us */
	if(frame_crc == (uint16)x) {
		/* Undo any special channel coding */
889
		switch(decoder->private->frame.header.channel_assignment) {
890
891
892
893
			case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
				/* do nothing */
				break;
			case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
894
895
896
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
				for(i = 0; i < decoder->private->frame.header.blocksize; i++)
					decoder->private->output[1][i] = decoder->private->output[0][i] - decoder->private->output[1][i];
897
898
				break;
			case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
899
900
901
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
				for(i = 0; i < decoder->private->frame.header.blocksize; i++)
					decoder->private->output[0][i] += decoder->private->output[1][i];
902
903
				break;
			case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
904
905
906
907
				FLAC__ASSERT(decoder->private->frame.header.channels == 2);
				for(i = 0; i < decoder->private->frame.header.blocksize; i++) {
					mid = decoder->private->output[0][i];
					side = decoder->private->output[1][i];
908
909
910
911
912
					mid <<= 1;
					if(side & 1) /* i.e. if 'side' is odd... */
						mid++;
					left = mid + side;
					right = mid - side;
913
914
					decoder->private->output[0][i] = left >> 1;
					decoder->private->output[1][i] = right >> 1;
915
916
917
				}
				break;
			default:
918
				FLAC__ASSERT(0);
919
920
921
922
923
				break;
		}
	}
	else {
		/* Bad frame, emit error and zero the output signal */
924
925
926
		decoder->private->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_FRAME_CRC_MISMATCH, decoder->private->client_data);
		for(channel = 0; channel < decoder->private->frame.header.channels; channel++) {
			memset(decoder->private->output[channel], 0, sizeof(int32) * decoder->private->frame.header.blocksize);
927
		}
Josh Coalson's avatar
Josh Coalson committed
928
929
930
931
932
	}

	*got_a_frame = true;

	/* put the latest values into the public section of the decoder instance */
933
934
935
936
937
	decoder->protected->channels = decoder->private->frame.header.channels;
	decoder->protected->channel_assignment = decoder->private->frame.header.channel_assignment;
	decoder->protected->bits_per_sample = decoder->private->frame.header.bits_per_sample;
	decoder->protected->sample_rate = decoder->private->frame.header.sample_rate;
	decoder->protected->blocksize = decoder->private->frame.header.blocksize;
Josh Coalson's avatar
Josh Coalson committed
938

939
	decoder->private->samples_decoded = decoder->private->frame.header.number.sample_number + decoder->private->frame.header.blocksize;
Josh Coalson's avatar
Josh Coalson committed
940
941

	/* write it */
942
	/* NOTE: some versions of GCC can't figure out const-ness right and will give you an 'incompatible pointer type' warning on arg 3 here: */
943
	if(decoder->private->write_callback(decoder, &decoder->private->frame, decoder->private->output, decoder->private->client_data) != FLAC__STREAM_DECODER_WRITE_CONTINUE)
Josh Coalson's avatar
Josh Coalson committed
944
945
		return false;

946
	decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
947
948
949
950
951
952
953
954
	return true;
}

bool stream_decoder_read_frame_header_(FLAC__StreamDecoder *decoder)
{
	uint32 x;
	uint64 xx;
	unsigned i, blocksize_hint = 0, sample_rate_hint = 0;
955
	byte crc8, raw_header[16]; /* MAGIC NUMBER based on the maximum frame header size, including CRC */
Josh Coalson's avatar
Josh Coalson committed
956
957
	unsigned raw_header_len;
	bool is_unparseable = false;
958
959
	const bool is_known_variable_blocksize_stream = (decoder->private->has_stream_info && decoder->private->stream_info.data.stream_info.min_blocksize != decoder->private->stream_info.data.stream_info.max_blocksize);
	const bool is_known_fixed_blocksize_stream = (decoder->private->has_stream_info && decoder->private->stream_info.data.stream_info.min_blocksize == decoder->private->stream_info.data.stream_info.max_blocksize);
Josh Coalson's avatar
Josh Coalson committed
960

961
	FLAC__ASSERT(decoder->private->input.consumed_bits == 0); /* make sure we're byte aligned */
Josh Coalson's avatar
Josh Coalson committed
962

963
	/* init the raw header with the saved bits from synchronization */
964
965
	raw_header[0] = decoder->private->header_warmup[0];
	raw_header[1] = decoder->private->header_warmup[1];
966
967
968
969
970
971
972
973
974
975
976
977
978
979
	raw_header_len = 2;

	/*
	 * check to make sure that the reserved bits are 0
	 */
	if(raw_header[1] & 0x03) { /* MAGIC NUMBER */
		is_unparseable = true;
	}

	/*
	 * Note that along the way as we read the header, we look for a sync
	 * code inside.  If we find one it would indicate that our original
	 * sync was bad since there cannot be a sync code in a valid header.
	 */
Josh Coalson's avatar
Josh Coalson committed
980
981
982
983
984

	/*
	 * read in the raw header as bytes so we can CRC it, and parse it on the way
	 */
	for(i = 0; i < 2; i++) {
985
		if(!FLAC__bitbuffer_read_raw_uint32(&decoder->private->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
986
			return false; /* the read_callback_ sets the state for us */
987
		if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
Josh Coalson's avatar
Josh Coalson committed
988
			/* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */
989
990
991
992
			decoder->private->lookahead = (byte)x;
			decoder->private->cached = true;
			decoder->private->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_BAD_HEADER, decoder->private->client_data);
			decoder->protected->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
993
			return true;
Josh Coalson's avatar
Josh Coalson committed
994
995
996
997
		}
		raw_header[raw_header_len++] = (byte)x;
	}

998
	switch(x = raw_header[2] >> 4) {
Josh Coalson's avatar
Josh Coalson committed
999
		case 0:
1000
			if(is_known_fixed_blocksize_stream)
1001
				decoder->private->frame.header.blocksize = decoder->private->stream_info.data.stream_info.min_blocksize;
Josh Coalson's avatar
Josh Coalson committed
1002
1003
1004
1005
			else
				is_unparseable = true;
			break;
		case 1:
1006
			decoder->private->frame.header.blocksize = 192;
Josh Coalson's avatar
Josh Coalson committed
1007
1008
1009
1010
1011
			break;
		case 2:
		case 3:
		case 4:
		case 5:
1012
			decoder->private->frame.header.blocksize = 576 << (x-2);
Josh Coalson's avatar
Josh Coalson committed
1013
1014
1015
1016
1017
			break;
		case 6:
		case 7:
			blocksize_hint = x;
			break;
1018
1019
1020
1021
1022
1023
1024
1025
		case 8:
		case 9:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
1026
			decoder->private->frame.header.blocksize = 256 << (x-8);
1027
			break;
Josh Coalson's avatar
Josh Coalson committed
1028
		default:
1029
			FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
1030
1031
1032
			break;
	}

1033
	switch(x = raw_header[2] & 0x0f) {
Josh Coalson's avatar
Josh Coalson committed
1034
		case 0:
1035
1036
			if(decoder->private->has_stream_info)
				decoder->private->frame.header.sample_rate = decoder->private->stream_info.data.stream_info.sample_rate;
Josh Coalson's avatar
Josh Coalson committed
1037
1038
1039
1040
1041
1042
1043
1044
1045
			else
				is_unparseable = true;
			break;
		case 1:
		case 2:
		case 3:
			is_unparseable = true;
			break;
		case 4:
1046
			decoder->private->frame.header.sample_rate = 8000;
Josh Coalson's avatar
Josh Coalson committed
1047
1048
			break;
		case 5:
1049
			decoder->private->frame.header.sample_rate = 16000;
Josh Coalson's avatar
Josh Coalson committed
1050
1051
			break;
		case 6:
1052
			decoder->private->frame.header.sample_rate = 22050;