diff options
author | Eric Fry | 2018-05-01 20:33:10 +1000 |
---|---|---|
committer | Eugene Sandulenko | 2018-07-20 06:43:33 +0000 |
commit | 5dd96b6fbe574d8ea2ec3710b46fe94779c3d3ce (patch) | |
tree | 90cf5f4664ef3be4b2f79eae5eb7324e324b6291 | |
parent | a7d78df98cdd0399d338c0077efc474d02678643 (diff) | |
download | scummvm-rg350-5dd96b6fbe574d8ea2ec3710b46fe94779c3d3ce.tar.gz scummvm-rg350-5dd96b6fbe574d8ea2ec3710b46fe94779c3d3ce.tar.bz2 scummvm-rg350-5dd96b6fbe574d8ea2ec3710b46fe94779c3d3ce.zip |
ILLUSIONS: Add midi music player
-rw-r--r-- | engines/illusions/duckman/scriptopcodes_duckman.cpp | 4 | ||||
-rw-r--r-- | engines/illusions/resources/backgroundresource.cpp | 2 | ||||
-rw-r--r-- | engines/illusions/sound.cpp | 91 | ||||
-rw-r--r-- | engines/illusions/sound.h | 26 |
4 files changed, 120 insertions, 3 deletions
diff --git a/engines/illusions/duckman/scriptopcodes_duckman.cpp b/engines/illusions/duckman/scriptopcodes_duckman.cpp index c864728062..c453aebd0a 100644 --- a/engines/illusions/duckman/scriptopcodes_duckman.cpp +++ b/engines/illusions/duckman/scriptopcodes_duckman.cpp @@ -623,11 +623,11 @@ void ScriptOpcodes_Duckman::opStopSound(ScriptThread *scriptThread, OpCall &opCa void ScriptOpcodes_Duckman::opStartMidiMusic(ScriptThread *scriptThread, OpCall &opCall) { ARG_SKIP(2); ARG_UINT32(musicId); - // TODO _vm->playMidiMusic(musicId); + _vm->_soundMan->playMidiMusic(musicId); } void ScriptOpcodes_Duckman::opStopMidiMusic(ScriptThread *scriptThread, OpCall &opCall) { - // TODO _vm->stopMidiMusic(); + _vm->_soundMan->stopMidiMusic(); } void ScriptOpcodes_Duckman::opFadeMidiMusic(ScriptThread *scriptThread, OpCall &opCall) { diff --git a/engines/illusions/resources/backgroundresource.cpp b/engines/illusions/resources/backgroundresource.cpp index 4df66e10f4..68bccf7ced 100644 --- a/engines/illusions/resources/backgroundresource.cpp +++ b/engines/illusions/resources/backgroundresource.cpp @@ -343,7 +343,7 @@ void BackgroundResource::load(byte *data, uint32 dataSize) { int BackgroundResource::findMasterBgIndex() { int index = 1; - while (!_bgInfos[index - 1]._flags & 1) + while (!_bgInfos[index - 1]._flags & 1) //TODO check if this is a typo ++index; return index; } diff --git a/engines/illusions/sound.cpp b/engines/illusions/sound.cpp index 5b1eea85f8..9379bf16c9 100644 --- a/engines/illusions/sound.cpp +++ b/engines/illusions/sound.cpp @@ -22,6 +22,7 @@ #include "illusions/illusions.h" #include "illusions/sound.h" +#include "audio/midiparser.h" namespace Illusions { @@ -72,6 +73,85 @@ bool MusicPlayer::isPlaying() { return (_flags & 1) && (_flags & 2) && g_system->getMixer()->isSoundHandleActive(_soundHandle); } +// MidiPlayer + +MidiPlayer::MidiPlayer() { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); + assert(_driver); + _paused = false; + + + int ret = _driver->open(); + if (ret == 0) { + _driver->sendGMReset(); + + _driver->setTimerCallback(this, &timerCallback); + } +} + +void MidiPlayer::play(const Common::String &filename) { + Common::StackLock lock(_mutex); + + stop(); + + Common::File *fd = new Common::File(); + if (!fd->open(filename)) { + delete fd; + error("MidiPlayer::play() Could not load %s", filename.c_str()); + } + + uint32 size = (uint32)fd->size(); + _midiData = (uint8 *)malloc(size); + + if (_midiData) { + fd->read(_midiData, size); + + syncVolume(); // FIXME: syncVolume calls setVolume which in turn also locks the mutex! ugh + + _parser = MidiParser::createParser_SMF(); + _parser->loadMusic(_midiData, size); + _parser->setTrack(0); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); + _isLooping = false; + _isPlaying = true; + } + fd->close(); + delete fd; +} + +void MidiPlayer::pause(bool p) { + _paused = p; + + for (int i = 0; i < kNumChannels; ++i) { + if (_channelsTable[i]) { + _channelsTable[i]->volume(_paused ? 0 : _channelsVolume[i] * _masterVolume / 255); + } + } +} + +void MidiPlayer::onTimer() { + Common::StackLock lock(_mutex); + + if (!_paused && _isPlaying && _parser) { + _parser->onTimer(); + } +} + +void MidiPlayer::sendToChannel(byte channel, uint32 b) { + if (!_channelsTable[channel]) { + _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); + // If a new channel is allocated during the playback, make sure + // its volume is correctly initialized. + if (_channelsTable[channel]) + _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255); + } + + if (_channelsTable[channel]) + _channelsTable[channel]->send(b); +} + // VoicePlayer VoicePlayer::VoicePlayer() { @@ -175,11 +255,13 @@ bool Sound::isPlaying() { SoundMan::SoundMan(IllusionsEngine *vm) : _vm(vm), _musicNotifyThreadId(0) { _musicPlayer = new MusicPlayer(); + _midiPlayer = new MidiPlayer(); _voicePlayer = new VoicePlayer(); } SoundMan::~SoundMan() { delete _musicPlayer; + delete _midiPlayer; delete _voicePlayer; unloadSounds(0); } @@ -264,4 +346,13 @@ Sound *SoundMan::getSound(uint32 soundEffectId) { return 0; } +void SoundMan::playMidiMusic(uint32 musicId) { + Common::String filename = Common::String::format("%08x.MID", musicId); + _midiPlayer->play(filename); +} + +void SoundMan::stopMidiMusic() { + _midiPlayer->stop(); +} + } // End of namespace Illusions diff --git a/engines/illusions/sound.h b/engines/illusions/sound.h index d2d91ac3c8..7979978c62 100644 --- a/engines/illusions/sound.h +++ b/engines/illusions/sound.h @@ -25,6 +25,7 @@ #include "illusions/graphics.h" #include "audio/audiostream.h" +#include "audio/midiplayer.h" #include "audio/mixer.h" #include "audio/decoders/wave.h" #include "common/list.h" @@ -46,6 +47,27 @@ protected: uint _flags; }; +class MidiPlayer : public Audio::MidiPlayer { +public: + MidiPlayer(); + + void pause(bool p); + void play(const Common::String &filename); + + // The following line prevents compiler warnings about hiding the pause() + // method from the parent class. + // FIXME: Maybe the pause(bool p) method should be removed and the + // pause/resume methods of the parent class be used instead? + virtual void pause() { Audio::MidiPlayer::pause(); } + + // Overload Audio::MidiPlayer method + virtual void sendToChannel(byte channel, uint32 b); + virtual void onTimer(); + +private: + bool _paused; +}; + class VoicePlayer { public: VoicePlayer(); @@ -90,6 +112,9 @@ public: void playMusic(uint32 musicId, int16 type, int16 volume, int16 pan, uint32 notifyThreadId); void stopMusic(); + void playMidiMusic(uint32 musicId); + void stopMidiMusic(); + bool cueVoice(const char *voiceName); void stopCueingVoice(); void startVoice(int16 volume, int16 pan); @@ -109,6 +134,7 @@ protected: IllusionsEngine *_vm; uint32 _musicNotifyThreadId; MusicPlayer *_musicPlayer; + MidiPlayer *_midiPlayer; VoicePlayer *_voicePlayer; SoundList _sounds; Sound *getSound(uint32 soundEffectId); |