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); | 
