aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2011-03-24 16:33:17 +0100
committerMax Horn2011-03-24 16:46:46 +0100
commite9570c3a4b18984669bd17ba4c80c98c77f3f6f1 (patch)
tree9463b682bc1cd883df7b17db4978b5e4817ef927
parent2d4dff8cb46dbe249e5e7918aa50f6adfc5cf6ea (diff)
downloadscummvm-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.
-rw-r--r--audio/midiplayer.cpp172
-rw-r--r--audio/midiplayer.h117
-rw-r--r--audio/module.mk1
3 files changed, 290 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
diff --git a/audio/midiplayer.h b/audio/midiplayer.h
new file mode 100644
index 0000000000..913d49c68c
--- /dev/null
+++ b/audio/midiplayer.h
@@ -0,0 +1,117 @@
+/* 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$
+ *
+ */
+
+#ifndef SOUND_MIDIPLAYER_H
+#define SOUND_MIDIPLAYER_H
+
+#include "common/scummsys.h"
+#include "common/mutex.h"
+#include "audio/mididrv.h"
+
+class MidiParser;
+
+namespace Audio {
+
+/**
+ * Simple MIDI playback class.
+ *
+ * @note Currently incomplete, as it lacks play() methods. This is just a
+ * start of the real thing, which tries to include code replicated between
+ * several of our engines.
+ *
+ * @todo Document origin of this class. It is based on code shared by
+ * several engines (e.g. DRACI says it copied it from MADE, which took
+ * it from SAGE).
+ */
+class MidiPlayer : public MidiDriver_BASE {
+public:
+ MidiPlayer();
+ ~MidiPlayer();
+
+ // TODO: Implement ways to actually play stuff
+ //virtual void play(TODO);
+ // TODO: Document these
+ virtual void stop();
+ virtual void pause();
+ virtual void resume();
+
+ bool isPlaying() const { return _isPlaying; }
+
+ int getVolume() const { return _masterVolume; }
+ virtual void setVolume(int volume); // FIXME: Overloaded by Tinsel
+ void syncVolume();
+
+ bool hasNativeMT32() const { return _nativeMT32; }
+
+ // MidiDriver_BASE interface
+ virtual void send(uint32 b);
+ virtual void metaEvent(byte type, byte *data, uint16 length);
+
+ /**
+ * This method is invoked by send() after suitably filtering
+ * the message b.
+ */
+ virtual void sendToChannel(byte channel, uint32 b);
+
+ /**
+ * This method is invoked by metaEvent when an end-of-track
+ * event arrives. By default, this tells the parser
+ * to jump to the start (if looping is enabled) resp.
+ * invokes stope():
+ * Overload this to customize behavior.
+ */
+ virtual void endOfTrack();
+
+protected:
+
+#if 0
+ // TODO: Start to make use of these, once we figured
+ // out the right way :)
+ static void onTimer(void *data);
+ virtual void onTimer();
+#endif
+
+ enum {
+ kNumChannels = 16
+ };
+
+ Common::Mutex _mutex;
+ MidiDriver *_driver;
+ MidiParser *_parser;
+
+ MidiChannel *_channelsTable[kNumChannels];
+ uint8 _channelsVolume[kNumChannels];
+
+ bool _isLooping;
+ bool _isPlaying;
+ int _masterVolume; // FIXME: byte or int ?
+
+ bool _nativeMT32;
+};
+
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/module.mk b/audio/module.mk
index 5b93c80d57..661d3ccad4 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
midiparser_smf.o \
midiparser_xmidi.o \
midiparser.o \
+ midiplayer.o \
mixer.o \
mpu401.o \
musicplugin.o \