diff options
author | Josh Coalson <jcoalson@users.sourceforce.net> | 2004-07-16 00:53:38 +0000 |
---|---|---|
committer | Josh Coalson <jcoalson@users.sourceforce.net> | 2004-07-16 00:53:38 +0000 |
commit | 47f51b1c227876c34a753df6190a623be84d317f (patch) | |
tree | 7c9b125073c75093f62d3f151c71a8139208cc8c | |
parent | 02d66815b848c04d6bae9de498b4d76011bbd76a (diff) | |
download | flac-47f51b1c227876c34a753df6190a623be84d317f.tar.gz |
add method for skipping an audio frame, plus tests
-rw-r--r-- | include/FLAC++/decoder.h | 3 | ||||
-rw-r--r-- | include/FLAC/file_decoder.h | 11 | ||||
-rw-r--r-- | include/FLAC/seekable_stream_decoder.h | 11 | ||||
-rw-r--r-- | include/FLAC/stream_decoder.h | 67 | ||||
-rw-r--r-- | src/libFLAC++/file_decoder.cpp | 6 | ||||
-rw-r--r-- | src/libFLAC++/seekable_stream_decoder.cpp | 6 | ||||
-rw-r--r-- | src/libFLAC++/stream_decoder.cpp | 6 | ||||
-rw-r--r-- | src/libFLAC/file_decoder.c | 20 | ||||
-rw-r--r-- | src/libFLAC/seekable_stream_decoder.c | 20 | ||||
-rw-r--r-- | src/libFLAC/stream_decoder.c | 180 | ||||
-rw-r--r-- | src/test_libFLAC++/decoders.cpp | 15 | ||||
-rw-r--r-- | src/test_libFLAC/decoders.c | 15 |
12 files changed, 283 insertions, 77 deletions
diff --git a/include/FLAC++/decoder.h b/include/FLAC++/decoder.h index 51d21387..8a913918 100644 --- a/include/FLAC++/decoder.h +++ b/include/FLAC++/decoder.h @@ -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: diff --git a/include/FLAC/file_decoder.h b/include/FLAC/file_decoder.h index fedf4cc3..04e05ffb 100644 --- a/include/FLAC/file_decoder.h +++ b/include/FLAC/file_decoder.h @@ -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(). diff --git a/include/FLAC/seekable_stream_decoder.h b/include/FLAC/seekable_stream_decoder.h index c47d0840..b28f4472 100644 --- a/include/FLAC/seekable_stream_decoder.h +++ b/include/FLAC/seekable_stream_decoder.h @@ -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. diff --git a/include/FLAC/stream_decoder.h b/include/FLAC/stream_decoder.h index 894e28f9..cd6ebe80 100644 --- a/include/FLAC/stream_decoder.h +++ b/include/FLAC/stream_decoder.h @@ -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 diff --git a/src/libFLAC++/file_decoder.cpp b/src/libFLAC++/file_decoder.cpp index 9a2ae391..b7c549fd 100644 --- a/src/libFLAC++/file_decoder.cpp +++ b/src/libFLAC++/file_decoder.cpp @@ -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_); diff --git a/src/libFLAC++/seekable_stream_decoder.cpp b/src/libFLAC++/seekable_stream_decoder.cpp index 0db8a61c..ca14c209 100644 --- a/src/libFLAC++/seekable_stream_decoder.cpp +++ b/src/libFLAC++/seekable_stream_decoder.cpp @@ -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()); diff --git a/src/libFLAC++/stream_decoder.cpp b/src/libFLAC++/stream_decoder.cpp index 3f23a3b9..af176888 100644 --- a/src/libFLAC++/stream_decoder.cpp +++ b/src/libFLAC++/stream_decoder.cpp @@ -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; diff --git a/src/libFLAC/file_decoder.c b/src/libFLAC/file_decoder.c index c11c6645..94e5c945 100644 --- a/src/libFLAC/file_decoder.c +++ b/src/libFLAC/file_decoder.c @@ -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); diff --git a/src/libFLAC/seekable_stream_decoder.c b/src/libFLAC/seekable_stream_decoder.c index b80390ce..ede23128 100644 --- a/src/libFLAC/seekable_stream_decoder.c +++ b/src/libFLAC/seekable_stream_decoder.c @@ -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; diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c index 575068c4..4b6f6e2e 100644 --- a/src/libFLAC/stream_decoder.c +++ b/src/libFLAC/stream_decoder.c @@ -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; } diff --git a/src/test_libFLAC++/decoders.cpp b/src/test_libFLAC++/decoders.cpp index be4ef415..d44d34dd 100644 --- a/src/test_libFLAC++/decoders.cpp +++ b/src/test_libFLAC++/decoders.cpp @@ -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"); + printf("OK\n"); + printf("testing flush()... "); if(!decoder->flush()) return decoder->die("returned false"); @@ -1723,6 +1733,11 @@ static bool test_file_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 seek_absolute()... "); if(!decoder->seek_absolute(0)) return decoder->die("returned false"); diff --git a/src/test_libFLAC/decoders.c b/src/test_libFLAC/decoders.c index 5fc93826..ebbd5ae4 100644 --- a/src/test_libFLAC/decoders.c +++ b/src/test_libFLAC/decoders.c @@ -386,6 +386,11 @@ static FLAC__bool test_stream_decoder() return die_s_("returned false", decoder); printf("OK\n"); + printf("testing FLAC__stream_decoder_skip_single_frame()... "); + if(!FLAC__stream_decoder_skip_single_frame(decoder)) + return die_s_("returned false", decoder); + printf("OK\n"); + printf("testing FLAC__stream_decoder_flush()... "); if(!FLAC__stream_decoder_flush(decoder)) return die_s_("returned false", decoder); @@ -1093,6 +1098,11 @@ static FLAC__bool test_seekable_stream_decoder() return die_ss_("returned false", decoder); printf("OK\n"); + printf("testing FLAC__seekable_stream_decoder_skip_single_frame()... "); + if(!FLAC__seekable_stream_decoder_skip_single_frame(decoder)) + return die_ss_("returned false", decoder); + printf("OK\n"); + printf("testing FLAC__seekable_stream_decoder_flush()... "); if(!FLAC__seekable_stream_decoder_flush(decoder)) return die_ss_("returned false", decoder); @@ -1664,6 +1674,11 @@ static FLAC__bool test_file_decoder() return die_f_("returned false", decoder); printf("OK\n"); + printf("testing FLAC__file_decoder_skip_single_frame()... "); + if(!FLAC__file_decoder_skip_single_frame(decoder)) + return die_f_("returned false", decoder); + printf("OK\n"); + printf("testing FLAC__file_decoder_seek_absolute()... "); if(!FLAC__file_decoder_seek_absolute(decoder, 0)) return die_f_("returned false", decoder); |