Commit 47f51b1c authored by Josh Coalson's avatar Josh Coalson
Browse files

add method for skipping an audio frame, plus tests

parent 02d66815
......@@ -134,6 +134,7 @@ namespace FLAC {
bool process_single();
bool process_until_end_of_metadata();
bool process_until_end_of_stream();
bool skip_single_frame();
protected:
virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
......@@ -222,6 +223,7 @@ namespace FLAC {
bool process_single();
bool process_until_end_of_metadata();
bool process_until_end_of_stream();
bool skip_single_frame();
bool seek_absolute(FLAC__uint64 sample);
protected:
......@@ -319,6 +321,7 @@ namespace FLAC {
bool process_single();
bool process_until_end_of_metadata();
bool process_until_end_of_file();
bool skip_single_frame();
bool seek_absolute(FLAC__uint64 sample);
protected:
......
......@@ -627,6 +627,17 @@ FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_metadata(FLAC__FileD
*/
FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_file(FLAC__FileDecoder *decoder);
/** This is inherited from FLAC__SeekableStreamDecoder; see
* FLAC__seekable_stream_decoder_skip_single_frame().
*
* \param decoder A decoder instance.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__bool
* See above.
*/
FLAC_API FLAC__bool FLAC__file_decoder_skip_single_frame(FLAC__FileDecoder *decoder);
/** Flush the input and seek to an absolute sample.
* This is inherited from FLAC__SeekableStreamDecoder; see
* FLAC__seekable_stream_decoder_seek_absolute().
......
......@@ -898,6 +898,17 @@ FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_metadata(
*/
FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_stream(FLAC__SeekableStreamDecoder *decoder);
/** This is inherited from FLAC__StreamDecoder; see
* FLAC__stream_decoder_skip_single_frame().
*
* \param decoder A decoder instance.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__bool
* See above.
*/
FLAC_API FLAC__bool FLAC__seekable_stream_decoder_skip_single_frame(FLAC__SeekableStreamDecoder *decoder);
/** Flush the input and seek to an absolute sample.
* Decoding will resume at the given sample. Note that because of
* this, the next write callback may contain a partial block.
......
......@@ -751,11 +751,21 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder);
* 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;
......@@ -776,11 +786,9 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *dec
* 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;
......@@ -801,11 +809,9 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__Str
* 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;
......@@ -815,6 +821,49 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__Str
*/
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
......
......@@ -193,6 +193,12 @@ namespace FLAC {
return (bool)::FLAC__file_decoder_process_until_end_of_file(decoder_);
}
bool File::skip_single_frame()
{
FLAC__ASSERT(is_valid());
return (bool)::FLAC__file_decoder_skip_single_frame(decoder_);
}
bool File::seek_absolute(FLAC__uint64 sample)
{
FLAC__ASSERT(0 != decoder_);
......
......@@ -198,6 +198,12 @@ namespace FLAC {
return (bool)::FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder_);
}
bool SeekableStream::skip_single_frame()
{
FLAC__ASSERT(is_valid());
return (bool)::FLAC__seekable_stream_decoder_skip_single_frame(decoder_);
}
bool SeekableStream::seek_absolute(FLAC__uint64 sample)
{
FLAC__ASSERT(is_valid());
......
......@@ -176,6 +176,12 @@ namespace FLAC {
return (bool)::FLAC__stream_decoder_process_until_end_of_stream(decoder_);
}
bool Stream::skip_single_frame()
{
FLAC__ASSERT(is_valid());
return (bool)::FLAC__stream_decoder_skip_single_frame(decoder_);
}
::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
(void)decoder;
......
......@@ -505,6 +505,26 @@ FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_file(FLAC__FileDecod
return ret;
}
FLAC_API FLAC__bool FLAC__file_decoder_skip_single_frame(FLAC__FileDecoder *decoder)
{
FLAC__bool ret;
FLAC__ASSERT(0 != decoder);
if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
return true;
FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
ret = FLAC__seekable_stream_decoder_skip_single_frame(decoder->private_->seekable_stream_decoder);
if(!ret)
decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
return ret;
}
FLAC_API FLAC__bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, FLAC__uint64 sample)
{
FLAC__ASSERT(0 != decoder);
......
......@@ -647,6 +647,26 @@ FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_stream(FL
return ret;
}
FLAC_API FLAC__bool FLAC__seekable_stream_decoder_skip_single_frame(FLAC__SeekableStreamDecoder *decoder)
{
FLAC__bool ret;
FLAC__ASSERT(0 != decoder);
if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
return true;
FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK);
ret = FLAC__stream_decoder_skip_single_frame(decoder->private_->stream_decoder);
if(!ret)
decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
return ret;
}
FLAC_API FLAC__bool FLAC__seekable_stream_decoder_seek_absolute(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
{
FLAC__uint64 length;
......
......@@ -76,13 +76,13 @@ static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLA
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);
......@@ -610,7 +610,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *dec
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 */
......@@ -673,7 +673,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__Strea
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:
......@@ -686,6 +686,37 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__Strea
}
}
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
......@@ -1315,7 +1346,7 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
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;
......@@ -1367,7 +1398,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame)
/*
* 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;
......@@ -1384,45 +1415,49 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame)
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);
}
}
}
......@@ -1439,8 +1474,10 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame)
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;
......@@ -1725,7 +1762,7 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
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;
......@@ -1755,11 +1792,11 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
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) {
......@@ -1767,7 +1804,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
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) {
......@@ -1775,11 +1812,11 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
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++)
......@@ -1789,7 +1826,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
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;
......@@ -1804,13 +1841,15 @@ FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channe
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;
......@@ -1856,13 +1895,15 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel,
}
/* 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;
......@@ -1930,19 +1971,21 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un
}
/* 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];
......@@ -1959,7 +2002,8 @@ FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channe
}
/* 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;
}
......
......@@ -343,6 +343,11 @@ static bool test_stream_decoder()
return decoder->die("returned false");
printf("OK\n");
printf("testing skip_single_frame()... ");
if(!decoder->skip_single_frame())
return decoder->die("returned false");
printf("OK\n");
printf("testing flush()... ");
if(!decoder->flush())
return decoder->die("returned false");
......@@ -1060,6 +1065,11 @@ static bool test_seekable_stream_decoder()
return decoder->die("returned false");
printf("OK\n");
printf("testing skip_single_frame()... ");
if(!decoder->skip_single_frame())
return decoder->die("returned false");