foo_asap.cpp
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:5k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * foo_asap.cpp - ASAP plugin for foobar2000
  3.  *
  4.  * Copyright (C) 2006  Piotr Fusik
  5.  *
  6.  * This file is part of ASAP (Another Slight Atari Player),
  7.  * see http://asap.sourceforge.net
  8.  *
  9.  * ASAP is free software; you can redistribute it and/or modify it
  10.  * under the terms of the GNU General Public License as published
  11.  * by the Free Software Foundation; either version 2 of the License,
  12.  * or (at your option) any later version.
  13.  *
  14.  * ASAP is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty
  16.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17.  * See the GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with ASAP; if not, write to the Free Software Foundation, Inc.,
  21.  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  22.  */
  23. #include "config.h"
  24. #define FREQUENCY          44100
  25. #define BITS_PER_SAMPLE    16
  26. #define QUALITY            1
  27. #define BUFFERED_BLOCKS    576
  28. #define SUPPORT_SUBSONGS   1
  29. #include "foobar2000/SDK/componentversion.h"
  30. #include "foobar2000/SDK/input.h"
  31. #if SUPPORT_SUBSONGS
  32. #include "foobar2000/SDK/playlist_loader.h"
  33. #endif
  34. #include "asap.h"
  35. #define EXT(c1, c2, c3) ((c1 + (c2 << 8) + (c3 << 16)) | 0x202020)
  36. static bool is_our_file(const char *filename)
  37. {
  38. const char *p;
  39. int ext;
  40. for (p = filename; *p != ''; p++);
  41. ext = 0;
  42. for (;;) {
  43. if (--p <= filename || *p < ' ')
  44. return false; /* no filename extension or invalid character */
  45. if (*p == '.')
  46. break;
  47. ext = (ext << 8) + (*p & 0xff);
  48. }
  49. switch (ext | 0x202020) {
  50. case EXT('C', 'M', 'C'):
  51. case EXT('C', 'M', 'R'):
  52. case EXT('D', 'M', 'C'):
  53. case EXT('M', 'P', 'D'):
  54. case EXT('M', 'P', 'T'):
  55. case EXT('R', 'M', 'T'):
  56. case EXT('S', 'A', 'P'):
  57. case EXT('T', 'M', 'C'):
  58. #ifdef STEREO_SOUND
  59. case EXT('T', 'M', '8'):
  60. #endif
  61. case EXT('T', 'M', '2'):
  62. return true;
  63. default:
  64. return false;
  65. }
  66. }
  67. static unsigned int channels;
  68. static unsigned int buffered_bytes;
  69. static int open_asap(const char *filename, reader *r)
  70. {
  71. ::buffered_bytes = 0;
  72. static bool initialized = false;
  73. if (!initialized) {
  74. ::ASAP_Initialize(FREQUENCY,
  75. BITS_PER_SAMPLE == 8 ? AUDIO_FORMAT_U8 : AUDIO_FORMAT_S16_NE,
  76. QUALITY);
  77. initialized = true;
  78. }
  79. static unsigned char module[65000];
  80. unsigned int module_len;
  81. #if SUPPORT_SUBSONGS
  82. if (r == NULL) {
  83. r = file::g_open_read(filename);
  84. if (r == NULL)
  85. return 0;
  86. module_len = r->read(module, sizeof(module));
  87. r->reader_release();
  88. }
  89. else
  90. #endif
  91. module_len = r->read(module, sizeof(module));
  92. return ::ASAP_Load(filename, module, module_len);
  93. }
  94. static
  95. #if BITS_PER_SAMPLE == 8
  96. unsigned char
  97. #else
  98. short int
  99. #endif
  100. buffer[BUFFERED_BLOCKS * 2];
  101. class input_asap : public input
  102. {
  103. public:
  104. bool test_filename(const char *full_path, const char *extension) { return ::is_our_file(full_path); }
  105. set_info_t set_info(reader *r, const file_info *info) { return SET_INFO_FAILURE; }
  106. bool open(reader *r, file_info *info, unsigned flags);
  107. bool can_seek() { return false; }
  108. bool seek(double seconds) { return false; }
  109. int run(audio_chunk *chunk);
  110. };
  111. bool input_asap::open(reader *r, file_info *info, unsigned flags)
  112. {
  113. if (!::open_asap(info->get_file_path(), r))
  114. return false;
  115. if ((flags & OPEN_FLAG_DECODE) == 0)
  116. return true;
  117. ::ASAP_PlaySong(
  118. #if SUPPORT_SUBSONGS
  119. info->get_subsong_index()
  120. #else
  121. ::ASAP_GetDefSong()
  122. #endif
  123. );
  124. ::channels = ::ASAP_GetChannels();
  125. ::buffered_bytes = BUFFERED_BLOCKS * ::channels * (BITS_PER_SAMPLE / 8);
  126. return true;
  127. }
  128. int input_asap::run(audio_chunk *chunk)
  129. {
  130. if (::buffered_bytes == 0)
  131. return 0;
  132. ::ASAP_Generate(::buffer, ::buffered_bytes);
  133. chunk->set_data_fixedpoint(::buffer, ::buffered_bytes, FREQUENCY, ::channels, BITS_PER_SAMPLE);
  134. return 1;
  135. }
  136. static service_factory_single_t<input,input_asap> foo;
  137. DECLARE_COMPONENT_VERSION("ASAP", ASAP_VERSION, ASAP_CREDITS "n" ASAP_COPYRIGHT);
  138. static const char * const names_and_masks[][2] = {
  139. { "Slight Atari Player (*.sap)", "*.SAP" },
  140. { "Chaos Music Composer (*.cmc;*.cmr;*.dmc)", "*.CMC;*.CMR;*.DMC" },
  141. { "Music ProTracker (*.mpt;*.mpd)", "*.MPT;*.MPD" },
  142. { "Raster Music Tracker (*.rmt)", "*.RMT" },
  143. #ifdef STEREO_SOUND
  144. { "Theta Music Composer 1.x (*.tmc;*.tm8)", "*.TMC;*.TM8" },
  145. #else
  146. { "Theta Music Composer 1.x (*.tmc)", "*.TMC" },
  147. #endif
  148. { "Theta Music Composer 2.x (*.tm2)", "*.TM2" }
  149. };
  150. #define N_FILE_TYPES (sizeof(names_and_masks) / sizeof(names_and_masks[0]))
  151. class input_file_type_asap : public service_impl_single_t<input_file_type>
  152. {
  153. public:
  154. virtual unsigned get_count() { return N_FILE_TYPES; }
  155. virtual bool get_name(unsigned idx, string_base &out)
  156. {
  157. if (idx < N_FILE_TYPES) { out = ::names_and_masks[idx][0]; return true; }
  158. return false;
  159. }
  160. virtual bool get_mask(unsigned idx, string_base &out)
  161. {
  162. if (idx < N_FILE_TYPES) { out = ::names_and_masks[idx][1]; return true; }
  163. return false;
  164. }
  165. };
  166. static service_factory_single_t<input_file_type,input_file_type_asap> foo2;
  167. #if SUPPORT_SUBSONGS
  168. class indexer_asap : public track_indexer
  169. {
  170. public:
  171. virtual int get_tracks(const char *filename, callback *out, reader *r)
  172. {
  173. if (!::is_our_file(filename))
  174. return 0;
  175. if (::open_asap(filename, r) == 0)
  176. return 0;
  177. unsigned int d = ::ASAP_GetDefSong();
  178. out->on_entry(make_playable_location(filename, (int) d));
  179. unsigned int n = ::ASAP_GetSongs();
  180. unsigned int i;
  181. for (i = 0; i < n; i++)
  182. if (i != d)
  183. out->on_entry(make_playable_location(filename, (int) i));
  184. return 1;
  185. }
  186. };
  187. static service_factory_single_t<track_indexer,indexer_asap> foo3;
  188. #endif /* SUPPORT_SUBSONGS */