diff options
author | Max Horn | 2011-03-24 16:33:17 +0100 |
---|---|---|
committer | Max Horn | 2011-03-24 16:46:46 +0100 |
commit | e9570c3a4b18984669bd17ba4c80c98c77f3f6f1 (patch) | |
tree | 9463b682bc1cd883df7b17db4978b5e4817ef927 /audio/midiplayer.cpp | |
parent | 2d4dff8cb46dbe249e5e7918aa50f6adfc5cf6ea (diff) | |
download | scummvm-rg350-e9570c3a4b18984669bd17ba4c80c98c77f3f6f1.tar.gz scummvm-rg350-e9570c3a4b18984669bd17ba4c80c98c77f3f6f1.tar.bz2 scummvm-rg350-e9570c3a4b18984669bd17ba4c80c98c77f3f6f1.zip |
AUDIO: Added Audio::MidiPlayer class
This code is currently not complete, but contains enough code to
allow several engines to switch their pseudo MidiDrivers to be
based on this class, greatly reducing code duplication.
Diffstat (limited to 'audio/midiplayer.cpp')
-rw-r--r-- | audio/midiplayer.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/audio/midiplayer.cpp b/audio/midiplayer.cpp new file mode 100644 index 0000000000..12d03d73f8 --- /dev/null +++ b/audio/midiplayer.cpp @@ -0,0 +1,172 @@ +/* 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$ + * $Id$ + * + */ + +#include "audio/midiplayer.h" +#include "audio/midiparser.h" + +#include "common/config-manager.h" + +namespace Audio { + +MidiPlayer::MidiPlayer() : + _driver(0), + _parser(0), + _isLooping(false), + _isPlaying(false), + _masterVolume(0), + _nativeMT32(false) { + + memset(_channelsTable, 0, sizeof(_channelsTable)); + memset(_channelsVolume, 127, sizeof(_channelsVolume)); + +// TODO +} + +MidiPlayer::~MidiPlayer() { +// TODO +} + +void MidiPlayer::setVolume(int volume) { + volume = CLIP(volume, 0, 255); + + if (_masterVolume == volume) + return; + + Common::StackLock lock(_mutex); + + _masterVolume = volume; + + for (int i = 0; i < kNumChannels; ++i) { + if (_channelsTable[i]) { + _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255); + } + } +} + +void MidiPlayer::syncVolume() { + int volume = ConfMan.getInt("music_volume"); + if (ConfMan.getBool("mute")) { + volume = -1; + } + setVolume(volume); +} + + +void MidiPlayer::send(uint32 b) { + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelsVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xFFF0) == 0x007BB0) { + // Only respond to All Notes Off if this channel + // has currently been allocated + if (!_channelsTable[channel]) + return; + } + + sendToChannel(channel, b); +} + +void MidiPlayer::sendToChannel(byte channel, uint32 b) { + if (!_channelsTable[channel]) { + _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); + // TODO: Some engines overload this method to insert code at this + // point which calls the channel's volume() method. + // Does this make sense, and should we maybe do it in general? + } + if (_channelsTable[channel]) + _channelsTable[channel]->send(b); +} + +void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) { + switch (type) { + case 0x2F: // End of Track + endOfTrack(); + break; + default: + //warning("Unhandled meta event: %02x", type); + break; + } +} + +void MidiPlayer::endOfTrack() { + if (_isLooping) { + assert(_parser); + _parser->jumpToTick(0); + } else + stop(); +} + +#if 0 +void MidiPlayer::onTimer(void *data) { + assert(data); + ((MidiPlayer *)data)->onTimer(); +} + +void MidiPlayer::onTimer() { + Common::StackLock lock(_mutex); + + // FIXME: There are various alternatives for this function: + +#if 0 + if (_parser) { + _parser->onTimer(); + } +#elif 0 + if (_isPlaying) { + assert(_parser); + _parser->onTimer(); + } +#endif +} +#endif + + +void MidiPlayer::stop() { + Common::StackLock lock(_mutex); + + _isPlaying = false; + if (_parser) { + _parser->unloadMusic(); + _parser = NULL; + } +} + +void MidiPlayer::pause() { +// debugC(2, kDraciSoundDebugLevel, "Pausing track %d", _track); + setVolume(-1); // FIXME: This should be 0, shouldn't it? + _isPlaying = false; +} + +void MidiPlayer::resume() { +// debugC(2, kDraciSoundDebugLevel, "Resuming track %d", _track); + syncVolume(); + _isPlaying = true; +} + +} // End of namespace Audio |