[Scummvm-cvs-logs] scummvm master -> f7ac1e944a273923735f1a79335cd043040b2c6a

m-kiewitz m_kiewitz at users.sourceforge.net
Tue Jun 30 16:06:21 CEST 2015


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:
f7ac1e944a AUDIO: XMIDI: implement support for TIMB chunk


Commit: f7ac1e944a273923735f1a79335cd043040b2c6a
    https://github.com/scummvm/scummvm/commit/f7ac1e944a273923735f1a79335cd043040b2c6a
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-30T16:05:01+02:00

Commit Message:
AUDIO: XMIDI: implement support for TIMB chunk

implement support for TIMB chunk inside XMIDI-parser (forwarding of data to driver)
implement actual support for TIMB chunk inside Miles Audio MT32 driver

Changed paths:
    audio/midiparser.h
    audio/midiparser_xmidi.cpp
    audio/miles.h
    audio/miles_mt32.cpp



diff --git a/audio/midiparser.h b/audio/midiparser.h
index 9c10462..2cca56b 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -370,6 +370,7 @@ public:
 
 public:
 	typedef void (*XMidiCallbackProc)(byte eventData, void *refCon);
+	typedef void (*XMidiNewTimbreListProc)(MidiDriver_BASE *driver, const byte *timbreListPtr, uint32 timbreListSize);
 
 	MidiParser();
 	virtual ~MidiParser() { allNotesOff(); }
@@ -395,7 +396,7 @@ public:
 	static void defaultXMidiCallback(byte eventData, void *refCon);
 
 	static MidiParser *createParser_SMF();
-	static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0);
+	static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0, XMidiNewTimbreListProc newTimbreListProc = NULL, MidiDriver_BASE *newTimbreListDriver = NULL);
 	static MidiParser *createParser_QT();
 	static void timerCallback(void *data) { ((MidiParser *) data)->onTimer(); }
 };
diff --git a/audio/midiparser_xmidi.cpp b/audio/midiparser_xmidi.cpp
index 95aa5d7..8742d7a 100644
--- a/audio/midiparser_xmidi.cpp
+++ b/audio/midiparser_xmidi.cpp
@@ -43,6 +43,22 @@ protected:
 	XMidiCallbackProc _callbackProc;
 	void *_callbackData;
 
+	// TODO:
+	// This should possibly get cleaned up at some point, but it's very tricks.
+	// We need to support XMIDI TIMB for 7th guest, which uses
+	// Miles Audio drivers. The MT32 driver needs to get the TIMB chunk, so that it
+	// can install all required timbres before the song starts playing.
+	// But we can't easily implement this directly like for example creating
+	// a special Miles Audio class for usage in this XMIDI-class, because other engines use this
+	// XMIDI-parser but w/o using Miles Audio drivers.
+	XMidiNewTimbreListProc _newTimbreListProc;
+	MidiDriver_BASE       *_newTimbreListDriver;
+
+	byte  *_tracksTimbreList[120]; ///< Timbre-List for each track.
+	uint32 _tracksTimbreListSize[120]; ///< Size of the Timbre-List for each track.
+	byte  *_activeTrackTimbreList;
+	uint32 _activeTrackTimbreListSize;
+
 protected:
 	uint32 readVLQ2(byte * &data);
 	void parseNextEvent(EventInfo &info);
@@ -53,7 +69,17 @@ protected:
 	}
 
 public:
-	MidiParser_XMIDI(XMidiCallbackProc proc, void *data) : _callbackProc(proc), _callbackData(data), _loopCount(-1) {}
+	MidiParser_XMIDI(XMidiCallbackProc proc, void *data, XMidiNewTimbreListProc newTimbreListProc, MidiDriver_BASE *newTimbreListDriver) {
+		_callbackProc = proc;
+		_callbackData = data;
+		_loopCount = -1;
+		_newTimbreListProc = newTimbreListProc;
+		_newTimbreListDriver = newTimbreListDriver;
+		memset(_tracksTimbreList, 0, sizeof(_tracksTimbreList));
+		memset(_tracksTimbreListSize, 0, sizeof(_tracksTimbreListSize));
+		_activeTrackTimbreList = NULL;
+		_activeTrackTimbreListSize = 0;
+	}
 	~MidiParser_XMIDI() { }
 
 	bool loadMusic(byte *data, uint32 size);
@@ -322,11 +348,16 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
 				// Skip this.
 				pos += 4;
 			} else if (!memcmp(pos, "TIMB", 4)) {
-				// Custom timbres?
-				// We don't support them.
-				// Read the length, skip it, and hope there was nothing there.
+				// Custom timbres
+				// chunk data is as follows:
+				// UINT16LE timbre count (amount of custom timbres used by this track)
+				//   BYTE     patchId
+				//   BYTE     bankId
+				//    * timbre count
 				pos += 4;
 				len = read4high(pos);
+				_tracksTimbreList[tracksRead] = pos; // Skip the length bytes
+				_tracksTimbreListSize[tracksRead] = len;
 				pos += (len + 1) & ~1;
 			} else if (!memcmp(pos, "EVNT", 4)) {
 				// Ahh! What we're looking for at last.
@@ -350,6 +381,12 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
 		resetTracking();
 		setTempo(500000);
 		setTrack(0);
+		_activeTrackTimbreList = _tracksTimbreList[0];
+		_activeTrackTimbreListSize = _tracksTimbreListSize[0];
+
+		if (_newTimbreListProc)
+			_newTimbreListProc(_newTimbreListDriver, _activeTrackTimbreList, _activeTrackTimbreListSize);
+
 		return true;
 	}
 
@@ -360,6 +397,6 @@ void MidiParser::defaultXMidiCallback(byte eventData, void *data) {
 	warning("MidiParser: defaultXMidiCallback(%d)", eventData);
 }
 
-MidiParser *MidiParser::createParser_XMIDI(XMidiCallbackProc proc, void *data) {
-	return new MidiParser_XMIDI(proc, data);
+MidiParser *MidiParser::createParser_XMIDI(XMidiCallbackProc proc, void *data, XMidiNewTimbreListProc newTimbreListProc, MidiDriver_BASE *newTimbreListDriver) {
+	return new MidiParser_XMIDI(proc, data, newTimbreListProc, newTimbreListDriver);
 }
diff --git a/audio/miles.h b/audio/miles.h
index f930606..0858623 100644
--- a/audio/miles.h
+++ b/audio/miles.h
@@ -75,6 +75,8 @@ extern MidiDriver *MidiDriver_Miles_AdLib_create(const Common::String instrument
 
 extern MidiDriver *MidiDriver_Miles_MT32_create(const Common::String instrumentDataFilename);
 
+extern void MidiDriver_Miles_MT32_processXMIDITimbreChunk(MidiDriver_BASE *driver, const byte *timbreListPtr, uint32 timbreListSize);
+
 } // End of namespace Audio
 
 #endif // AUDIO_MILES_MIDIDRIVER_H
diff --git a/audio/miles_mt32.cpp b/audio/miles_mt32.cpp
index 889dad3..d28006e 100644
--- a/audio/miles_mt32.cpp
+++ b/audio/miles_mt32.cpp
@@ -36,6 +36,9 @@ namespace Audio {
 #define MILES_MT32_PATCHES_COUNT 128
 #define MILES_MT32_CUSTOMTIMBRE_COUNT 64
 
+#define MILES_MT32_TIMBREBANK_STANDARD_ROLAND 0
+#define MILES_MT32_TIMBREBANK_MELODIC_MODULE 127
+
 #define MILES_MT32_PATCHDATA_COMMONPARAMETER_SIZE 14
 #define MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE 58
 #define MILES_MT32_PATCHDATA_PARTIALPARAMETERS_COUNT 4
@@ -111,6 +114,7 @@ protected:
 	int _baseFreq;
 
 public:
+	void processXMIDITimbreChunk(const byte *timbreListPtr, uint32 timbreListSize);
 
 private:
 	void resetMT32();
@@ -327,6 +331,7 @@ void MidiDriver_Miles_MT32::MT32SysEx(const uint32 targetAddress, const byte *da
 		delay += 40;
 
 	g_system->delayMillis(delay);
+	g_system->updateScreen();
 }
 
 // MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
@@ -550,11 +555,6 @@ void MidiDriver_Miles_MT32::setupPatch(byte patchBank, byte patchId) {
 	if (patchBank) {
 		// non-built-in bank
 		int16 customTimbreId = searchCustomTimbre(patchBank, patchId);
-		if (customTimbreId < 0) {
-			// currently not loaded, try to install it
-			// Miles Audio didn't do this here, I'm not exactly sure when it called the install code
-			customTimbreId = installCustomTimbre(patchBank, patchId);
-		}
 		if (customTimbreId >= 0) {
 			// now available? -> use this timbre
 			writePatchTimbre(patchId, 2, customTimbreId); // Group MEMORY
@@ -571,11 +571,54 @@ void MidiDriver_Miles_MT32::setupPatch(byte patchBank, byte patchId) {
 	}
 }
 
+void MidiDriver_Miles_MT32::processXMIDITimbreChunk(const byte *timbreListPtr, uint32 timbreListSize) {
+	uint16 timbreCount = 0;
+	uint32 expectedSize = 0;
+	const byte *timbreListSeeker = timbreListPtr;
+
+	if (timbreListSize < 2) {
+		warning("MILES-MT32: XMIDI-TIMB chunk - not enough bytes in chunk");
+		return;
+	}
+
+	timbreCount = READ_LE_UINT16(timbreListPtr);
+	expectedSize = timbreCount * 2;
+	if (expectedSize > timbreListSize) {
+		warning("MILES-MT32: XMIDI-TIMB chunk - size mismatch");
+		return;
+	}
+
+	timbreListSeeker += 2;
+
+	while (timbreCount) {
+		const byte  patchId   = *timbreListSeeker++;
+		const byte  patchBank = *timbreListSeeker++;
+		int16       customTimbreId = 0;
+
+		switch (patchBank) {
+		case MILES_MT32_TIMBREBANK_STANDARD_ROLAND:
+		case MILES_MT32_TIMBREBANK_MELODIC_MODULE:
+			// ignore those 2 banks
+			break;
+
+		default:
+			// Check, if this timbre was already loaded
+			customTimbreId = searchCustomTimbre(patchBank, patchId);
+
+			if (customTimbreId < 0) {
+				// currently not loaded, try to install it
+				installCustomTimbre(patchBank, patchId);
+			}
+		}
+		timbreCount--;
+	}
+}
+
 //
 int16 MidiDriver_Miles_MT32::installCustomTimbre(byte patchBank, byte patchId) {
 	switch(patchBank) {
-	case 0:   // Standard Roland MT32 bank
-	case 127: // Reserved for melodic mode
+	case MILES_MT32_TIMBREBANK_STANDARD_ROLAND: // Standard Roland MT32 bank
+	case MILES_MT32_TIMBREBANK_MELODIC_MODULE:  // Reserved for melodic mode
 		return -1;
 	default:
 		break;
@@ -641,6 +684,25 @@ int16 MidiDriver_Miles_MT32::installCustomTimbre(byte patchBank, byte patchId) {
 	uint32 targetAddressPartial3 = targetAddress + 0x000102;
 	uint32 targetAddressPartial4 = targetAddress + 0x00013C;
 
+#if 0
+	byte parameterData[MILES_MT32_PATCHDATA_TOTAL_SIZE + 1];
+	uint16 parameterDataPos = 0;
+
+	memcpy(parameterData, instrumentPtr->commonParameter, MILES_MT32_PATCHDATA_COMMONPARAMETER_SIZE);
+	parameterDataPos += MILES_MT32_PATCHDATA_COMMONPARAMETER_SIZE;
+	memcpy(parameterData + parameterDataPos, instrumentPtr->partialParameters[0], MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE);
+	parameterDataPos += MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE;
+	memcpy(parameterData + parameterDataPos, instrumentPtr->partialParameters[1], MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE);
+	parameterDataPos += MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE;
+	memcpy(parameterData + parameterDataPos, instrumentPtr->partialParameters[2], MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE);
+	parameterDataPos += MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE;
+	memcpy(parameterData + parameterDataPos, instrumentPtr->partialParameters[3], MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE);
+	parameterDataPos += MILES_MT32_PATCHDATA_PARTIALPARAMETER_SIZE;
+	parameterData[parameterDataPos] = MILES_MT32_SYSEX_TERMINATOR;
+
+	MT32SysEx(targetAddressCommon, parameterData);
+#endif
+
 	// upload common parameter data
 	MT32SysEx(targetAddressCommon, instrumentPtr->commonParameter);
 	// upload partial parameter data
@@ -649,6 +711,8 @@ int16 MidiDriver_Miles_MT32::installCustomTimbre(byte patchBank, byte patchId) {
 	MT32SysEx(targetAddressPartial3, instrumentPtr->partialParameters[2]);
 	MT32SysEx(targetAddressPartial4, instrumentPtr->partialParameters[3]);
 
+	setupPatch(patchBank, patchId);
+
 	return customTimbreId;
 }
 
@@ -806,4 +870,12 @@ MidiDriver *MidiDriver_Miles_MT32_create(const Common::String instrumentDataFile
 	return new MidiDriver_Miles_MT32(instrumentTablePtr, instrumentTableCount);
 }
 
+void MidiDriver_Miles_MT32_processXMIDITimbreChunk(MidiDriver_BASE *driver, const byte *timbreListPtr, uint32 timbreListSize) {
+	MidiDriver_Miles_MT32 *driverMT32 = dynamic_cast<MidiDriver_Miles_MT32 *>(driver);
+
+	if (driverMT32) {
+		driverMT32->processXMIDITimbreChunk(timbreListPtr, timbreListSize);
+	}
+}
+
 } // End of namespace Audio






More information about the Scummvm-git-logs mailing list