[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, ®Order[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