* occurred. If the decoder loses sync it will call the error callback
* instead.
*
- * \param decoder An initialized decoder instance in the state
- * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC.
+ * Unless there is a fatal read error or end of stream, this function
+ * will return once one whole frame is decoded. In other words, if the
+ * stream is not syncronized or points to a corrupt frame header, the
+ * decoder will continue to try and resync until it gets to a valid
+ * frame, then decode one frame, then return. If the decoder points to
+ * frame whose frame CRC in the frame footer does not match the
+ * computed frame CRC, this function will issue a
+ * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the
+ * error callback, and return, having decoded one complete, although
+ * corrupt, frame. (Such corrupted frames are sent as silence of the
+ * correct length to the write callback.)
+ *
+ * \param decoder An initialized decoder instance.
* \assert
* \code decoder != NULL \endcode
- * \code FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC \endcode
* \retval FLAC__bool
* \c false if any read or write error occurred (except
* \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true;
* with the decoded metadata. If the decoder loses sync it will call the
* error callback.
*
- * \param decoder An initialized decoder instance in the state
- * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA.
+ * \param decoder An initialized decoder instance.
* \assert
* \code decoder != NULL \endcode
- * \code FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA \endcode
* \retval FLAC__bool
* \c false if any read or write error occurred (except
* \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true;
* callback will be called with the decoded metadata or frame. If the
* decoder loses sync it will call the error callback.
*
- * \param decoder An initialized decoder instance in the state
- * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA.
+ * \param decoder An initialized decoder instance.
* \assert
* \code decoder != NULL \endcode
- * \code FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA \endcode
* \retval FLAC__bool
* \c false if any read or write error occurred (except
* \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true;
*/
FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder);
+/** Skip one audio frame.
+ * This version instructs the decoder to 'skip' a single frame and stop,
+ * unless the callbacks return a fatal error or the read callback returns
+ * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM.
+ *
+ * The decoding flow is the same as what occurs when
+ * FLAC__stream_decoder_process_single() is called to process an audio
+ * frame, except that this function does not decode the parsed data into
+ * PCM or call the write callback. The integrity of the frame is still
+ * checked the same way as in the other process functions.
+ *
+ * This function will return once one whole frame is skipped, in the
+ * same way that FLAC__stream_decoder_process_single() will return once
+ * one whole frame is decoded.
+ *
+ * This function, when used from the higher FLAC__SeekableStreamDecoder
+ * layer, can be used in more quickly determining FLAC frame boundaries
+ * when decoding of the actual data is not needed, for example when a
+ * application is separating a FLAC stream into frames for editing or
+ * storing in a container. To do this, the application can use
+ * FLAC__seekable_stream_decoder_skip_single_frame() to quickly advance
+ * to the next frame, then use
+ * FLAC__seekable_stream_decoder_get_decode_position() to find the new
+ * frame boundary.
+ *
+ * This function should only be called when the stream has advanced
+ * past all the metadata, otherwise it will return \c false.
+ *
+ * \param decoder An initialized decoder instance not in a metadata
+ * state.
+ * \assert
+ * \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if any read or write error occurred (except
+ * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), or if the decoder
+ * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or
+ * FLAC__STREAM_DECODER_READ_METADATA state, else \c true;
+ * in any case, check the decoder state with
+ * FLAC__stream_decoder_get_state() to see what went wrong or to
+ * check for lost synchronization (a sign of stream corruption).
+ */
+FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder);
+
/* \} */
#ifdef __cplusplus
static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj);
static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder);
static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder);
-static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame);
+static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode);
static FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder);
-static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
-static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
-static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
-static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order);
-static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps);
+static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode);
+static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode);
+static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode);
+static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode);
+static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode);
static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual);
static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder);
static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data);
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_FRAME:
- if(!read_frame_(decoder, &got_a_frame))
+ if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/true))
return false; /* above function sets the status for us */
if(got_a_frame)
return true; /* above function sets the status for us */
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_FRAME:
- if(!read_frame_(decoder, &dummy))
+ if(!read_frame_(decoder, &dummy, /*do_full_decode=*/true))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_END_OF_STREAM:
}
}
+FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder)
+{
+ FLAC__bool got_a_frame;
+ FLAC__ASSERT(0 != decoder);
+ FLAC__ASSERT(0 != decoder->protected_);
+
+ while(1) {
+ switch(decoder->protected_->state) {
+ case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
+ case FLAC__STREAM_DECODER_READ_METADATA:
+ return false; /* above function sets the status for us */
+ case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
+ if(!frame_sync_(decoder))
+ return true; /* above function sets the status for us */
+ break;
+ case FLAC__STREAM_DECODER_READ_FRAME:
+ if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/false))
+ 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:
+ case FLAC__STREAM_DECODER_ABORTED:
+ return true;
+ default:
+ FLAC__ASSERT(0);
+ return false;
+ }
+ }
+}
+
/***********************************************************************
*
* Protected class methods
return true;
}
-FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame)
+FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode)
{
unsigned channel;
unsigned i;
/*
* now read it
*/
- if(!read_subframe_(decoder, channel, bps))
+ if(!read_subframe_(decoder, channel, bps, do_full_decode))
return false;
if(decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder))
return false; /* the read_callback_ sets the state for us */
if(frame_crc == (FLAC__uint16)x) {
- /* Undo any special channel coding */
- switch(decoder->private_->frame.header.channel_assignment) {
- case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
- /* do nothing */
- break;
- case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
- 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];
- break;
- case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
- 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];
- break;
- case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
- 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];
- mid <<= 1;
- if(side & 1) /* i.e. if 'side' is odd... */
- mid++;
- left = mid + side;
- right = mid - side;
- decoder->private_->output[0][i] = left >> 1;
- decoder->private_->output[1][i] = right >> 1;
- }
- break;
- default:
- FLAC__ASSERT(0);
- break;
+ if(do_full_decode) {
+ /* Undo any special channel coding */
+ switch(decoder->private_->frame.header.channel_assignment) {
+ case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
+ /* do nothing */
+ break;
+ case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
+ 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];
+ break;
+ case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
+ 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];
+ break;
+ case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
+ 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];
+ mid <<= 1;
+ if(side & 1) /* i.e. if 'side' is odd... */
+ mid++;
+ left = mid + side;
+ right = mid - side;
+ decoder->private_->output[0][i] = left >> 1;
+ decoder->private_->output[1][i] = right >> 1;
+ }
+ break;
+ default:
+ FLAC__ASSERT(0);
+ break;
+ }
}
}
else {
/* Bad frame, emit error and zero the output signal */
decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, decoder->private_->client_data);
- for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
- memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
+ if(do_full_decode) {
+ for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
+ memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
+ }
}
}
decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize;
/* write it */
- if(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE)
- return false;
+ if(do_full_decode) {
+ if(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE)
+ return false;
+ }
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
return true;
}
-FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps)
+FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode)
{
FLAC__uint32 x;
FLAC__bool wasted_bits;
return true;
}
else if(x == 0) {
- if(!read_subframe_constant_(decoder, channel, bps))
+ if(!read_subframe_constant_(decoder, channel, bps, do_full_decode))
return false;
}
else if(x == 2) {
- if(!read_subframe_verbatim_(decoder, channel, bps))
+ if(!read_subframe_verbatim_(decoder, channel, bps, do_full_decode))
return false;
}
else if(x < 16) {
return false;
}
else if(x <= 24) {
- if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7))
+ if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7, do_full_decode))
return false;
}
else if(x < 64) {
return false;
}
else {
- if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1))
+ if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1, do_full_decode))
return false;
}
- if(wasted_bits) {
+ if(wasted_bits && do_full_decode) {
unsigned i;
x = decoder->private_->frame.subframes[channel].wasted_bits;
for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
return true;
}
-FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps)
+FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode)
{
FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant;
FLAC__int32 x;
subframe->value = x;
/* decode the subframe */
- for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
- output[i] = x;
+ if(do_full_decode) {
+ for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
+ output[i] = x;
+ }
return true;
}
-FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order)
+FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode)
{
FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed;
FLAC__int32 i32;
}
/* decode the subframe */
- memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order);
- FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order);
+ if(do_full_decode) {
+ memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order);
+ FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order);
+ }
return true;
}
-FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order)
+FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode)
{
FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc;
FLAC__int32 i32;
}
/* decode the subframe */
- memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order);
- if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32)
- if(bps <= 16 && subframe->qlp_coeff_precision <= 16)
- decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
+ if(do_full_decode) {
+ memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order);
+ if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32)
+ if(bps <= 16 && subframe->qlp_coeff_precision <= 16)
+ decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
+ else
+ decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
else
- decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
- else
- decoder->private_->local_lpc_restore_signal_64bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
+ decoder->private_->local_lpc_restore_signal_64bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
+ }
return true;
}
-FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps)
+FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode)
{
FLAC__Subframe_Verbatim *subframe = &decoder->private_->frame.subframes[channel].data.verbatim;
FLAC__int32 x, *residual = decoder->private_->residual[channel];
}
/* decode the subframe */
- memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
+ if(do_full_decode)
+ memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
return true;
}