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

📄 foo_asap.cpp

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 CPP
字号:
/*
 * foo_asap.cpp - ASAP plugin for foobar2000
 *
 * Copyright (C) 2006  Piotr Fusik
 *
 * This file is part of ASAP (Another Slight Atari Player),
 * see http://asap.sourceforge.net
 *
 * ASAP 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.
 *
 * ASAP 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 ASAP; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"

#define FREQUENCY          44100
#define BITS_PER_SAMPLE    16
#define QUALITY            1
#define BUFFERED_BLOCKS    576
#define SUPPORT_SUBSONGS   1

#include "foobar2000/SDK/componentversion.h"
#include "foobar2000/SDK/input.h"
#if SUPPORT_SUBSONGS
#include "foobar2000/SDK/playlist_loader.h"
#endif

#include "asap.h"

#define EXT(c1, c2, c3) ((c1 + (c2 << 8) + (c3 << 16)) | 0x202020)

static bool is_our_file(const char *filename)
{
	const char *p;
	int ext;
	for (p = filename; *p != '\0'; p++);
	ext = 0;
	for (;;) {
		if (--p <= filename || *p < ' ')
			return false; /* no filename extension or invalid character */
		if (*p == '.')
			break;
		ext = (ext << 8) + (*p & 0xff);
	}
	switch (ext | 0x202020) {
	case EXT('C', 'M', 'C'):
	case EXT('C', 'M', 'R'):
	case EXT('D', 'M', 'C'):
	case EXT('M', 'P', 'D'):
	case EXT('M', 'P', 'T'):
	case EXT('R', 'M', 'T'):
	case EXT('S', 'A', 'P'):
	case EXT('T', 'M', 'C'):
#ifdef STEREO_SOUND
	case EXT('T', 'M', '8'):
#endif
	case EXT('T', 'M', '2'):
		return true;
	default:
		return false;
	}
}

static unsigned int channels;
static unsigned int buffered_bytes;

static int open_asap(const char *filename, reader *r)
{
	::buffered_bytes = 0;
	static bool initialized = false;
	if (!initialized) {
		::ASAP_Initialize(FREQUENCY,
			BITS_PER_SAMPLE == 8 ? AUDIO_FORMAT_U8 : AUDIO_FORMAT_S16_NE,
			QUALITY);
		initialized = true;
	}
	static unsigned char module[65000];
	unsigned int module_len;
#if SUPPORT_SUBSONGS
	if (r == NULL) {
		r = file::g_open_read(filename);
		if (r == NULL)
			return 0;
		module_len = r->read(module, sizeof(module));
		r->reader_release();
	}
	else
#endif
		module_len = r->read(module, sizeof(module));
	return ::ASAP_Load(filename, module, module_len);
}

static
#if BITS_PER_SAMPLE == 8
	unsigned char
#else
	short int
#endif
	buffer[BUFFERED_BLOCKS * 2];

class input_asap : public input
{
public:
	bool test_filename(const char *full_path, const char *extension) { return ::is_our_file(full_path); }
	set_info_t set_info(reader *r, const file_info *info) { return SET_INFO_FAILURE; }
	bool open(reader *r, file_info *info, unsigned flags);
	bool can_seek() { return false; }
	bool seek(double seconds) { return false; }
	int run(audio_chunk *chunk);
};

bool input_asap::open(reader *r, file_info *info, unsigned flags)
{
	if (!::open_asap(info->get_file_path(), r))
		return false;
	if ((flags & OPEN_FLAG_DECODE) == 0)
		return true;
	::ASAP_PlaySong(
#if SUPPORT_SUBSONGS
		info->get_subsong_index()
#else
		::ASAP_GetDefSong()
#endif
	);
	::channels = ::ASAP_GetChannels();
	::buffered_bytes = BUFFERED_BLOCKS * ::channels * (BITS_PER_SAMPLE / 8);
	return true;
}

int input_asap::run(audio_chunk *chunk)
{
	if (::buffered_bytes == 0)
		return 0;
	::ASAP_Generate(::buffer, ::buffered_bytes);
	chunk->set_data_fixedpoint(::buffer, ::buffered_bytes, FREQUENCY, ::channels, BITS_PER_SAMPLE);
	return 1;
}

static service_factory_single_t<input,input_asap> foo;

DECLARE_COMPONENT_VERSION("ASAP", ASAP_VERSION, ASAP_CREDITS "\n" ASAP_COPYRIGHT);

static const char * const names_and_masks[][2] = {
	{ "Slight Atari Player (*.sap)", "*.SAP" },
	{ "Chaos Music Composer (*.cmc;*.cmr;*.dmc)", "*.CMC;*.CMR;*.DMC" },
	{ "Music ProTracker (*.mpt;*.mpd)", "*.MPT;*.MPD" },
	{ "Raster Music Tracker (*.rmt)", "*.RMT" },
#ifdef STEREO_SOUND
	{ "Theta Music Composer 1.x (*.tmc;*.tm8)", "*.TMC;*.TM8" },
#else
	{ "Theta Music Composer 1.x (*.tmc)", "*.TMC" },
#endif
	{ "Theta Music Composer 2.x (*.tm2)", "*.TM2" }
};

#define N_FILE_TYPES (sizeof(names_and_masks) / sizeof(names_and_masks[0]))

class input_file_type_asap : public service_impl_single_t<input_file_type>
{
public:
	virtual unsigned get_count() { return N_FILE_TYPES; }
	virtual bool get_name(unsigned idx, string_base &out)
	{
		if (idx < N_FILE_TYPES) { out = ::names_and_masks[idx][0]; return true; }
		return false;
	}
	virtual bool get_mask(unsigned idx, string_base &out)
	{
		if (idx < N_FILE_TYPES) { out = ::names_and_masks[idx][1]; return true; }
		return false;
	}
};

static service_factory_single_t<input_file_type,input_file_type_asap> foo2;

#if SUPPORT_SUBSONGS

class indexer_asap : public track_indexer
{
public:
	virtual int get_tracks(const char *filename, callback *out, reader *r)
	{
		if (!::is_our_file(filename))
			return 0;
		if (::open_asap(filename, r) == 0)
			return 0;
		unsigned int d = ::ASAP_GetDefSong();
		out->on_entry(make_playable_location(filename, (int) d));
		unsigned int n = ::ASAP_GetSongs();
		unsigned int i;
		for (i = 0; i < n; i++)
			if (i != d)
				out->on_entry(make_playable_location(filename, (int) i));
		return 1;
	}
};

static service_factory_single_t<track_indexer,indexer_asap> foo3;

#endif /* SUPPORT_SUBSONGS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -