FLAC__uint64 skip;
const char *inbasefilename;
+ const char *outfilename;
FLAC__uint64 samples_processed;
unsigned frame_counter;
/*
* local routines
*/
-static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool verbose, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, FLAC_uint64 skip, const char *infilename, const char *outfilename);
-static void DecoderSession_destroy(DecoderSession *d);
-static FLAC__bool DecoderSession_init_decoder(const char *infilename, DecoderSession *decoder_session);
-static int DecoderSession_finish_ok(DecoderSession *d, int info_align_carry, int info_align_zero);
+static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, FLAC__uint64 skip, const char *infilename, const char *outfilename);
+static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred);
+static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, const char *infilename);
+static FLAC__bool DecoderSession_process(DecoderSession *d);
+static int DecoderSession_finish_ok(DecoderSession *d);
static int DecoderSession_finish_error(DecoderSession *d);
static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
static void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static void print_error_with_state(const DecoderSession *d, const char *message);
static void print_stats(const DecoderSession *decoder_session);
*/
int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
{
- FLAC__bool md5_failure = false;
DecoderSession decoder_session;
- if(!DecoderSession_construct(options.common.verbose, /*is_wave_out=*/true, options.common.continue_through_decode_errors, analysis_mode, aopts, options.common.skip, infilename, outfilename))
+ if(!DecoderSession_construct(&decoder_session, options.common.is_ogg, options.common.verbose, /*is_wave_out=*/true, options.common.continue_through_decode_errors, analysis_mode, aopts, options.common.skip, infilename, outfilename))
return 1;
if(!DecoderSession_init_decoder(&decoder_session, infilename))
return DecoderSession_finish_error(&decoder_session);
- if(decoder_session.skip > 0) {
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) { /*@@@ (move this check into main.c) */
- fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", decoder_session.inbasefilename);
- goto wav_abort_;
- }
-#endif
- if(!FLAC__file_decoder_process_until_end_of_metadata(decoder_session.decoder.file)) {
- fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- if(decoder_session.abort_flag)
- goto wav_abort_;
- if(!FLAC__file_decoder_seek_absolute(decoder_session.decoder.file, decoder_session.skip)) {
- fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- if(!FLAC__file_decoder_process_until_end_of_file(decoder_session.decoder.file)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- if(FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- }
- else {
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(!OggFLAC__stream_decoder_process_until_end_of_stream(decoder_session.decoder.stream)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", decoder_session.inbasefilename, OggFLAC__stream_decoder_get_state(decoder_session.decoder.stream), FLAC__StreamDecoderStateString[OggFLAC__stream_decoder_get_state(decoder_session.decoder.stream)]);
- goto wav_abort_;
- }
- if(OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream), FLAC__StreamDecoderStateString[OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream)]);
- goto wav_abort_;
- }
- }
- else
-#endif
- {
- if(!FLAC__file_decoder_process_until_end_of_file(decoder_session.decoder.file)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- if(FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto wav_abort_;
- }
- }
- }
+ if(!DecoderSession_process(&decoder_session))
+ return DecoderSession_finish_error(&decoder_session);
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(decoder_session.decoder.stream) {
- OggFLAC__stream_decoder_finish(decoder_session.decoder.stream);
- md5_failure = false;
- print_stats(&decoder_session);
- OggFLAC__stream_decoder_delete(decoder_session.decoder.stream);
- }
- }
- else
-#endif
- {
- if(decoder_session.decoder.file) {
- md5_failure = !FLAC__file_decoder_finish(decoder_session.decoder.file);
- print_stats(&decoder_session);
- FLAC__file_decoder_delete(decoder_session.decoder.file);
- }
- }
- if(0 != decoder_session.fout && decoder_session.fout != stdout)
- fclose(decoder_session.fout);
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(0 != decoder_session.fin && decoder_session.fin != stdin)
- fclose(decoder_session.fin);
- }
-#endif
- if(analysis_mode)
- flac__analyze_finish(aopts);
- if(decoder_session.wave_chunk_size_fixup.needs_fixup)
- if(!fixup_wave_chunk_size(outfilename, decoder_session.wave_chunk_size_fixup.riff_offset, decoder_session.wave_chunk_size_fixup.data_offset, (FLAC__uint32)decoder_session.samples_processed))
- return 1;
- if(md5_failure) {
- fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", decoder_session.inbasefilename);
- }
- else {
- if(decoder_session.verbose)
- fprintf(stderr, "\r%s: %s \n", decoder_session.inbasefilename, decoder_session.test_only? "ok ":analysis_mode?"done ":"done");
- }
- return 0;
-wav_abort_:
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(decoder_session.decoder.stream) {
- OggFLAC__stream_decoder_finish(decoder_session.decoder.stream);
- OggFLAC__stream_decoder_delete(decoder_session.decoder.stream);
- }
- }
- else
-#endif
- {
- if(decoder_session.decoder.file) {
- FLAC__file_decoder_finish(decoder_session.decoder.file);
- FLAC__file_decoder_delete(decoder_session.decoder.file);
- }
- }
- if(0 != decoder_session.fout && decoder_session.fout != stdout) {
- fclose(decoder_session.fout);
- unlink(outfilename);
- }
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(0 != decoder_session.fin && decoder_session.fin != stdin)
- fclose(decoder_session.fin);
- }
-#endif
- if(analysis_mode)
- flac__analyze_finish(aopts);
- return 1;
+ return DecoderSession_finish_ok(&decoder_session);
}
int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options)
{
- FLAC__bool md5_failure = false;
DecoderSession decoder_session;
decoder_session.is_big_endian = options.is_big_endian;
decoder_session.is_unsigned_samples = options.is_unsigned_samples;
- if(!DecoderSession_construct(options.common.verbose, /*is_wave_out=*/false, options.common.continue_through_decode_errors, analysis_mode, aopts, options.common.skip, infilename, outfilename))
+ if(!DecoderSession_construct(&decoder_session, options.common.is_ogg, options.common.verbose, /*is_wave_out=*/false, options.common.continue_through_decode_errors, analysis_mode, aopts, options.common.skip, infilename, outfilename))
return 1;
if(!DecoderSession_init_decoder(&decoder_session, infilename))
return DecoderSession_finish_error(&decoder_session);
- if(decoder_session.skip > 0) {
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) { /*@@@ (move this check into main.c) */
- fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", decoder_session.inbasefilename);
- goto raw_abort_;
- }
-#endif
- if(!FLAC__file_decoder_process_until_end_of_metadata(decoder_session.decoder.file)) {
- fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- if(decoder_session.abort_flag)
- goto raw_abort_;
- if(!FLAC__file_decoder_seek_absolute(decoder_session.decoder.file, decoder_session.skip)) {
- fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- if(!FLAC__file_decoder_process_until_end_of_file(decoder_session.decoder.file)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- if(FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- }
- else {
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(!OggFLAC__stream_decoder_process_until_end_of_stream(decoder_session.decoder.stream)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", decoder_session.inbasefilename, OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream), FLAC__StreamDecoderStateString[OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream)]);
- goto raw_abort_;
- }
- if(OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream), FLAC__StreamDecoderStateString[OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session.decoder.stream)]);
- goto raw_abort_;
- }
- }
- else
-#endif
- {
- if(!FLAC__file_decoder_process_until_end_of_file(decoder_session.decoder.file)) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- if(FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder_session.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
- if(decoder_session.verbose) fprintf(stderr, "\n");
- fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", decoder_session.inbasefilename, FLAC__file_decoder_get_state(decoder_session.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session.decoder.file)]);
- goto raw_abort_;
- }
- }
- }
+ if(!DecoderSession_process(&decoder_session))
+ return DecoderSession_finish_error(&decoder_session);
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(decoder_session.decoder.stream) {
- OggFLAC__stream_decoder_finish(decoder_session.decoder.stream);
- md5_failure = false;
- print_stats(&decoder_session);
- OggFLAC__stream_decoder_delete(decoder_session.decoder.stream);
- }
- }
- else
-#endif
- {
- if(decoder_session.decoder.file) {
- md5_failure = !FLAC__file_decoder_finish(decoder_session.decoder.file);
- print_stats(&decoder_session);
- FLAC__file_decoder_delete(decoder_session.decoder.file);
- }
- }
- if(0 != decoder_session.fout && decoder_session.fout != stdout)
- fclose(decoder_session.fout);
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(0 != decoder_session.fin && decoder_session.fin != stdin)
- fclose(decoder_session.fin);
- }
-#endif
- if(analysis_mode)
- flac__analyze_finish(aopts);
- if(md5_failure) {
- fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", decoder_session.inbasefilename);
- }
- else {
- if(decoder_session.verbose)
- fprintf(stderr, "\r%s: %s \n", decoder_session.inbasefilename, decoder_session.test_only? "ok ":analysis_mode?"done ":"done");
- }
- return 0;
-raw_abort_:
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(decoder_session.decoder.stream) {
- OggFLAC__stream_decoder_finish(decoder_session.decoder.stream);
- OggFLAC__stream_decoder_delete(decoder_session.decoder.stream);
- }
- }
- else
-#endif
- {
- if(decoder_session.decoder.file) {
- FLAC__file_decoder_finish(decoder_session.decoder.file);
- FLAC__file_decoder_delete(decoder_session.decoder.file);
- }
- }
- if(0 != decoder_session.fout && decoder_session.fout != stdout) {
- fclose(decoder_session.fout);
- unlink(outfilename);
- }
-#ifdef FLAC__HAS_OGG
- if(decoder_session.is_ogg) {
- if(0 != decoder_session.fin && decoder_session.fin != stdin)
- fclose(decoder_session.fin);
- }
-#endif
- if(analysis_mode)
- flac__analyze_finish(aopts);
- return 1;
+ return DecoderSession_finish_ok(&decoder_session);
}
-FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool verbose, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, FLAC_uint64 skip, const char *infilename, const char *outfilename)
+FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, FLAC__uint64 skip, const char *infilename, const char *outfilename)
{
#ifdef FLAC__HAS_OGG
- d->is_ogg = options.common.is_ogg;
+ d->is_ogg = is_ogg;
#endif
d->verbose = verbose;
- d->is_wave_out = true;
+ d->is_wave_out = is_wave_out;
d->continue_through_decode_errors = continue_through_decode_errors;
d->test_only = (0 == outfilename);
d->analysis_mode = analysis_mode;
d->aopts = aopts;
- d->skip = common.skip;
+ d->skip = skip;
d->inbasefilename = flac__file_get_basename(infilename);
+ d->outfilename = outfilename;
d->samples_processed = 0;
d->frame_counter = 0;
d->decoder.ogg.stream = 0;
#endif
+#ifdef FLAC__HAS_OGG
+ d->fin = 0;
+#endif
d->fout = 0; /* initialized with an open file later if necessary */
- FLAC__ASSERT(!(decoder_session.test_only && decoder_session.analysis_mode));
+ FLAC__ASSERT(!(d->test_only && d->analysis_mode));
if(!d->test_only) {
if(0 == strcmp(outfilename, "-")) {
else {
if(0 == (d->fout = fopen(outfilename, "wb"))) {
fprintf(stderr, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename);
- return 1;
+ DecoderSession_destroy(d, /*error_occurred=*/true);
+ return false;
}
}
}
} else {
if (0 == (d->fin = fopen(infilename, "rb"))) {
fprintf(stderr, "%s: ERROR: can't open input file %s\n", d->inbasefilename, infilename);
- if(0 != d->fout && d->fout != stdout)
- fclose(d->fout);
- return 1;
+ DecoderSession_destroy(d, /*error_occurred=*/true);
+ return false;
}
}
}
if(analysis_mode)
flac__analyze_init(aopts);
- return 0;
+ return true;
}
-void DecoderSession_destroy(DecoderSession *d)
+void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred)
{
+ if(0 != d->fout && d->fout != stdout) {
+ fclose(d->fout);
+ if(error_occurred)
+ unlink(d->outfilename);
+ }
+#ifdef FLAC__HAS_OGG
+ if(0 != d->fin && d->fin != stdin)
+ fclose(d->fin);
+#endif
}
FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, const char *infilename)
#ifdef FLAC__HAS_OGG
if(decoder_session->is_ogg) {
- decoder_session->decoder.stream = OggFLAC__stream_decoder_new();
+ decoder_session->decoder.ogg.stream = OggFLAC__stream_decoder_new();
- if(0 == decoder_session->decoder.stream) {
+ if(0 == decoder_session->decoder.ogg.stream) {
fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
return false;
}
- OggFLAC__stream_decoder_set_read_callback(decoder_session->decoder.stream, read_callback);
+ OggFLAC__stream_decoder_set_read_callback(decoder_session->decoder.ogg.stream, read_callback);
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
* the callback down to 'FLAC__StreamDecoder *'. In C++ this would be
* unnecessary but here the cast makes the C compiler happy.
*/
- OggFLAC__stream_decoder_set_write_callback(decoder_session->decoder.stream, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
- OggFLAC__stream_decoder_set_metadata_callback(decoder_session->decoder.stream, (void (*)(const OggFLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
- OggFLAC__stream_decoder_set_error_callback(decoder_session->decoder.stream, (void (*)(const OggFLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
- OggFLAC__stream_decoder_set_client_data(decoder_session->decoder.stream, decoder_session);
+ OggFLAC__stream_decoder_set_write_callback(decoder_session->decoder.ogg.stream, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
+ OggFLAC__stream_decoder_set_metadata_callback(decoder_session->decoder.ogg.stream, (void (*)(const OggFLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
+ OggFLAC__stream_decoder_set_error_callback(decoder_session->decoder.ogg.stream, (void (*)(const OggFLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
+ OggFLAC__stream_decoder_set_client_data(decoder_session->decoder.ogg.stream, decoder_session);
- if(OggFLAC__stream_decoder_init(decoder_session->decoder.stream) != OggFLAC__STREAM_DECODER_OK) {
- fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", decoder_session->inbasefilename, OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session->decoder.stream), FLAC__StreamDecoderStateString[OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_session->decoder.stream)]);
+ if(OggFLAC__stream_decoder_init(decoder_session->decoder.ogg.stream) != OggFLAC__STREAM_DECODER_OK) {
+ print_error_with_state(decoder_session, "ERROR initializing decoder");
return false;
}
}
else
#endif
{
- decoder_session->decoder.file = FLAC__file_decoder_new();
+ decoder_session->decoder.flac.file = FLAC__file_decoder_new();
- if(0 == decoder_session->decoder.file) {
+ if(0 == decoder_session->decoder.flac.file) {
fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
return false;
}
- FLAC__file_decoder_set_md5_checking(decoder_session->decoder.file, true);
- FLAC__file_decoder_set_filename(decoder_session->decoder.file, infilename);
+ FLAC__file_decoder_set_md5_checking(decoder_session->decoder.flac.file, true);
+ FLAC__file_decoder_set_filename(decoder_session->decoder.flac.file, infilename);
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
* the callback down to 'FLAC__FileDecoder *'.
*/
- FLAC__file_decoder_set_write_callback(decoder_session->decoder.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
- FLAC__file_decoder_set_metadata_callback(decoder_session->decoder.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
- FLAC__file_decoder_set_error_callback(decoder_session->decoder.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
- FLAC__file_decoder_set_client_data(decoder_session->decoder.file, decoder_session);
+ FLAC__file_decoder_set_write_callback(decoder_session->decoder.flac.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
+ FLAC__file_decoder_set_metadata_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
+ FLAC__file_decoder_set_error_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
+ FLAC__file_decoder_set_client_data(decoder_session->decoder.flac.file, decoder_session);
- if(FLAC__file_decoder_init(decoder_session->decoder.file) != FLAC__FILE_DECODER_OK) {
- fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", decoder_session->inbasefilename, FLAC__file_decoder_get_state(decoder_session->decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_session->decoder.file)]);
+ if(FLAC__file_decoder_init(decoder_session->decoder.flac.file) != FLAC__FILE_DECODER_OK) {
+ print_error_with_state(decoder_session, "ERROR initializing decoder");
return false;
}
}
return true;
}
-int DecoderSession_finish_ok(DecoderSession *d, int info_align_carry, int info_align_zero)
+FLAC__bool DecoderSession_process(DecoderSession *d)
{
+ if(d->skip > 0) {
+#ifdef FLAC__HAS_OGG
+ if(d->is_ogg) { /*@@@ (move this check into main.c) */
+ fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", d->inbasefilename);
+ return false;
+ }
+#endif
+ if(!FLAC__file_decoder_process_until_end_of_metadata(d->decoder.flac.file)) {
+ print_error_with_state(d, "ERROR while decoding metadata");
+ return false;
+ }
+ if(d->abort_flag)
+ return false;
+ if(!FLAC__file_decoder_seek_absolute(d->decoder.flac.file, d->skip)) {
+ print_error_with_state(d, "ERROR seeking while skipping bytes");
+ return false;
+ }
+ if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file)) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR while decoding frames");
+ return false;
+ }
+ if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR during decoding");
+ return false;
+ }
+ }
+ else {
+#ifdef FLAC__HAS_OGG
+ if(d->is_ogg) {
+ if(!OggFLAC__stream_decoder_process_until_end_of_stream(d->decoder.ogg.stream)) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR while decoding data");
+ return false;
+ }
+ if(OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR during decoding");
+ return false;
+ }
+ }
+ else
+#endif
+ {
+ if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file)) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR while decoding data");
+ return false;
+ }
+ if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
+ if(d->verbose) fprintf(stderr, "\n");
+ print_error_with_state(d, "ERROR during decoding");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+int DecoderSession_finish_ok(DecoderSession *d)
+{
+ FLAC__bool md5_failure = false;
+
+#ifdef FLAC__HAS_OGG
+ if(d->is_ogg) {
+ if(d->decoder.ogg.stream) {
+ OggFLAC__stream_decoder_finish(d->decoder.ogg.stream);
+ md5_failure = false;
+ print_stats(d);
+ OggFLAC__stream_decoder_delete(d->decoder.ogg.stream);
+ }
+ }
+ else
+#endif
+ {
+ if(d->decoder.flac.file) {
+ md5_failure = !FLAC__file_decoder_finish(d->decoder.flac.file);
+ print_stats(d);
+ FLAC__file_decoder_delete(d->decoder.flac.file);
+ }
+ }
+ if(d->analysis_mode)
+ flac__analyze_finish(d->aopts);
+ if(md5_failure) {
+ fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename);
+ }
+ else {
+ if(d->verbose)
+ fprintf(stderr, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done");
+ }
+ DecoderSession_destroy(d, /*error_occurred=*/false);
+ if(d->is_wave_out && d->wave_chunk_size_fixup.needs_fixup)
+ if(!fixup_wave_chunk_size(d->outfilename, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, (FLAC__uint32)d->samples_processed))
+ return 1;
+ return 0;
}
int DecoderSession_finish_error(DecoderSession *d)
{
+#ifdef FLAC__HAS_OGG
+ if(d->is_ogg) {
+ if(d->decoder.ogg.stream) {
+ OggFLAC__stream_decoder_finish(d->decoder.ogg.stream);
+ OggFLAC__stream_decoder_delete(d->decoder.ogg.stream);
+ }
+ }
+ else
+#endif
+ {
+ if(d->decoder.flac.file) {
+ FLAC__file_decoder_finish(d->decoder.flac.file);
+ FLAC__file_decoder_delete(d->decoder.flac.file);
+ }
+ }
+ if(d->analysis_mode)
+ flac__analyze_finish(d->aopts);
+ DecoderSession_destroy(d, /*error_occurred=*/true);
+ return 1;
}
FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val)
decoder_session->samples_processed += wide_samples;
decoder_session->frame_counter++;
- if(decoder_session->verbose && !(decoder_session->frame_counter & 0x7f))
+ if(decoder_session->verbose && !(decoder_session->frame_counter & 0x3f))
print_stats(decoder_session);
if(decoder_session->analysis_mode) {
DecoderSession *decoder_session = (DecoderSession*)client_data;
(void)decoder;
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
- /* remember, metadata->data.decoder_session.total_samples can be 0, meaning 'unknown' */
- if(metadata->data.decoder_session.total_samples > 0 && decoder_session->skip >= metadata->data.decoder_session.total_samples) {
+ /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
+ if(metadata->data.stream_info.total_samples > 0 && decoder_session->skip >= metadata->data.stream_info.total_samples) {
fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", decoder_session->inbasefilename);
decoder_session->abort_flag = true;
return;
}
- else if(metadata->data.decoder_session.total_samples == 0 && decoder_session->skip > 0) {
+ else if(metadata->data.stream_info.total_samples == 0 && decoder_session->skip > 0) {
fprintf(stderr, "%s: ERROR, can't skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename);
decoder_session->abort_flag = true;
return;
}
else
- decoder_session->total_samples = metadata->data.decoder_session.total_samples - decoder_session->skip;
- decoder_session->bps = metadata->data.decoder_session.bits_per_sample;
- decoder_session->channels = metadata->data.decoder_session.channels;
- decoder_session->sample_rate = metadata->data.decoder_session.sample_rate;
+ decoder_session->total_samples = metadata->data.stream_info.total_samples - decoder_session->skip;
+ decoder_session->bps = metadata->data.stream_info.bits_per_sample;
+ decoder_session->channels = metadata->data.stream_info.channels;
+ decoder_session->sample_rate = metadata->data.stream_info.sample_rate;
if(decoder_session->bps != 8 && decoder_session->bps != 16 && decoder_session->bps != 24) {
fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename);
decoder_session->abort_flag = true;
}
+void print_error_with_state(const DecoderSession *d, const char *message)
+{
+ const int ilen = strlen(d->inbasefilename) + 1;
+
+ fprintf(stderr, "\n%s: %s\n", d->inbasefilename, message);
+
+#ifdef FLAC__HAS_OGG
+ if(d->is_ogg) {
+ const OggFLAC__StreamDecoderState osd_state = OggFLAC__stream_decoder_get_state(d->decoder.ogg.stream);
+ if(osd_state != OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
+ fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)osd_state, OggFLAC__StreamDecoderStateString[osd_state]);
+ }
+ else {
+ const FLAC__StreamDecoderState fsd_state = OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream);
+ fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
+ }
+ }
+ else
+#endif
+ {
+ const FLAC__FileDecoderState ffd_state = FLAC__file_decoder_get_state(d->decoder.flac.file);
+ if(ffd_state != FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
+ fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)ffd_state, FLAC__FileDecoderStateString[ffd_state]);
+ }
+ else {
+ const FLAC__SeekableStreamDecoderState fssd_state = FLAC__file_decoder_get_seekable_stream_decoder_state(d->decoder.flac.file);
+ if(fssd_state != FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
+ fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fssd_state, FLAC__SeekableStreamDecoderStateString[fssd_state]);
+ }
+ else {
+ const FLAC__StreamDecoderState fsd_state = FLAC__file_decoder_get_stream_decoder_state(d->decoder.flac.file);
+ fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
+ }
+ }
+ }
+}
+
void print_stats(const DecoderSession *decoder_session)
{
if(decoder_session->verbose) {