stream_decoder.c 58.7 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
46
47
48
49
50
51
52
53
54
55
56
static FLAC__bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels);
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);
57
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
58
59
static FLAC__bool stream_decoder_read_zero_padding_(FLAC__StreamDecoder *decoder);
static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data);
60
61
62
63
64
65
66

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

Josh Coalson's avatar
Josh Coalson committed
67
typedef struct FLAC__StreamDecoderPrivate {
Josh Coalson's avatar
Josh Coalson committed
68
69
	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
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);
Josh Coalson's avatar
Josh Coalson committed
72
73
	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
74
	void *client_data;
75
	FLAC__BitBuffer *input;
Josh Coalson's avatar
Josh Coalson committed
76
77
	FLAC__int32 *output[FLAC__MAX_CHANNELS];
	FLAC__int32 *residual[FLAC__MAX_CHANNELS];
78
	unsigned output_capacity, output_channels;
Josh Coalson's avatar
Josh Coalson committed
79
80
81
	FLAC__uint32 last_frame_number;
	FLAC__uint64 samples_decoded;
	FLAC__bool has_stream_info, has_seek_table;
82
83
	FLAC__StreamMetaData stream_info;
	FLAC__StreamMetaData seek_table;
84
	FLAC__Frame frame;
Josh Coalson's avatar
Josh Coalson committed
85
	FLAC__bool cached; /* true if there is a byte in lookahead */
86
	FLAC__CPUInfo cpuinfo;
Josh Coalson's avatar
Josh Coalson committed
87
88
	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
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
	decoder->protected_ = (FLAC__StreamDecoderProtected*)malloc(sizeof(FLAC__StreamDecoderProtected));
	if(decoder->protected_ == 0) {
145
146
147
		free(decoder);
		return 0;
	}
148
149
150
	decoder->private_ = (FLAC__StreamDecoderPrivate*)malloc(sizeof(FLAC__StreamDecoderPrivate));
	if(decoder->private_ == 0) {
		free(decoder->protected_);
151
152
153
		free(decoder);
		return 0;
	}
154
155
156
157
158
159
160
	decoder->private_->input = FLAC__bitbuffer_new();
	if(decoder->private_->input == 0) {
		free(decoder->private_);
		free(decoder->protected_);
		free(decoder);
		return 0;
	}
161

162
	decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
163

164
165
166
167
168
	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;
169

Josh Coalson's avatar
Josh Coalson committed
170
171
172
	return decoder;
}

173
void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
174
{
175
	FLAC__ASSERT(decoder != 0);
176
177
	FLAC__ASSERT(decoder->protected_ != 0);
	FLAC__ASSERT(decoder->private_ != 0);
178
	FLAC__ASSERT(decoder->private_->input != 0);
179

180
	FLAC__bitbuffer_delete(decoder->private_->input);
181
182
	free(decoder->private_);
	free(decoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
183
184
185
	free(decoder);
}

186
187
188
189
190
191
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

192
FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
193
194
195
{
	unsigned i;

196
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
197

198
199
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
		return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED;
Josh Coalson's avatar
Josh Coalson committed
200

201
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
202

203
204
	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
205

206
207
	if(!FLAC__bitbuffer_init(decoder->private_->input))
		return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
208

209
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
210
211
		decoder->private_->output[i] = 0;
		decoder->private_->residual[i] = 0;
212
	}
Josh Coalson's avatar
Josh Coalson committed
213

214
215
216
217
218
219
220
	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
221

222
223
224
	/*
	 * get the CPU info and set the function pointers
	 */
225
	FLAC__cpu_info(&decoder->private_->cpuinfo);
226
	/* first default to the non-asm routines */
227
228
	decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal;
	decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal;
229
	/* now override with asm where appropriate */
230
#ifndef FLAC__NO_ASM
231
	if(decoder->private_->cpuinfo.use_asm) {
232
#ifdef FLAC__CPU_IA32
233
		FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
234
#ifdef FLAC__HAS_NASM
235
236
237
		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;
238
239
		}
		else {
240
241
			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;
242
		}
243
#endif
244
#endif
245
	}
246
247
#endif

248
	return decoder->protected_->state;
Josh Coalson's avatar
Josh Coalson committed
249
250
251
252
253
}

void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
{
	unsigned i;
254
	FLAC__ASSERT(decoder != 0);
255
	if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED)
Josh Coalson's avatar
Josh Coalson committed
256
		return;
257
258
259
	if(decoder->private_->has_seek_table) {
		free(decoder->private_->seek_table.data.seek_table.points);
		decoder->private_->seek_table.data.seek_table.points = 0;
260
	}
261
	FLAC__bitbuffer_free(decoder->private_->input);
262
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
263
		/* 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. */
264
265
266
		if(decoder->private_->output[i] != 0) {
			free(decoder->private_->output[i]-4);
			decoder->private_->output[i] = 0;
267
		}
268
269
270
		if(decoder->private_->residual[i] != 0) {
			free(decoder->private_->residual[i]);
			decoder->private_->residual[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
271
272
		}
	}
273
274
275
	decoder->private_->output_capacity = 0;
	decoder->private_->output_channels = 0;
	decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
276
277
}

Josh Coalson's avatar
Josh Coalson committed
278
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))
279
{
280
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
281
		return false;
282
	decoder->private_->read_callback = value;
283
284
285
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
286
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))
287
{
288
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
289
		return false;
290
	decoder->private_->write_callback = value;
291
292
293
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
294
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))
295
{
296
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
297
		return false;
298
	decoder->private_->metadata_callback = value;
299
300
301
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
302
FLAC__bool FLAC__stream_decoder_set_error_callback(const FLAC__StreamDecoder *decoder, void (*value)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data))
303
{
304
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
305
		return false;
306
	decoder->private_->error_callback = value;
307
308
309
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
310
FLAC__bool FLAC__stream_decoder_set_client_data(const FLAC__StreamDecoder *decoder, void *value)
311
{
312
	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
313
		return false;
314
	decoder->private_->client_data = value;
315
316
317
318
	return true;
}

FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder)
319
{
320
	return decoder->protected_->state;
321
322
}

323
unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
324
{
325
	return decoder->protected_->channels;
326
327
}

328
FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder)
329
{
330
	return decoder->protected_->channel_assignment;
331
332
}

333
unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)
334
{
335
	return decoder->protected_->bits_per_sample;
336
337
}

338
unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)
339
{
340
	return decoder->protected_->sample_rate;
341
342
}

343
unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder)
344
{
345
	return decoder->protected_->blocksize;
Josh Coalson's avatar
Josh Coalson committed
346
347
}

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

352
	if(!FLAC__bitbuffer_clear(decoder->private_->input)) {
353
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
354
355
		return false;
	}
356
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
357
358
359
360

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
361
FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
362
{
363
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
364
365

	if(!FLAC__stream_decoder_flush(decoder)) {
366
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
367
368
		return false;
	}
369
	decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
Josh Coalson's avatar
Josh Coalson committed
370

371
	decoder->private_->samples_decoded = 0;
Josh Coalson's avatar
Josh Coalson committed
372

Josh Coalson's avatar
Josh Coalson committed
373
374
375
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
376
FLAC__bool FLAC__stream_decoder_process_whole_stream(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
377
{
Josh Coalson's avatar
Josh Coalson committed
378
	FLAC__bool dummy;
379
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
380

381
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
382
383
		return true;

384
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
385
386

	if(!FLAC__stream_decoder_reset(decoder)) {
387
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
388
389
390
391
		return false;
	}

	while(1) {
392
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
			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:
412
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
413
414
415
416
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
417
FLAC__bool FLAC__stream_decoder_process_metadata(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
418
{
419
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
420

421
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
422
423
		return true;

424
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA);
Josh Coalson's avatar
Josh Coalson committed
425
426

	if(!FLAC__stream_decoder_reset(decoder)) {
427
		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
428
429
430
431
		return false;
	}

	while(1) {
432
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
433
434
435
436
437
438
439
440
441
442
			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;
443
444
			case FLAC__STREAM_DECODER_READ_FRAME:
				return true;
Josh Coalson's avatar
Josh Coalson committed
445
446
447
			case FLAC__STREAM_DECODER_END_OF_STREAM:
				return true;
			default:
448
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
449
450
451
452
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
453
FLAC__bool FLAC__stream_decoder_process_one_frame(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
454
{
Josh Coalson's avatar
Josh Coalson committed
455
	FLAC__bool got_a_frame;
456
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
457

458
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
459
460
		return true;

461
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
462
463

	while(1) {
464
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
465
466
467
468
469
470
471
472
473
474
475
476
477
			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:
478
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
479
480
481
482
		}
	}
}

Josh Coalson's avatar
Josh Coalson committed
483
FLAC__bool FLAC__stream_decoder_process_remaining_frames(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
484
{
Josh Coalson's avatar
Josh Coalson committed
485
	FLAC__bool dummy;
486
	FLAC__ASSERT(decoder != 0);
Josh Coalson's avatar
Josh Coalson committed
487

488
	if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
Josh Coalson's avatar
Josh Coalson committed
489
490
		return true;

491
	FLAC__ASSERT(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC);
Josh Coalson's avatar
Josh Coalson committed
492
493

	while(1) {
494
		switch(decoder->protected_->state) {
Josh Coalson's avatar
Josh Coalson committed
495
496
497
498
499
500
501
502
503
504
505
			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:
506
				FLAC__ASSERT(0);
Josh Coalson's avatar
Josh Coalson committed
507
508
509
510
		}
	}
}

511
512
513
514
515
516
/***********************************************************************
 *
 * Protected class methods
 *
 ***********************************************************************/

517
unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
518
{
519
	FLAC__ASSERT(decoder != 0);
520
	return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input);
Josh Coalson's avatar
Josh Coalson committed
521
522
}

523
524
525
526
527
528
/***********************************************************************
 *
 * Private class methods
 *
 ***********************************************************************/

Josh Coalson's avatar
Josh Coalson committed
529
FLAC__bool stream_decoder_allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels)
Josh Coalson's avatar
Josh Coalson committed
530
531
{
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
532
	FLAC__int32 *tmp;
Josh Coalson's avatar
Josh Coalson committed
533

534
	if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels)
Josh Coalson's avatar
Josh Coalson committed
535
536
		return true;

537
538
	/* @@@ should change to use realloc() */

Josh Coalson's avatar
Josh Coalson committed
539
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
540
541
542
		if(decoder->private_->output[i] != 0) {
			free(decoder->private_->output[i]);
			decoder->private_->output[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
543
		}
544
545
546
		if(decoder->private_->residual[i] != 0) {
			free(decoder->private_->residual[i]);
			decoder->private_->residual[i] = 0;
547
		}
Josh Coalson's avatar
Josh Coalson committed
548
549
	}

550
	for(i = 0; i < channels; i++) {
551
552
		/* 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
553
		if(tmp == 0) {
554
			decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
Josh Coalson's avatar
Josh Coalson committed
555
556
			return false;
		}
557
		memset(tmp, 0, sizeof(FLAC__int32)*4);
558
		decoder->private_->output[i] = tmp + 4;
559

Josh Coalson's avatar
Josh Coalson committed
560
		tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*size);
561
		if(tmp == 0) {
562
			decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
563
564
			return false;
		}
565
		decoder->private_->residual[i] = tmp;
Josh Coalson's avatar
Josh Coalson committed
566
567
	}

568
569
	decoder->private_->output_capacity = size;
	decoder->private_->output_channels = channels;
Josh Coalson's avatar
Josh Coalson committed
570
571
572
573

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
574
FLAC__bool stream_decoder_find_metadata_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
575
{
Josh Coalson's avatar
Josh Coalson committed
576
	FLAC__uint32 x;
Josh Coalson's avatar
Josh Coalson committed
577
	unsigned i, id;
Josh Coalson's avatar
Josh Coalson committed
578
	FLAC__bool first = true;
Josh Coalson's avatar
Josh Coalson committed
579

580
	FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
Josh Coalson's avatar
Josh Coalson committed
581
582

	for(i = id = 0; i < 4; ) {
583
584
585
		if(decoder->private_->cached) {
			x = (FLAC__uint32)decoder->private_->lookahead;
			decoder->private_->cached = false;
586
587
		}
		else {
588
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
589
590
				return false; /* the read_callback_ sets the state for us */
		}
Josh Coalson's avatar
Josh Coalson committed
591
		if(x == FLAC__STREAM_SYNC_STRING[i]) {
592
			first = true;
Josh Coalson's avatar
Josh Coalson committed
593
594
595
596
597
598
599
600
601
602
603
604
605
606
			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 */
607
			decoder->private_->header_warmup[0] = (FLAC__byte)x;
608
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
609
				return false; /* the read_callback_ sets the state for us */
610
611
612
613

			/* 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 */
614
615
				decoder->private_->lookahead = (FLAC__byte)x;
				decoder->private_->cached = true;
616
617
			}
			else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */
618
619
				decoder->private_->header_warmup[1] = (FLAC__byte)x;
				decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME;
Josh Coalson's avatar
Josh Coalson committed
620
621
622
623
624
				return true;
			}
		}
		i = 0;
		if(first) {
625
			decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private_->client_data);
626
			first = false;
Josh Coalson's avatar
Josh Coalson committed
627
628
629
		}
	}

630
	decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA;
Josh Coalson's avatar
Josh Coalson committed
631
632
633
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
634
FLAC__bool stream_decoder_read_metadata_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
635
{
Josh Coalson's avatar
Josh Coalson committed
636
637
	FLAC__uint32 i, x, last_block, type, length;
	FLAC__uint64 xx;
Josh Coalson's avatar
Josh Coalson committed
638

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

641
	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
642
		return false; /* the read_callback_ sets the state for us */
643
	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
644
		return false; /* the read_callback_ sets the state for us */
645
	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
646
		return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
647
	if(type == FLAC__METADATA_TYPE_STREAMINFO) {
648
		unsigned used_bits = 0;
649
650
651
		decoder->private_->stream_info.type = type;
		decoder->private_->stream_info.is_last = last_block;
		decoder->private_->stream_info.length = length;
652

653
		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
654
			return false; /* the read_callback_ sets the state for us */
655
		decoder->private_->stream_info.data.stream_info.min_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
656
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
657

658
		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
659
			return false; /* the read_callback_ sets the state for us */
660
		decoder->private_->stream_info.data.stream_info.max_blocksize = x;
Josh Coalson's avatar
Josh Coalson committed
661
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
662

663
		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
664
			return false; /* the read_callback_ sets the state for us */
665
		decoder->private_->stream_info.data.stream_info.min_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
666
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
667

668
		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
669
			return false; /* the read_callback_ sets the state for us */
670
		decoder->private_->stream_info.data.stream_info.max_framesize = x;
Josh Coalson's avatar
Josh Coalson committed
671
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
672

673
		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
674
			return false; /* the read_callback_ sets the state for us */
675
		decoder->private_->stream_info.data.stream_info.sample_rate = x;
Josh Coalson's avatar
Josh Coalson committed
676
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
677

678
		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
679
			return false; /* the read_callback_ sets the state for us */
680
		decoder->private_->stream_info.data.stream_info.channels = x+1;
Josh Coalson's avatar
Josh Coalson committed
681
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
682

683
		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
684
			return false; /* the read_callback_ sets the state for us */
685
		decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1;
Josh Coalson's avatar
Josh Coalson committed
686
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
687

688
		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
689
			return false; /* the read_callback_ sets the state for us */
Josh Coalson's avatar
Josh Coalson committed
690
		used_bits += FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
691

Josh Coalson's avatar
Josh Coalson committed
692
		for(i = 0; i < 16; i++) {
693
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
694
				return false; /* the read_callback_ sets the state for us */
695
			decoder->private_->stream_info.data.stream_info.md5sum[i] = (FLAC__byte)x;
Josh Coalson's avatar
Josh Coalson committed
696
		}
697
		used_bits += i*8;
Josh Coalson's avatar
Josh Coalson committed
698

699
		/* skip the rest of the block */
700
		FLAC__ASSERT(used_bits % 8 == 0);
701
702
		length -= (used_bits / 8);
		for(i = 0; i < length; i++) {
703
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
704
705
706
				return false; /* the read_callback_ sets the state for us */
		}

707
708
		decoder->private_->has_stream_info = true;
		decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data);
709
710
	}
	else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
711
712
		unsigned real_points;

713
714
715
		decoder->private_->seek_table.type = type;
		decoder->private_->seek_table.is_last = last_block;
		decoder->private_->seek_table.length = length;
716

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

719
720
		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;
721
722
			return false;
		}
723
		for(i = real_points = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) {
724
			if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
725
				return false; /* the read_callback_ sets the state for us */
726
			decoder->private_->seek_table.data.seek_table.points[real_points].sample_number = xx;
727

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

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

736
			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
737
				real_points++;
738
		}
739
		decoder->private_->seek_table.data.seek_table.num_points = real_points;
740

741
742
		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
743
744
745
746
	}
	else {
		/* skip other metadata blocks */
		for(i = 0; i < length; i++) {
747
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
748
749
750
751
752
				return false; /* the read_callback_ sets the state for us */
		}
	}

	if(last_block)
753
		decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
Josh Coalson's avatar
Josh Coalson committed
754
755
756
757

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
758
FLAC__bool stream_decoder_skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
759
{
Josh Coalson's avatar
Josh Coalson committed
760
	FLAC__uint32 x;
Josh Coalson's avatar
Josh Coalson committed
761
762
763
	unsigned i, skip;

	/* skip the version and flags bytes */
764
	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
765
766
767
768
		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++) {
769
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
770
771
772
773
774
775
			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++) {
776
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
777
778
779
780
781
			return false; /* the read_callback_ sets the state for us */
	}
	return true;
}

Josh Coalson's avatar
Josh Coalson committed
782
FLAC__bool stream_decoder_frame_sync_(FLAC__StreamDecoder *decoder)
Josh Coalson's avatar
Josh Coalson committed
783
{
Josh Coalson's avatar
Josh Coalson committed
784
785
	FLAC__uint32 x;
	FLAC__bool first = true;
Josh Coalson's avatar
Josh Coalson committed
786
787
788

	/* 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. */
789
790
791
	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
792
793
794
795
796
			return true;
		}
	}

	/* make sure we're byte aligned */
797
798
	if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) {
		if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
799
800
801
802
			return false; /* the read_callback_ sets the state for us */
	}

	while(1) {
803
804
805
		if(decoder->private_->cached) {
			x = (FLAC__uint32)decoder->private_->lookahead;
			decoder->private_->cached = false;
806
807
		}
		else {
808
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
809
810
				return false; /* the read_callback_ sets the state for us */
		}
Josh Coalson's avatar
Josh Coalson committed
811
		if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
812
			decoder->private_->header_warmup[0] = (FLAC__byte)x;
813
			if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
Josh Coalson's avatar
Josh Coalson committed
814
				return false; /* the read_callback_ sets the state for us */
815
816
817
818

			/* 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 */
819
820
				decoder->private_->lookahead = (FLAC__byte)x;
				decoder->private_->cached = true;
821
822
			}
			else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */
823
824
				decoder->private_->header_warmup[1] = (FLAC__byte)x;
				decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME;
Josh Coalson's avatar
Josh Coalson committed
825
826
827
828
				return true;
			}
		}
		if(first) {
829
			decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_LOST_SYNC, decoder->private_->client_data);
Josh Coalson's avatar
Josh Coalson committed
830
			first = false;
Josh Coalson's avatar
Josh Coalson committed
831
832
833
834
835
836
		}
	}

	return true;
}

Josh Coalson's avatar
Josh Coalson committed
837
FLAC__bool stream_decoder_read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame)
Josh Coalson's avatar
Josh Coalson committed
838
839
840
{
	unsigned channel;
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
841
842
843
	FLAC__int32 mid, side, left, right;
	FLAC__uint16 frame_crc; /* the one we calculate from the input stream */
	FLAC__uint32 x;
Josh Coalson's avatar
Josh Coalson committed
844
845
846

	*got_a_frame = false;

847
848
	/* init the CRC */
	frame_crc = 0;
849
850
	FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc);
	FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc);
851
	FLAC__bitbuffer_reset_read_crc16(decoder->private_->input, frame_crc);
852

Josh Coalson's avatar
Josh Coalson committed
853
854
	if(!stream_decoder_read_frame_header_(decoder))
		return false;
855
	if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC)
Josh Coalson's avatar
Josh Coalson committed
856
		return true;
857
	if(!stream_decoder_allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels))
Josh Coalson's avatar
Josh Coalson committed
858
		return false;
859
	for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
860
861
862
		/*
		 * first figure the correct bits-per-sample of the subframe
		 */
863
864
		unsigned bps = decoder->private_->frame.header.bits_per_sample;
		switch(decoder->private_->frame.header.channel_assignment) {
865
866
867
868
			case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
				/* no adjustment needed */
				break;
			case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
869
				FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
870
871
872
873
				if(channel == 1)
					bps++;
				break;
			case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
874
				FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
875
876
877
878
				if(channel == 0)
					bps++;
				break;
			case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
879
				FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
880
881
882
883
				if(channel == 1)
					bps++;
				break;
			default:
884
				FLAC__ASSERT(0);
885
886
887
888
889
		}
		/*
		 * now read it
		 */
		if(!stream_decoder_read_subframe_(decoder, channel, bps))
Josh Coalson's avatar
Josh Coalson committed
890
			return false;
891
892
		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
893
894
895
896
897
898
</