📄 decode.c
字号:
flac__analyze_init(aopts);
return true;
}
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);
}
}
FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_options_t decode_options, const char *infilename)
{
FLAC__uint32 test = 1;
is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
#ifdef FLAC__HAS_OGG
if(decoder_session->is_ogg) {
decoder_session->decoder.ogg.file = OggFLAC__file_decoder_new();
if(0 == decoder_session->decoder.ogg.file) {
flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
return false;
}
OggFLAC__file_decoder_set_md5_checking(decoder_session->decoder.ogg.file, true);
OggFLAC__file_decoder_set_filename(decoder_session->decoder.ogg.file, infilename);
if(!decode_options.use_first_serial_number)
OggFLAC__file_decoder_set_serial_number(decoder_session->decoder.ogg.file, decode_options.serial_number);
if (0 != decoder_session->cue_specification)
OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_CUESHEET);
if (decoder_session->replaygain.spec.apply)
OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_VORBIS_COMMENT);
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
* the callback down to 'OggFLAC__FileDecoder *'. In C++ this would be
* unnecessary but here the cast makes the C compiler happy.
*/
OggFLAC__file_decoder_set_write_callback(decoder_session->decoder.ogg.file, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
OggFLAC__file_decoder_set_metadata_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
OggFLAC__file_decoder_set_error_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
OggFLAC__file_decoder_set_client_data(decoder_session->decoder.ogg.file, decoder_session);
if(OggFLAC__file_decoder_init(decoder_session->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK) {
print_error_with_state(decoder_session, "ERROR initializing decoder");
return false;
}
}
else
#else
(void)decode_options;
#endif
{
decoder_session->decoder.flac.file = FLAC__file_decoder_new();
if(0 == decoder_session->decoder.flac.file) {
flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
return false;
}
FLAC__file_decoder_set_md5_checking(decoder_session->decoder.flac.file, true);
FLAC__file_decoder_set_filename(decoder_session->decoder.flac.file, infilename);
if (0 != decoder_session->cue_specification)
FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_CUESHEET);
if (decoder_session->replaygain.spec.apply)
FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_VORBIS_COMMENT);
/*
* 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.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.flac.file) != FLAC__FILE_DECODER_OK) {
print_error_with_state(decoder_session, "ERROR initializing decoder");
return false;
}
}
return true;
}
FLAC__bool DecoderSession_process(DecoderSession *d)
{
#ifdef FLAC__HAS_OGG
if(d->is_ogg) {
if(!OggFLAC__file_decoder_process_until_end_of_metadata(d->decoder.ogg.file)) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR while decoding metadata");
return false;
}
if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR during metadata decoding");
return false;
}
}
else
#endif
{
if(!FLAC__file_decoder_process_until_end_of_metadata(d->decoder.flac.file)) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR while decoding metadata");
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) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR during metadata decoding");
return false;
}
}
if(d->abort_flag)
return false;
/* write the WAVE/AIFF headers if necessary */
if(!write_necessary_headers(d)) {
d->abort_flag = true;
return false;
}
if(d->skip_specification->value.samples > 0) {
const FLAC__uint64 skip = (FLAC__uint64)d->skip_specification->value.samples;
#ifdef FLAC__HAS_OGG
if(d->is_ogg) {
if(!OggFLAC__file_decoder_seek_absolute(d->decoder.ogg.file, skip)) {
print_error_with_state(d, "ERROR seeking while skipping bytes");
return false;
}
if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR while decoding frames");
return false;
}
if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR during decoding");
return false;
}
}
else
#endif
{
if(!FLAC__file_decoder_seek_absolute(d->decoder.flac.file, 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) && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\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 && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR during decoding");
return false;
}
}
}
else {
#ifdef FLAC__HAS_OGG
if(d->is_ogg) {
if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR while decoding data");
return false;
}
if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\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) && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\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 && !d->aborting_due_to_until) {
flac__utils_printf(stderr, 2, "\n");
print_error_with_state(d, "ERROR during decoding");
return false;
}
}
}
if((d->is_wave_out || d->is_aiff_out) && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) {
if(flac__utils_fwrite("\000", 1, 1, d->fout) != 1) {
print_error_with_state(d, d->is_wave_out?
"ERROR writing pad byte to WAVE data chunk" :
"ERROR writing pad byte to AIFF SSND chunk"
);
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.file) {
md5_failure = !OggFLAC__file_decoder_finish(d->decoder.ogg.file) && !d->aborting_due_to_until;
print_stats(d);
OggFLAC__file_decoder_delete(d->decoder.ogg.file);
}
}
else
#endif
{
if(d->decoder.flac.file) {
md5_failure = !FLAC__file_decoder_finish(d->decoder.flac.file) && !d->aborting_due_to_until;
print_stats(d);
FLAC__file_decoder_delete(d->decoder.flac.file);
}
}
if(d->analysis_mode)
flac__analyze_finish(d->aopts);
if(md5_failure) {
flac__utils_printf(stderr, 1, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename);
}
else {
flac__utils_printf(stderr, 2, "\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->is_aiff_out) && d->wave_chunk_size_fixup.needs_fixup)
if(!fixup_wave_chunk_size(d->outfilename, d->is_wave_out, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, d->wave_chunk_size_fixup.frames_offset, (FLAC__uint32)d->samples_processed, d->channels, d->bps))
return 1;
return 0;
}
int DecoderSession_finish_error(DecoderSession *d)
{
#ifdef FLAC__HAS_OGG
if(d->is_ogg) {
if(d->decoder.ogg.file) {
OggFLAC__file_decoder_finish(d->decoder.ogg.file);
OggFLAC__file_decoder_delete(d->decoder.ogg.file);
}
}
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 canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input)
{
/* convert from mm:ss.sss to sample number if necessary */
flac__utils_canonicalize_skip_until_specification(spec, sample_rate);
/* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */
if(spec->is_relative && spec->value.samples == 0) {
spec->is_relative = false;
return true;
}
/* in any other case the total samples in the input must be known */
if(total_samples_in_input == 0) {
flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename);
return false;
}
FLAC__ASSERT(spec->value_is_samples);
/* convert relative specifications to absolute */
if(spec->is_relative) {
if(spec->value.samples <= 0)
spec->value.samples += (FLAC__int64)total_samples_in_input;
else
spec->value.samples += skip;
spec->is_relative = false;
}
/* error check */
if(spec->value.samples < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before beginning of input\n", inbasefilename);
return false;
}
if((FLAC__uint64)spec->value.samples <= skip) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -