diff options
author | Robert Špalek | 2009-10-21 08:41:57 +0000 |
---|---|---|
committer | Robert Špalek | 2009-10-21 08:41:57 +0000 |
commit | 8d8b4dc50a4ad235c3692a2d136e5e4c64d8f4d4 (patch) | |
tree | 2e4c25d0cd20d778e505f7e3973c024270560a72 | |
parent | 9785eca16b3d3ff901cba5a917b267ee50df2dcf (diff) | |
download | scummvm-rg350-8d8b4dc50a4ad235c3692a2d136e5e4c64d8f4d4.tar.gz scummvm-rg350-8d8b4dc50a4ad235c3692a2d136e5e4c64d8f4d4.tar.bz2 scummvm-rg350-8d8b4dc50a4ad235c3692a2d136e5e4c64d8f4d4.zip |
Enabled music.
Several TODO's added.
svn-id: r45298
-rw-r--r-- | engines/draci/draci.cpp | 18 | ||||
-rw-r--r-- | engines/draci/draci.h | 4 | ||||
-rw-r--r-- | engines/draci/game.cpp | 6 | ||||
-rw-r--r-- | engines/draci/module.mk | 1 | ||||
-rw-r--r-- | engines/draci/music.cpp | 213 | ||||
-rw-r--r-- | engines/draci/music.h | 101 |
6 files changed, 343 insertions, 0 deletions
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index 4c52398737..19732e7687 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -61,6 +61,7 @@ const char *initPath = "INIT.DFW"; const char *stringsPath = "RETEZCE.DFW"; const char *soundsPath = "CD2.SAM"; const char *dubbingPath = "CD.SAM"; +const char *musicPathMask = "HUDBA%d.MID"; const uint kSoundsFrequency = 13000; const uint kDubbingFrequency = 22000; @@ -117,6 +118,18 @@ int DraciEngine::init() { _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency); _sound = new Sound(_mixer); + int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (midiDriver == MD_ADLIB); + + _midiDriver = MidiDriver::createMidi(midiDriver); + if (native_mt32) + _midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + + _music = new MusicPlayer(_midiDriver, musicPathMask); + _music->setNativeMT32(native_mt32); + //_music->setAdlib(adlib); + // Load the game's fonts _smallFont = new Font(kFontSmall); _bigFont = new Font(kFontBig); @@ -303,6 +316,8 @@ DraciEngine::~DraciEngine() { delete _soundsArchive; delete _dubbingArchive; delete _sound; + delete _music; + delete _midiDriver; // Remove all of our debug levels here Common::clearAllDebugChannels(); @@ -332,10 +347,12 @@ void DraciEngine::pauseEngineIntern(bool pause) { _anims->pauseAnimations(); _sound->pauseSound(); _sound->pauseVoice(); + _music->pause(); } else { _anims->unpauseAnimations(); _sound->resumeSound(); _sound->resumeVoice(); + _music->resume(); // Adjust engine start time const int delta = _system->getMillis() - _pauseStartTime; @@ -349,6 +366,7 @@ void DraciEngine::syncSoundSettings() { Engine::syncSoundSettings(); _sound->setVolume(); + _music->setVolume(ConfMan.getInt("music_volume")); } const char *DraciEngine::getSavegameFile(int saveGameIdx) { diff --git a/engines/draci/draci.h b/engines/draci/draci.h index 6ef339de33..8de37ac312 100644 --- a/engines/draci/draci.h +++ b/engines/draci/draci.h @@ -29,6 +29,7 @@ #include "common/system.h" #include "engines/engine.h" #include "engines/advancedDetector.h" +#include "sound/mididrv.h" #include "draci/game.h" #include "draci/mouse.h" @@ -38,6 +39,7 @@ #include "draci/barchive.h" #include "draci/animation.h" #include "draci/sound.h" +#include "draci/music.h" namespace Draci { @@ -67,6 +69,8 @@ public: Script *_script; AnimationManager *_anims; Sound *_sound; + MusicPlayer *_music; + MidiDriver *_midiDriver; Font *_smallFont; Font *_bigFont; diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 1694d81cf0..773f97ce64 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -1123,6 +1123,12 @@ void Game::loadRoom(int roomNum) { Animation *map = _vm->_anims->addAnimation(kWalkingMapOverlay, 255, false); map->addFrame(ov, NULL); + + if (_currentRoom._music) { + _vm->_music->playSMF(_currentRoom._music, true); + } else { + _vm->_music->stop(); + } } int Game::loadAnimation(uint animNum, uint z) { diff --git a/engines/draci/module.mk b/engines/draci/module.mk index 1810ddff2f..2005c0b095 100644 --- a/engines/draci/module.mk +++ b/engines/draci/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ font.o \ saveload.o \ sound.o \ + music.o \ sprite.o \ screen.o \ surface.o \ diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp new file mode 100644 index 0000000000..b63c171974 --- /dev/null +++ b/engines/draci/music.cpp @@ -0,0 +1,213 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/made/music.cpp $ + * $Id: music.cpp 35843 2009-01-13 10:11:52Z thebluegr $ + * + */ + +// FIXME: This code is taken from SAGA and needs more work (e.g. setVolume). + +// MIDI and digital music class + +#include "sound/audiostream.h" +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/config-manager.h" +#include "common/file.h" + +#include "draci/draci.h" +#include "draci/music.h" + +namespace Draci { + +MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), _driver(driver), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) { + memset(_channel, 0, sizeof(_channel)); + _masterVolume = 0; + this->open(); + _smfParser = MidiParser::createParser_SMF(); + _midiMusicData = NULL; +} + +MusicPlayer::~MusicPlayer() { + _driver->setTimerCallback(NULL, NULL); + stop(); + this->close(); + _smfParser->setMidiDriver(NULL); + delete _smfParser; + delete _midiMusicData; +} + +void MusicPlayer::setVolume(int volume) { + volume = CLIP(volume, 0, 255); + + if (_masterVolume == volume) + return; + + _masterVolume = volume; + + Common::StackLock lock(_mutex); + + for (int i = 0; i < 16; ++i) { + if (_channel[i]) { + _channel[i]->volume(_channelVolume[i] * _masterVolume / 255); + } + } +} + +int MusicPlayer::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; + + int ret = _driver->open(); + if (ret) + return ret; + + _driver->setTimerCallback(this, &onTimer); + return 0; +} + +void MusicPlayer::close() { + stop(); + if (_driver) + _driver->close(); + _driver = 0; +} + +void MusicPlayer::send(uint32 b) { + if (_passThrough) { + _driver->send(b); + return; + } + + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { + b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; + } + else if ((b & 0xFFF0) == 0x007BB0) { + //Only respond to All Notes Off if this channel + //has currently been allocated + if (_channel[b & 0x0F]) + return; + } + + if (!_channel[channel]) + _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); + + if (_channel[channel]) + _channel[channel]->send(b); +} + +void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { + + switch (type) { + case 0x2F: // End of Track + if (_looping) + _parser->jumpToTick(0); + else + stop(); + break; + default: + //warning("Unhandled meta event: %02x", type); + break; + } +} + +void MusicPlayer::onTimer(void *refCon) { + MusicPlayer *music = (MusicPlayer *)refCon; + Common::StackLock lock(music->_mutex); + + if (music->_isPlaying) + music->_parser->onTimer(); +} + +void MusicPlayer::playSMF(int track, bool loop) { + if (_isPlaying && track == _track) + return; + + stop(); + + _isGM = true; + + debugC(2, kDraciSoundDebugLevel, "Playing track %d", track); + + // Load MIDI resource data + Common::File musicFile; + char musicFileName[40]; + sprintf(musicFileName, _pathMask.c_str(), track); + musicFile.open(musicFileName); + int midiMusicSize = musicFile.size(); + delete _midiMusicData; + _midiMusicData = new byte[midiMusicSize]; + musicFile.read(_midiMusicData, midiMusicSize); + musicFile.close(); + + if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) { + MidiParser *parser = _smfParser; + parser->setTrack(0); + parser->setMidiDriver(this); + parser->setTimerRate(getBaseTempo()); + parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + + _parser = parser; + + setVolume(127); + + _looping = loop; + _isPlaying = true; + _track = track; + } +} + +void MusicPlayer::stop() { + Common::StackLock lock(_mutex); + + _isPlaying = false; + if (_parser) { + _parser->unloadMusic(); + _parser = NULL; + } +} + +void MusicPlayer::pause() { + setVolume(-1); + _isPlaying = false; +} + +void MusicPlayer::resume() { + setVolume(127); + _isPlaying = true; +} + +// TODO: +// - volume support +// - bindings to GPL2 scripting +// - load cmf.ins +// - enable Adlib +// - resuming after load + +} // End of namespace Draci diff --git a/engines/draci/music.h b/engines/draci/music.h new file mode 100644 index 0000000000..bd8ffe6301 --- /dev/null +++ b/engines/draci/music.h @@ -0,0 +1,101 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/made/music.h $ + * $Id: music.h 31873 2008-05-05 12:51:50Z john_doe $ + * + */ + +// Music class + +#ifndef DRACI_MUSIC_H +#define DRACI_MUSIC_H + +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/mutex.h" + +namespace Draci { + +// Taken from MADE, which took it from SAGA. + +class MusicPlayer : public MidiDriver { +public: + MusicPlayer(MidiDriver *driver, const char *pathMask); + ~MusicPlayer(); + + bool isPlaying() { return _isPlaying; } + void setPlaying(bool playing) { _isPlaying = playing; } + + void setVolume(int volume); + int getVolume() { return _masterVolume; } + + void setNativeMT32(bool b) { _nativeMT32 = b; } + bool hasNativeMT32() { return _nativeMT32; } + void playSMF(int track, bool loop); + void stop(); + void pause(); + void resume(); + void setLoop(bool loop) { _looping = loop; } + void setPassThrough(bool b) { _passThrough = b; } + + void setGM(bool isGM) { _isGM = isGM; } + + //MidiDriver interface implementation + int open(); + void close(); + void send(uint32 b); + + void metaEvent(byte type, byte *data, uint16 length); + + void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } + uint32 getBaseTempo(void) { return _driver ? _driver->getBaseTempo() : 0; } + + //Channel allocation functions + MidiChannel *allocateChannel() { return 0; } + MidiChannel *getPercussionChannel() { return 0; } + + MidiParser *_parser; + Common::Mutex _mutex; + +protected: + + static void onTimer(void *data); + + MidiChannel *_channel[16]; + MidiDriver *_driver; + MidiParser *_smfParser; + Common::String _pathMask; + byte _channelVolume[16]; + bool _nativeMT32; + bool _isGM; + bool _passThrough; + + bool _isPlaying; + bool _looping; + byte _masterVolume; + int _track; + + byte *_midiMusicData; +}; + +} // End of namespace Draci + +#endif |