⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 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"
#endif

typedef 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 + -