From 55e90c6aa1903e46102bcd66318eca4f5b2fcb5e Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Sat, 21 May 2022 17:41:20 +0200 Subject: [PATCH] Code for sending a voice dump via MIDI started. --- src/mididevice.cpp | 73 +++++++++++++++++++++++++++++++--------- src/mididevice.h | 6 ++-- src/minidexed.cpp | 28 +++++++++++++++ src/minidexed.h | 1 + src/serialmididevice.cpp | 1 + 5 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 6a1a400..935570d 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -117,7 +117,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign printf("MIDI%u: SysEx data length: [%d]:",nCable, uint16_t(nLength)); for (uint16_t i = 0; i < nLength; i++) { - if((i % 8) == 0) + if((i % 16) == 0) printf("\n%04d:",i); printf(" 0x%02x",pMessage[i]); } @@ -130,6 +130,21 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign } } + // Only for debugging: +/* + if(pMessage[0]==MIDI_SYSTEM_EXCLUSIVE_BEGIN) + { + printf("MIDI%u: SysEx data length: [%d]:",nCable, uint16_t(nLength)); + for (uint16_t i = 0; i < nLength; i++) + { + if((i % 16) == 0) + printf("\n%04d:",i); + printf(" 0x%02x",pMessage[i]); + } + printf("\n"); + } +*/ + // Handle MIDI Thru if (m_DeviceName.compare (m_pConfig->GetMIDIThruIn ()) == 0) { @@ -170,7 +185,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) { LOGNOTE("MIDI-SYSEX: channel: %u, len: %u, TG: %u",m_ChannelMap[nTG],nLength,nTG); - HandleSystemExclusive(pMessage, nLength, nTG); + HandleSystemExclusive(pMessage, nLength, nCable, nTG); } } else @@ -311,7 +326,7 @@ void CMIDIDevice::AddDevice (const char *pDeviceName) s_DeviceMap.insert (std::pair (pDeviceName, this)); } -void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const uint8_t nTG) +void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG) { int16_t sysex_return; @@ -324,33 +339,33 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL LOGERR("SysEx end status byte not detected."); break; case -2: - LOGERR("E: SysEx vendor not Yamaha."); + LOGERR("SysEx vendor not Yamaha."); break; case -3: - LOGERR("E: Unknown SysEx parameter change."); + LOGERR("Unknown SysEx parameter change."); break; case -4: - LOGERR(" Unknown SysEx voice or function."); + LOGERR("Unknown SysEx voice or function."); break; case -5: - LOGERR("E: Not a SysEx voice bulk upload."); + LOGERR("Not a SysEx voice bulk upload."); break; case -6: - LOGERR("E: Wrong length for SysEx voice bulk upload (not 155)."); + LOGERR("Wrong length for SysEx voice bulk upload (not 155)."); break; case -7: - LOGERR("E: Checksum error for one voice."); + LOGERR("Checksum error for one voice."); break; case -8: - LOGERR("E: Not a SysEx bank bulk upload."); + LOGERR("Not a SysEx bank bulk upload."); break; case -9: - LOGERR("E: Wrong length for SysEx bank bulk upload (not 4096)."); + LOGERR("Wrong length for SysEx bank bulk upload (not 4096)."); case -10: - LOGERR("E: Checksum error for bank."); + LOGERR("Checksum error for bank."); break; case -11: - LOGERR("E: Unknown SysEx message."); + LOGERR("Unknown SysEx message."); break; case 64: LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); @@ -420,9 +435,37 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL LOGNOTE("Currently code for storing a bulk bank upload is missing!"); break; default: - LOGDBG("SysEx voice parameter change: Parameter %d value: %d",pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5]); - m_pSynthesizer->setVoiceDataElement(pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5],nTG); + if(sysex_return >= 300 && sysex_return < 500) + { + LOGDBG("SysEx voice parameter change: Parameter %d value: %d",pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5]); + m_pSynthesizer->setVoiceDataElement(pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5],nTG); + } + else if(sysex_return >= 500 && sysex_return < 600) + { + LOGDBG("SysEx send voice %u request",sysex_return-500); + SendSystemExclusiveVoice(sysex_return-500, nCable, nTG); + } break; } } +void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG) +{ + uint8_t voicedump[163]; + + LOGDBG("Sending SysEx voice %u ",nVoice); + + // Get voice sysex dump from TG + m_pSynthesizer->getSysExVoiceDump(voicedump, nTG); + + if (m_DeviceName.compare (m_pConfig->GetMIDIThruIn ()) == 0) + { + TDeviceMap::const_iterator Iterator; + + Iterator = s_DeviceMap.find (m_pConfig->GetMIDIThruOut ()); + if (Iterator != s_DeviceMap.end ()) + { + Iterator->second->Send (voicedump, sizeof(voicedump)*sizeof(uint8_t), nCable); + } + } +} diff --git a/src/mididevice.h b/src/mididevice.h index 0b116d1..556306e 100644 --- a/src/mididevice.h +++ b/src/mididevice.h @@ -52,11 +52,9 @@ public: protected: void MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsigned nCable = 0); - void AddDevice (const char *pDeviceName); - - void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const uint8_t nTG); - + void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG); + void SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG); private: CMiniDexed *m_pSynthesizer; CConfig *m_pConfig; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 21e79f1..1e1c173 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -1153,5 +1153,33 @@ void CMiniDexed::setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG) int16_t CMiniDexed::checkSystemExclusive(const uint8_t* pMessage,const uint16_t nLength, uint8_t nTG) { + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + return(m_pTG[nTG]->checkSystemExclusive(pMessage, nLength)); } + +void CMiniDexed::getSysExVoiceDump(uint8_t* dest, uint8_t nTG) +{ + uint8_t checksum = 0; + uint8_t data[155]; + + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + + m_pTG[nTG]->getVoiceData(data); + + dest[0] = 0xF0; // SysEx start + dest[1] = 0x43; // ID=Yamaha + dest[2] = GetTGParameter(TGParameterMIDIChannel, nTG); // Sub-status and MIDI channel + dest[3] = 0x00; // Format number (0=1 voice) + dest[4] = 0x01; // Byte count MSB + dest[5] = 0x1B; // Byte count LSB + for (uint8_t n = 0; n < 155; n++) + { + checksum -= data[n]; + dest[6 + n] = data[n]; + } + dest[161] = checksum & 0x7f; // Checksum + dest[162] = 0xF7; // SysEx end +} diff --git a/src/minidexed.h b/src/minidexed.h index 66beb35..6eccf3e 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -100,6 +100,7 @@ public: void setAftertouchTarget(uint8_t target, uint8_t nTG); void loadVoiceParameters(const uint8_t* data, uint8_t nTG); void setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG); + void getSysExVoiceDump(uint8_t* dest, uint8_t nTG); int16_t checkSystemExclusive(const uint8_t* pMessage, const uint16_t nLength, uint8_t nTG); diff --git a/src/serialmididevice.cpp b/src/serialmididevice.cpp index c3f2788..aed64a6 100644 --- a/src/serialmididevice.cpp +++ b/src/serialmididevice.cpp @@ -158,6 +158,7 @@ void CSerialMIDIDevice::Process (void) } } } + void CSerialMIDIDevice::Send (const u8 *pMessage, size_t nLength, unsigned nCable) { m_SendBuffer.Write (pMessage, nLength);