aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2011-08-12 23:10:30 +1000
committerPaul Gilbert2011-08-12 23:10:30 +1000
commit91fdecbf68cf9eb1bd1f4105cefd1fa20351d31e (patch)
tree36ca9201d00be0ad6b092fe1994a63e9d5090dac
parentb76c0af2f4fe9cafeafdde70867e159e076b2752 (diff)
downloadscummvm-rg350-91fdecbf68cf9eb1bd1f4105cefd1fa20351d31e.tar.gz
scummvm-rg350-91fdecbf68cf9eb1bd1f4105cefd1fa20351d31e.tar.bz2
scummvm-rg350-91fdecbf68cf9eb1bd1f4105cefd1fa20351d31e.zip
CGE: Properly implemented MIDI music playback
-rw-r--r--engines/cge/sound.cpp78
-rw-r--r--engines/cge/sound.h8
2 files changed, 60 insertions, 26 deletions
diff --git a/engines/cge/sound.cpp b/engines/cge/sound.cpp
index aa42df57bf..8e60d851a4 100644
--- a/engines/cge/sound.cpp
+++ b/engines/cge/sound.cpp
@@ -31,6 +31,7 @@
#include "cge/cfile.h"
#include "cge/vol.h"
#include "cge/cge_main.h"
+#include "common/config-manager.h"
#include "common/memstream.h"
#include "audio/decoders/raw.h"
@@ -199,31 +200,36 @@ void *Patch(int pat) {
}
MusicPlayer::MusicPlayer() {
- MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
- _driver = MidiDriver::createMidi(dev);
- _driver->open();
- _midiParser = NULL;
_data = NULL;
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ // TODO: Load cmf.ins with the instrument table. It seems that an
+ // interface for such an operation is supported for AdLib. Maybe for
+ // this card, setting instruments is necessary.
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
}
MusicPlayer::~MusicPlayer() {
killMidi();
- _driver->close();
- delete _driver;
}
void MusicPlayer::killMidi() {
- if (_midiParser) {
- // Stop MIDI playback
- _midiParser->unloadMusic();
- _driver->setTimerCallback(NULL, NULL);
- _driver->close();
- delete _midiParser;
- delete _data;
+ Audio::MidiPlayer::stop();
- // Reset playback objects
+ if (_data != NULL) {
+ delete _data;
_data = NULL;
- _midiParser = NULL;
}
}
@@ -247,16 +253,42 @@ void MusicPlayer::loadMidi(int ref) {
}
void MusicPlayer::sndMidiStart() {
- _midiParser = MidiParser::createParser_SMF();
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_data, _dataSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
- if (_midiParser->loadMusic(_data, _dataSize)) {
- _midiParser->setTrack(0);
- _midiParser->setMidiDriver(_driver);
- _midiParser->setTimerRate(_driver->getBaseTempo());
+ syncVolume();
+
+ _isPlaying = true;
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::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);
+ }
- _midiParser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
- _driver->setTimerCallback(_midiParser, MidiParser::timerCallback);
- }
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
}
} // End of namespace CGE
diff --git a/engines/cge/sound.h b/engines/cge/sound.h
index 9f7d20957e..33c4e95d35 100644
--- a/engines/cge/sound.h
+++ b/engines/cge/sound.h
@@ -79,12 +79,11 @@ public:
DataCk *operator[](int ref);
};
-class MusicPlayer {
+class MusicPlayer: public Audio::MidiPlayer {
private:
- MidiDriver *_driver;
- MidiParser *_midiParser;
byte *_data;
int _dataSize;
+ bool _isGM;
// Start MIDI File
void sndMidiStart();
@@ -97,6 +96,9 @@ public:
void loadMidi(int ref);
void killMidi();
+
+ virtual void send(uint32 b);
+ virtual void sendToChannel(byte channel, uint32 b);
};
} // End of namespace CGE