📄 decode.c
字号:
/* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined _WIN32 && !defined __CYGWIN__/* where MSVC puts unlink() */# include <io.h>#else# include <unistd.h>#endif#include <errno.h>#include <math.h> /* for floor() */#include <stdio.h> /* for FILE et al. */#include <string.h> /* for strcmp() */#include "FLAC/all.h"#include "share/grabbag.h"#include "share/replaygain_synthesis.h"#include "decode.h"#ifdef FLAC__HAS_OGG#include "OggFLAC/file_decoder.h"#endiftypedef struct {#ifdef FLAC__HAS_OGG FLAC__bool is_ogg;#endif FLAC__bool is_aiff_out; FLAC__bool is_wave_out; FLAC__bool continue_through_decode_errors; struct { replaygain_synthesis_spec_t spec; FLAC__bool apply; /* 'spec.apply' is just a request; this 'apply' means we actually parsed the RG tags and are ready to go */ double scale; DitherContext dither_context; } replaygain; FLAC__bool test_only; FLAC__bool analysis_mode; analysis_options aopts; utils__SkipUntilSpecification *skip_specification; utils__SkipUntilSpecification *until_specification; /* a canonicalized value of 0 mean end-of-stream (i.e. --until=-0) */ utils__CueSpecification *cue_specification; const char *inbasefilename; const char *outfilename; FLAC__uint64 samples_processed; unsigned frame_counter; FLAC__bool abort_flag; FLAC__bool aborting_due_to_until; /* true if we intentionally abort decoding prematurely because we hit the --until point */ struct { FLAC__bool needs_fixup; unsigned riff_offset; /* or FORM offset for AIFF */ unsigned data_offset; /* or SSND offset for AIFF */ unsigned frames_offset; /* AIFF only */ } wave_chunk_size_fixup; FLAC__bool is_big_endian; FLAC__bool is_unsigned_samples; FLAC__uint64 total_samples; unsigned bps; unsigned channels; unsigned sample_rate; union { union { FLAC__FileDecoder *file; } flac;#ifdef FLAC__HAS_OGG union { OggFLAC__FileDecoder *file; } ogg;#endif } decoder; FILE *fout;} DecoderSession;static FLAC__bool is_big_endian_host_;/* * local routines */static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename);static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred);static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, decode_options_t decode_options, 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 canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);static FLAC__bool write_necessary_headers(DecoderSession *decoder_session);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__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val);static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val);static FLAC__bool write_sane_extended(FILE *f, unsigned val);static FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps);/* * We use 'void *' so that we can use the same callbacks for the * FLAC__StreamDecoder and FLAC__FileDecoder. The 'decoder' argument is * actually never used in the callbacks. */static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const 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);/* * public routines */int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options){ DecoderSession decoder_session; if(! DecoderSession_construct( &decoder_session,#ifdef FLAC__HAS_OGG options.common.is_ogg,#else /*is_ogg=*/false,#endif /*is_aiff_out=*/true, /*is_wave_out=*/false, options.common.continue_through_decode_errors, options.common.replaygain_synthesis_spec, analysis_mode, aopts, &options.common.skip_specification, &options.common.until_specification, options.common.has_cue_specification? &options.common.cue_specification : 0, infilename, outfilename ) ) return 1; if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) return DecoderSession_finish_error(&decoder_session); if(!DecoderSession_process(&decoder_session)) return DecoderSession_finish_error(&decoder_session); return DecoderSession_finish_ok(&decoder_session);}int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options){ DecoderSession decoder_session; if(! DecoderSession_construct( &decoder_session,#ifdef FLAC__HAS_OGG options.common.is_ogg,#else /*is_ogg=*/false,#endif /*is_aiff_out=*/false, /*is_wave_out=*/true, options.common.continue_through_decode_errors, options.common.replaygain_synthesis_spec, analysis_mode, aopts, &options.common.skip_specification, &options.common.until_specification, options.common.has_cue_specification? &options.common.cue_specification : 0, infilename, outfilename ) ) return 1; if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) return DecoderSession_finish_error(&decoder_session); if(!DecoderSession_process(&decoder_session)) return DecoderSession_finish_error(&decoder_session); 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){ DecoderSession decoder_session; decoder_session.is_big_endian = options.is_big_endian; decoder_session.is_unsigned_samples = options.is_unsigned_samples; if(! DecoderSession_construct( &decoder_session,#ifdef FLAC__HAS_OGG options.common.is_ogg,#else /*is_ogg=*/false,#endif /*is_aiff_out=*/false, /*is_wave_out=*/false, options.common.continue_through_decode_errors, options.common.replaygain_synthesis_spec, analysis_mode, aopts, &options.common.skip_specification, &options.common.until_specification, options.common.has_cue_specification? &options.common.cue_specification : 0, infilename, outfilename ) ) return 1; if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) return DecoderSession_finish_error(&decoder_session); if(!DecoderSession_process(&decoder_session)) return DecoderSession_finish_error(&decoder_session); return DecoderSession_finish_ok(&decoder_session);}FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename){#ifdef FLAC__HAS_OGG d->is_ogg = is_ogg;#else (void)is_ogg;#endif d->is_aiff_out = is_aiff_out; d->is_wave_out = is_wave_out; d->continue_through_decode_errors = continue_through_decode_errors; d->replaygain.spec = replaygain_synthesis_spec; d->replaygain.apply = false; d->replaygain.scale = 0.0; /* d->replaygain.dither_context gets initialized later once we know the sample resolution */ d->test_only = (0 == outfilename); d->analysis_mode = analysis_mode; d->aopts = aopts; d->skip_specification = skip_specification; d->until_specification = until_specification; d->cue_specification = cue_specification; d->inbasefilename = grabbag__file_get_basename(infilename); d->outfilename = outfilename; d->samples_processed = 0; d->frame_counter = 0; d->abort_flag = false; d->aborting_due_to_until = false; d->wave_chunk_size_fixup.needs_fixup = false; d->decoder.flac.file = 0;#ifdef FLAC__HAS_OGG d->decoder.ogg.file = 0;#endif d->fout = 0; /* initialized with an open file later if necessary */ FLAC__ASSERT(!(d->test_only && d->analysis_mode)); if(!d->test_only) { if(0 == strcmp(outfilename, "-")) { d->fout = grabbag__file_get_binary_stdout(); } else { if(0 == (d->fout = fopen(outfilename, "wb"))) { flac__utils_printf(stderr, 1, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename); DecoderSession_destroy(d, /*error_occurred=*/true); return false; } } } if(analysis_mode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -