diff --git a/src/modules/sound/lullaby/GmeDecoder.cpp b/src/modules/sound/lullaby/GmeDecoder.cpp new file mode 100644 index 000000000..e13b8ed8f --- /dev/null +++ b/src/modules/sound/lullaby/GmeDecoder.cpp @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2006-2012 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#include "common/config.h" + +#ifdef LOVE_SUPPORT_GME + +#include "common/Exception.h" +#include "GmeDecoder.h" + +namespace love +{ +namespace sound +{ +namespace lullaby +{ + +GmeDecoder::GmeDecoder(Data *data, const std::string &ext, int bufferSize) + : Decoder(data, ext, bufferSize) + , emu(0) + , num_tracks(0) + , cur_track(0) +{ + void *d = data->getData(); + int s = data->getSize(); + + if (gme_open_data(d, s, &emu, sampleRate) != 0) + throw love::Exception("Could not open game music file"); + + num_tracks = gme_track_count(emu); + + if (num_tracks <= 0) + throw love::Exception("Game music file has no tracks"); + + if (gme_start_track(emu, cur_track) != 0) + throw love::Exception("Could not start game music playback"); +} + +GmeDecoder::~GmeDecoder() +{ + if (emu) + gme_delete(emu); +} + +bool GmeDecoder::accepts(const std::string &ext) +{ + static const std::string supported[] = + { + "ay", "gbs", "gym", "hes", "kss", "nsf", + "nsfe", "sap", "spc", "vgm", "vgz" + }; + + for (int i = 0; !(supported[i].empty()); i++) + { + if (supported[i].compare(ext) == 0) + return true; + } + + return false; +} + +love::sound::Decoder *GmeDecoder::clone() +{ + return new GmeDecoder(data, ext, bufferSize); +} + +int GmeDecoder::decode() +{ + short *sbuf = static_cast(buffer); + int size = bufferSize / sizeof(short); + + if (gme_play(emu, size, sbuf) != 0) + throw love::Exception("Error while decoding game music"); + + if (!eof && gme_track_ended(emu)) + { + // Start the next track if this one ended. + if (cur_track < num_tracks - 1) + gme_start_track(emu, ++cur_track); + else + eof = true; + } + + return bufferSize; +} + +bool GmeDecoder::seek(float s) +{ + return gme_seek(emu, static_cast(s * 1000.f)) != 0; +} + +bool GmeDecoder::rewind() +{ + // If we're in the first track, rewind. + if (cur_track == 0) + return gme_seek(emu, 0) == 0; + else + { + // Otherwise, start from the first track again. + cur_track = 0; + return gme_start_track(emu, cur_track) == 0; + } +} + +bool GmeDecoder::isSeekable() +{ + return true; +} + +int GmeDecoder::getChannels() const +{ + return 2; +} + +int GmeDecoder::getBits() const +{ + return 16; +} + +} // lullaby +} // sound +} // love + +#endif // LOVE_SUPPORT_GME \ No newline at end of file diff --git a/src/modules/sound/lullaby/GmeDecoder.h b/src/modules/sound/lullaby/GmeDecoder.h new file mode 100644 index 000000000..311d5ef8a --- /dev/null +++ b/src/modules/sound/lullaby/GmeDecoder.h @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2006-2012 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#ifndef LOVE_SOUND_LULLABY_GME_DECODER_H +#define LOVE_SOUND_LULLABY_GME_DECODER_H + +#ifdef LOVE_SUPPORT_GME + +// LOVE +#include "common/Data.h" +#include "Decoder.h" + +#include + +namespace love +{ +namespace sound +{ +namespace lullaby +{ + +class GmeDecoder : public Decoder +{ +public: + + GmeDecoder(Data *data, const std::string &ext, int bufferSize); + virtual ~GmeDecoder(); + + static bool accepts(const std::string &ext); + + love::sound::Decoder *clone(); + int decode(); + bool seek(float s); + bool rewind(); + bool isSeekable(); + int getChannels() const; + int getBits() const; + +private: + Music_Emu *emu; + int num_tracks; + int cur_track; +}; // Decoder + +} // lullaby +} // sound +} // love + +#endif // LOVE_SUPPORT_GME + +#endif // LOVE_SOUND_LULLABY_GME_DECODER_H diff --git a/src/modules/sound/lullaby/Sound.cpp b/src/modules/sound/lullaby/Sound.cpp index a4b1c8ac3..33c98954c 100644 --- a/src/modules/sound/lullaby/Sound.cpp +++ b/src/modules/sound/lullaby/Sound.cpp @@ -18,11 +18,14 @@ * 3. This notice may not be removed or altered from any source distribution. **/ +#include "common/config.h" + #include "Sound.h" #include "ModPlugDecoder.h" #include "Mpg123Decoder.h" #include "VorbisDecoder.h" +#include "GmeDecoder.h" //#include "FLACDecoder.h" namespace love @@ -64,6 +67,10 @@ sound::Decoder *Sound::newDecoder(love::filesystem::File *file, int bufferSize) #endif // LOVE_NOMPG123 else if (VorbisDecoder::accepts(ext)) decoder = new VorbisDecoder(data, ext, bufferSize); +#ifdef LOVE_SUPPORT_GME + else if (GmeDecoder::accepts(ext)) + decoder = new GmeDecoder(data, ext, bufferSize); +#endif // LOVE_SUPPORT_GME /*else if (FLACDecoder::accepts(ext)) decoder = new FLACDecoder(data, ext, bufferSize);*/