[Scummvm-git-logs] scummvm master -> 74609d7fa59a937c0fd3eda271a88cd2c7a1843c

athrxx noreply at scummvm.org
Sat Oct 22 20:22:24 UTC 2022


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:
74609d7fa5 SCUMM: (IMS/MT-32) - minor fixes for playback on real hardware


Commit: 74609d7fa59a937c0fd3eda271a88cd2c7a1843c
    https://github.com/scummvm/scummvm/commit/74609d7fa59a937c0fd3eda271a88cd2c7a1843c
Author: athrxx (athrxx at scummvm.org)
Date: 2022-10-22T22:20:41+02:00

Commit Message:
SCUMM: (IMS/MT-32) - minor fixes for playback on real hardware

- avoid sending unnecessary sysex messages
- add a delay after certain sysex messages
(but without calling OSystem::delayMillis(), since
that has negative impact on the playback).

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


diff --git a/engines/scumm/imuse/drivers/midi.cpp b/engines/scumm/imuse/drivers/midi.cpp
index 456570785d5..2d18b43f90e 100644
--- a/engines/scumm/imuse/drivers/midi.cpp
+++ b/engines/scumm/imuse/drivers/midi.cpp
@@ -643,6 +643,7 @@ public:
 	~IMuseChannel_MT32() override {}
 
 	bool allocate() override;
+	void reset();
 
 	// Regular messages
 	void programChange(byte program) override;
@@ -698,15 +699,17 @@ IMuseChannel_MT32::IMuseChannel_MT32(IMuseDriver_MT32 *drv, int number) : IMuseC
 bool IMuseChannel_MT32::allocate() {
 	bool res = IMuseChannel_Midi::allocate();
 
-	if (res && !_newSystem) {
-		byte msg[] = { (byte)(_timbre >> 6), (byte)(_timbre & 0x3F), 0x18, 0x32, 0x10, 0x00, _reverbSwitch};
-		sendSysexPatchData(0, msg, sizeof(msg));
+	if (res && !_newSystem)
 		_program = _number;
-	}
 
 	return res;
 }
 
+void IMuseChannel_MT32::reset() {
+	byte msg[] = { (byte)(_timbre >> 6), (byte)(_timbre & 0x3F), 0x18, 0x32, 0x10, 0x00, _reverbSwitch};
+	sendSysexPatchData(0, msg, sizeof(msg));
+}
+
 void IMuseChannel_MT32::programChange(byte program)  {
 	if (program > 127)
 		return;
@@ -895,6 +898,11 @@ void IMuseDriver_MT32::initDevice() {
 		send(0x3F0AB0 | i);
 		send(0x4000E0 | i);
 	}
+
+	for (int i = 0; i < _numChannels; ++i) {
+		static_cast<IMuseChannel_MT32*>(_imsParts[i])->reset();
+		g_system->delayMillis(5);
+	}
 }
 
 void IMuseDriver_MT32::deinitDevice() {
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 57385062d2a..967e1c9fe5f 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -296,6 +296,7 @@ public:
 	// MidiDriver interface
 	void send(uint32 b) override;
 	void sysEx(const byte *msg, uint16 length) override;
+	uint16 sysExNoDelay(const byte *msg, uint16 length) override;
 	void metaEvent(byte type, byte *data, uint16 length) override;
 };
 
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index ac224ec8c7d..a848d875778 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -435,6 +435,33 @@ void Player::sysEx(const byte *p, uint16 len) {
 		(*_se->_sysex)(this, p, len);
 }
 
+uint16 Player::sysExNoDelay(const byte *msg, uint16 length) {
+	sysEx(msg, length);
+
+	// The reason for adding this delay was the music track in the MI2 start scene (on the bridge, with Largo) when
+	// played on real hardware (in my case a Roland CM32L). The track starts with several sysex messages (mostly
+	// iMuse control messages, but also a Roland custom timbre sysex message). When played through the Munt emulator
+	// this works totally fine, but the real hardware seems to still "choke" on the sysex data, when the actual song
+	// playback has already started. This will cause a skipping of the first couple of notes, since the midi parser
+	// will not wait, but strictly enforce sync on the next time stamps.
+	// My tests with the dreamm emulator on that scene did sometimes show the same issue (although to a weaker extent),
+	// but most of the time not. So it seems to be rather a delicate and race-condition prone matter. The original
+	// parser handles the timing differently than our general purpose parser and the code execution is also expected
+	// to be much slower, so that might make all the difference here. It is really a flaw of the track. The time stamps
+	// after the sysex messages should have been made a bit more generous. 
+	// Now, I have added some delays here that I have taken from the original DOTT MT-32 driver's sysex function which
+	// are supposed to handle the situation when _scanning is enabled. For non-_scanning situations there is no delay in
+	// the original driver, since apparently is wasn't necessary.
+	// We only need to intercept actual hardware sysex messages here. So, for the iMuse control messages, we intercept
+	// just type 0, since that one leads to hardware messages. This is not a perfect solution, but it seems to work
+	// as intended.
+
+	if (_isMT32 && ((msg[0] == IMUSE_SYSEX_ID && msg[1] == 0) || msg[0] == ROLAND_SYSEX_ID))
+		return length >= 25 ? 70 : 20;
+
+	return 0;
+}
+
 void Player::decode_sysex_bytes(const byte *src, byte *dst, int len) {
 	while (len >= 0) {
 		*dst++ = ((src[0] << 4) & 0xFF) | (src[1] & 0xF);




More information about the Scummvm-git-logs mailing list