@@ -214,7 +214,18 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
214
214
u8 ucType = ucStatus >> 4 ;
215
215
216
216
// GLOBAL MIDI SYSEX
217
- //
217
+
218
+ // Set MIDI Channel for TX816/TX216 SysEx; in MiniDexed, we interpret the device parameter as the number of the TG (unlike the TX816/TX216 which has a hardware switch to select the TG)
219
+ if (nLength >= 6 && pMessage[0 ] == MIDI_SYSTEM_EXCLUSIVE_BEGIN && pMessage[1 ] == 0x43 && pMessage[3 ] == 0x04 && pMessage[4 ] == 0x01 ) {
220
+ uint8_t mTG = pMessage[2 ] & 0x0F ;
221
+ uint8_t val = pMessage[5 ];
222
+ LOGNOTE (" MIDI-SYSEX: Set TG%d to MIDI Channel %d" , mTG + 1 , val & 0x0F );
223
+ m_pSynthesizer->SetMIDIChannel (val & 0x0F , mTG );
224
+ // Do not process this message further for any TGs
225
+ m_MIDISpinLock.Release ();
226
+ return ;
227
+ }
228
+
218
229
// Master Volume is set using a MIDI SysEx message as follows:
219
230
// F0 Start of SysEx
220
231
// 7F System Realtime SysEx
@@ -320,16 +331,17 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
320
331
// Process MIDI for each active Tone Generator
321
332
bool bSystemCCHandled = false ;
322
333
bool bSystemCCChecked = false ;
323
- for (unsigned nTG = 0 ; nTG < m_pConfig->GetToneGenerators () && !bSystemCCHandled; nTG++)
324
- {
325
- if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN)
326
- {
327
- // MIDI SYSEX per MIDI channel
328
- uint8_t ucSysExChannel = (pMessage[2 ] & 0x0F );
329
- if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode)
330
- {
334
+ if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN) {
335
+ uint8_t ucSysExChannel = (pMessage[2 ] & 0x0F );
336
+ for (unsigned nTG = 0 ; nTG < m_pConfig->GetToneGenerators (); nTG++) {
337
+ if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) {
331
338
LOGNOTE (" MIDI-SYSEX: channel: %u, len: %u, TG: %u" ,m_ChannelMap[nTG],nLength,nTG);
332
339
340
+ HandleSystemExclusive (pMessage, nLength, nCable, nTG);
341
+ if (nLength == 5 ) {
342
+ break ; // Send dump request only to the first TG that matches the MIDI channel requested via the SysEx message device ID
343
+ }
344
+
333
345
// Check for TX216/TX816 style performance sysex messages
334
346
335
347
if (pMessage[3 ] == 0x04 )
@@ -339,21 +351,12 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
339
351
uint8_t par = pMessage[4 ];
340
352
uint8_t val = pMessage[5 ];
341
353
342
- // For parameter 1 (Set MIDI Channel), only process for the TG with the number in pMessage[2]
343
- if (par == 1 ) {
344
- if (nTG != mTG ) continue ;
345
- } else {
346
- // For all other parameters, process for all TGs listening on the MIDI channel mTG or OmniMode
347
- if (!(m_ChannelMap[nTG] == mTG || m_ChannelMap[nTG] == OmniMode)) continue ;
348
- }
354
+ if (!(m_ChannelMap[nTG] == mTG || m_ChannelMap[nTG] == OmniMode)) continue ;
355
+
349
356
LOGNOTE (" MIDI-SYSEX: Assuming TX216/TX816 style performance sysex message because 4th byte is 0x04" );
350
357
351
358
switch (par)
352
359
{
353
- case 1 : // MIDI Channel
354
- LOGNOTE (" MIDI-SYSEX: Set TG%d to MIDI Channel %d" , mTG , val & 0x0F );
355
- m_pSynthesizer->SetMIDIChannel (val & 0x0F , mTG );
356
- break ;
357
360
case 2 : // Poly/Mono
358
361
LOGNOTE (" MIDI-SYSEX: Set Poly/Mono %d to %d" , nTG, val & 0x0F );
359
362
m_pSynthesizer->setMonoMode (val ? true : false , nTG);
@@ -452,11 +455,10 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
452
455
}
453
456
}
454
457
}
455
- else
456
- {
458
+ } else {
459
+ for ( unsigned nTG = 0 ; nTG < m_pConfig-> GetToneGenerators () && !bSystemCCHandled; nTG++) {
457
460
if ( m_ChannelMap[nTG] == ucChannel
458
- || m_ChannelMap[nTG] == OmniMode)
459
- {
461
+ || m_ChannelMap[nTG] == OmniMode) {
460
462
switch (ucType)
461
463
{
462
464
case MIDI_NOTE_ON:
@@ -733,6 +735,25 @@ bool CMIDIDevice::HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval)
733
735
734
736
void CMIDIDevice::HandleSystemExclusive (const uint8_t * pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG)
735
737
{
738
+
739
+ LOGDBG (" HandleSystemExclusive: TG %d, length %zu" , nTG, nLength);
740
+
741
+ // Check if it is a dump request; these have the format F0 43 2n ff F7
742
+ // with n = the MIDI channel and ff = 00 for voice or 09 for bank
743
+ // It was confirmed that on the TX816, the device number is interpreted as the MIDI channel;
744
+ if (nLength == 5 && pMessage[3 ] == 0x00 )
745
+ {
746
+ LOGDBG (" SysEx voice dump request: device %d" , nTG);
747
+ SendSystemExclusiveVoice (nTG, m_DeviceName, nCable, nTG);
748
+ return ;
749
+ }
750
+ else if (nLength == 5 && pMessage[3 ] == 0x09 )
751
+ {
752
+ LOGDBG (" SysEx bank dump request: device %d" , nTG);
753
+ LOGDBG (" Still to be implemented" );
754
+ return ;
755
+ }
756
+
736
757
int16_t sysex_return;
737
758
738
759
sysex_return = m_pSynthesizer->checkSystemExclusive (pMessage, nLength, nTG);
@@ -802,25 +823,22 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL
802
823
else if (sysex_return >= 500 && sysex_return < 600 )
803
824
{
804
825
LOGDBG (" SysEx send voice %u request" ,sysex_return-500 );
805
- SendSystemExclusiveVoice (sysex_return-500 , nCable, nTG);
826
+ SendSystemExclusiveVoice (sysex_return-500 , m_DeviceName, nCable, nTG);
806
827
}
807
828
break ;
808
829
}
809
830
}
810
831
811
- void CMIDIDevice::SendSystemExclusiveVoice (uint8_t nVoice, const unsigned nCable, uint8_t nTG)
832
+ void CMIDIDevice::SendSystemExclusiveVoice (uint8_t nVoice, const std::string& deviceName, unsigned nCable, uint8_t nTG)
812
833
{
813
- uint8_t voicedump[163 ];
814
-
815
- // Get voice sysex dump from TG
816
- m_pSynthesizer->getSysExVoiceDump (voicedump, nTG);
817
-
818
- TDeviceMap::const_iterator Iterator;
819
-
820
- // send voice dump to all MIDI interfaces
821
- for (Iterator = s_DeviceMap.begin (); Iterator != s_DeviceMap.end (); ++Iterator)
822
- {
823
- Iterator->second ->Send (voicedump, sizeof (voicedump)*sizeof (uint8_t ));
824
- // LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
825
- }
834
+ // Example: F0 43 20 00 F7
835
+ uint8_t voicedump[163 ];
836
+ m_pSynthesizer->getSysExVoiceDump (voicedump, nTG);
837
+ TDeviceMap::const_iterator Iterator = s_DeviceMap.find (deviceName);
838
+ if (Iterator != s_DeviceMap.end ()) {
839
+ Iterator->second ->Send (voicedump, sizeof (voicedump), nCable);
840
+ LOGDBG (" Send SYSEX voice dump %u to \" %s\" " , nVoice, deviceName.c_str ());
841
+ } else {
842
+ LOGWARN (" No device found in s_DeviceMap for name: %s" , deviceName.c_str ());
843
+ }
826
844
}
0 commit comments