[Scummvm-git-logs] scummvm master -> adb52bcebed27bb8f9512090e12f9de4515da223

athrxx noreply at scummvm.org
Thu Mar 6 15:49:51 UTC 2025


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
adb52bcebe SCUMM: (IMS/MIDI) - add midi message tracking


Commit: adb52bcebed27bb8f9512090e12f9de4515da223
    https://github.com/scummvm/scummvm/commit/adb52bcebed27bb8f9512090e12f9de4515da223
Author: athrxx (athrxx at scummvm.org)
Date: 2025-03-06T16:47:53+01:00

Commit Message:
SCUMM: (IMS/MIDI) - add midi message tracking

(to reduce data sent to hardware devices and avoid
possible lag)

Changed paths:
    engines/scumm/imuse/drivers/midi.cpp
    engines/scumm/imuse/drivers/midi.h


diff --git a/engines/scumm/imuse/drivers/midi.cpp b/engines/scumm/imuse/drivers/midi.cpp
index 184137070ac..89ba484a412 100644
--- a/engines/scumm/imuse/drivers/midi.cpp
+++ b/engines/scumm/imuse/drivers/midi.cpp
@@ -385,8 +385,8 @@ void IMuseChannel_Midi::sendNoteOn(byte note, byte velocity) {
 namespace Scumm {
 using namespace IMSMidi;
 
-IMuseDriver_GMidi::IMuseDriver_GMidi(MidiDriver::DeviceHandle dev, bool rolandGSMode, bool newSystem) : MidiDriver(), _drv(nullptr), _gsMode(rolandGSMode),
-	_imsParts(nullptr), _newSystem(newSystem), _numChannels(16), _notesPlaying(nullptr), _notesSustained(nullptr), _idleChain(nullptr), _activeChain(nullptr), _numVoices(12) {
+IMuseDriver_GMidi::IMuseDriver_GMidi(MidiDriver::DeviceHandle dev, bool rolandGSMode, bool newSystem) : MidiDriver(), _drv(nullptr), _gsMode(rolandGSMode), _noProgramTracking(false),
+	_imsParts(nullptr), _newSystem(newSystem), _numChannels(16), _notesPlaying(nullptr), _notesSustained(nullptr), _midiRegState(nullptr), _idleChain(nullptr), _activeChain(nullptr), _numVoices(12) {
 	_drv = MidiDriver::createMidi(dev);
 	assert(_drv);
 }
@@ -465,6 +465,9 @@ void IMuseDriver_GMidi::createChannels() {
 		_notesPlaying = new uint16[128]();
 		_notesSustained = new uint16[128]();
 	}
+
+	_midiRegState = new byte[160];
+	memset(_midiRegState, 0xFF, 160);
 }
 
 void IMuseDriver_GMidi::createParts() {
@@ -503,6 +506,8 @@ void IMuseDriver_GMidi::releaseChannels() {
 	_notesPlaying = nullptr;
 	delete[] _notesSustained;
 	_notesSustained = nullptr;
+	delete[] _midiRegState;
+	_midiRegState = nullptr;
 }
 
 void IMuseDriver_GMidi::initDevice() {
@@ -639,6 +644,58 @@ void IMuseDriver_GMidi::deinitDevice() {
 	}
 }
 
+bool IMuseDriver_GMidi::trackMidiState(uint32 b) {
+	// The purpose of this function is to reduce the amount of data sent to hardware devices and
+	// thus avoid possible lag. It tracks certain midi messages with a table and allows skipping of
+	// messages which just repeat the already present device state.
+
+	byte evt = ((b & 0xF0) - 0xB0) >> 4;
+	if (evt > 3) // Only track the state of program change, control change and pitch bend events
+		return true;
+
+	// Skip program change tracking for old MT-32 tracks, since their sysex based program changing
+	// method requires resending the program change message, even with the same program.
+	if (evt == 1 && _noProgramTracking)
+		return true;
+
+	byte part = b & 0x0F;
+	b >>= 8; // Switch to para 1
+
+	byte *var = &_midiRegState[part];
+
+	switch (evt) {
+	case 0: { // Control Change
+		// Only track the state of these controllers. The first entry is an invalid placeholder,
+		// since the first part of the reg state table is reserved for the program change state.
+		static const byte regOrder[] = { 0xFF, 0, 1, 7, 10, 64, 91, 93 };
+		int srchReslt = Common::find(regOrder, &regOrder[ARRAYSIZE(regOrder)], b & 0xFF) - regOrder;
+		if (srchReslt > 0 && srchReslt < ARRAYSIZE(regOrder))
+			var += (srchReslt * 0x10);
+		else
+			return true;
+		b >>= 8; // Switch to para 2
+	}
+	// fall through
+	case 1: // Program change
+		if (*var == (b & 0xFF))
+			return false;
+		else
+			*var = b & 0xFF;
+		break;
+	case 3: // Pitch bend
+		var += (0x80 + part);
+		if (*reinterpret_cast<uint16*>(var) == (b & 0xFFFF))
+			return false;
+		else
+			*reinterpret_cast<uint16*>(var) = b & 0xFFFF;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
 } // End of namespace Scumm
 
 namespace IMSMidi {
@@ -873,6 +930,8 @@ IMuseDriver_MT32::IMuseDriver_MT32(MidiDriver::DeviceHandle dev, bool newSystem)
 
 	if (_newSystem)
 		_programsMapping = MidiDriver::_gmToMt32;
+	else
+		_noProgramTracking = true;
 }
 
 void IMuseDriver_MT32::initDevice() {
diff --git a/engines/scumm/imuse/drivers/midi.h b/engines/scumm/imuse/drivers/midi.h
index d4cb7f5fcc4..63d09e252cb 100644
--- a/engines/scumm/imuse/drivers/midi.h
+++ b/engines/scumm/imuse/drivers/midi.h
@@ -46,7 +46,7 @@ public:
 	uint32 property(int prop, uint32 param) override { return _drv ? _drv->property(prop, param) : 0; }
 	void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) override { if (_drv) _drv->setTimerCallback(timerParam, timerProc); }
 	uint32 getBaseTempo() override { return _drv ? _drv->getBaseTempo() : 0; }
-	void send(uint32 b) override { if (_drv) _drv->send(b); };
+	void send(uint32 b) override { if (_drv && trackMidiState(b)) _drv->send(b); };
 	void sysEx(const byte *msg, uint16 length) override { if (_drv) _drv->sysEx(msg, length); }
 	virtual void setPitchBendRange(byte channel, uint range) override { if (_drv) _drv->setPitchBendRange(channel, range); }
 
@@ -65,6 +65,7 @@ protected:
 	byte _numChannels;
 	byte _numVoices;
 	IMSMidi::IMuseChannel_Midi **_imsParts;
+	bool _noProgramTracking;
 
 private:
 	virtual void initDevice();
@@ -78,6 +79,8 @@ private:
 	void clearSustainFlag(byte chan, byte note) { if (_notesSustained && chan < 16 && note < 128) _notesSustained[note] &= ~(1 << chan); }
 	bool querySustainFlag(byte chan, byte note) const { return (_notesSustained && chan < 16 && note < 128) ? _notesSustained[note] & (1 << chan) : false; }
 
+	bool trackMidiState(uint32 b);
+
 	const bool _gsMode;
 
 	IMSMidi::ChannelNode *_idleChain;
@@ -85,6 +88,7 @@ private:
 
 	uint16 *_notesPlaying;
 	uint16 *_notesSustained;
+	byte *_midiRegState;
 };
 
 class IMuseDriver_MT32 final : public IMuseDriver_GMidi {




More information about the Scummvm-git-logs mailing list