From 9b8c04045bad8422ce8da7d6a7b30c03f1ceb2a5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 2 Feb 2011 23:27:59 +0000 Subject: [PATCH] MIDI: Fix for bug #3170988 - "MONKEY2: Messed up MT-32 music" This is a regression from r55256. Apparently, SCUMM has issues when sending a sustain off on a notes off event. Thus, this has been turned into a feature, which is disabled by default. Since MADE, SAGA and tinsel all share the same music code and play regular MIDI files, and this feature fixes hanging notes for them, it has been enabled for them. Also, applied a patch for a bug regarding the notes off event in MADE and tinsel, which has been applied in SAGA already svn-id: r55746 --- engines/made/music.cpp | 7 ++++--- engines/saga/music.cpp | 1 + engines/tinsel/music.cpp | 7 ++++--- sound/midiparser.cpp | 7 ++++++- sound/midiparser.h | 10 ++++++++-- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/engines/made/music.cpp b/engines/made/music.cpp index 4e2789e5fae..3124fc069ea 100644 --- a/engines/made/music.cpp +++ b/engines/made/music.cpp @@ -113,9 +113,9 @@ void MusicPlayer::send(uint32 b) { 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]) + // Only respond to All Notes Off if this channel + // has currently been allocated + if (!_channel[b & 0x0F]) return; } @@ -165,6 +165,7 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) { parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _parser = parser; diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 081fe955fc3..3c0ce75db0b 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -184,6 +184,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { _parser->setMidiDriver(_driver); _parser->setTimerRate(_driver->getBaseTempo()); _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _digitalMusic = false; } diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index ad096312601..23ef28a99c8 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -466,9 +466,9 @@ void MidiMusicPlayer::send(uint32 b) { 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 (_channel[b & 0x0F]) + // Only respond to All Notes Off if this channel + // has currently been allocated + if (!_channel[b & 0x0F]) return; } @@ -533,6 +533,7 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _parser = parser; diff --git a/sound/midiparser.cpp b/sound/midiparser.cpp index 851f91e9b50..bd51a96d46b 100644 --- a/sound/midiparser.cpp +++ b/sound/midiparser.cpp @@ -43,6 +43,7 @@ _psec_per_tick(5208), // 500000 / 96 _autoLoop(false), _smartJump(false), _centerPitchWheelOnUnload(false), +_sendSustainOffOnNotesOff(false), _num_tracks(0), _active_track(255), _abort_parse(0) { @@ -64,6 +65,9 @@ void MidiParser::property(int prop, int value) { case mpCenterPitchWheelOnUnload: _centerPitchWheelOnUnload = (value != 0); break; + case mpSendSustainOffOnNotesOff: + _sendSustainOffOnNotesOff = (value != 0); + break; } } @@ -281,7 +285,8 @@ void MidiParser::allNotesOff() { for (i = 0; i < 16; ++i) { sendToDriver(0xB0 | i, 0x7b, 0); // All notes off - sendToDriver(0xB0 | i, 0x40, 0); // Also send a sustain off event (bug #3116608) + if (_sendSustainOffOnNotesOff) + sendToDriver(0xB0 | i, 0x40, 0); // Also send a sustain off event (bug #3116608) } memset(_active_notes, 0, sizeof(_active_notes)); diff --git a/sound/midiparser.h b/sound/midiparser.h index 9ebcae7a075..0b18a19a5bf 100644 --- a/sound/midiparser.h +++ b/sound/midiparser.h @@ -281,7 +281,7 @@ protected: bool _autoLoop; ///< For lightweight clients that don't provide their own flow control. bool _smartJump; ///< Support smart expiration of hanging notes when jumping bool _centerPitchWheelOnUnload; ///< Center the pitch wheels when unloading a song - + bool _sendSustainOffOnNotesOff; ///< Send a sustain off on a notes off event, stopping hanging notes byte *_tracks[120]; ///< Multi-track MIDI formats are supported, up to 120 tracks. byte _num_tracks; ///< Count of total tracks for multi-track MIDI formats. 1 for single-track formats. byte _active_track; ///< Keeps track of the currently active track, in multi-track formats. @@ -361,7 +361,13 @@ public: * Center the pitch wheels when unloading music in preparation * for the next piece of music. */ - mpCenterPitchWheelOnUnload = 4 + mpCenterPitchWheelOnUnload = 4, + + /** + * Sends a sustain off event when a notes off event is triggered. + * Stops hanging notes. + */ + mpSendSustainOffOnNotesOff = 5 }; public: