|
|
@ -329,7 +329,127 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign |
|
|
|
if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) |
|
|
|
if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOGNOTE("MIDI-SYSEX: channel: %u, len: %u, TG: %u",m_ChannelMap[nTG],nLength,nTG); |
|
|
|
LOGNOTE("MIDI-SYSEX: channel: %u, len: %u, TG: %u",m_ChannelMap[nTG],nLength,nTG); |
|
|
|
HandleSystemExclusive(pMessage, nLength, nCable, nTG); |
|
|
|
|
|
|
|
|
|
|
|
// Check for TX216/TX816 style performance sysex messages
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pMessage[3] == 0x04) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// TX816/TX216 Performance SysEx message
|
|
|
|
|
|
|
|
uint8_t mTG = pMessage[2] & 0x0F; // mTG = module/tone generator number (0-7)
|
|
|
|
|
|
|
|
uint8_t par = pMessage[4]; |
|
|
|
|
|
|
|
uint8_t val = pMessage[5]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// For parameter 1 (Set MIDI Channel), only process for the TG with the number in pMessage[2]
|
|
|
|
|
|
|
|
if (par == 1) { |
|
|
|
|
|
|
|
if (nTG != mTG) continue; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// For all other parameters, process for all TGs listening on the MIDI channel mTG or OmniMode
|
|
|
|
|
|
|
|
if (!(m_ChannelMap[nTG] == mTG || m_ChannelMap[nTG] == OmniMode)) continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Assuming TX216/TX816 style performance sysex message because 4th byte is 0x04"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (par) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case 1: // MIDI Channel
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set TG%d to MIDI Channel %d", mTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->SetMIDIChannel(val & 0x0F, mTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 2: // Poly/Mono
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Poly/Mono %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setMonoMode(val ? true : false, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 3: // Pitch Bend Range
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Pitch Bend Range %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setPitchbendRange(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 4: // Pitch Bend Step
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Pitch Bend Step %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setPitchbendStep(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 5: // Portamento Time
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Portamento Time %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoTime(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 6: // Portamento/Glissando
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Portamento/Glissando %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoGlissando(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 7: // Portamento Mode
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Portamento Mode %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoMode(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 9: // Mod Wheel Sensitivity
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int scaled = (val * 99) / 15; |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Mod Wheel Sensitivity %d to %d (scaled %d)", nTG, val & 0x0F, scaled); |
|
|
|
|
|
|
|
m_pSynthesizer->setModWheelRange(scaled, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 10: // Mod Wheel Assign
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Mod Wheel Assign %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setModWheelTarget(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 11: // Foot Controller Sensitivity
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int scaled = (val * 99) / 15; |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Foot Controller Sensitivity %d to %d (scaled %d)", nTG, val & 0x0F, scaled); |
|
|
|
|
|
|
|
m_pSynthesizer->setFootControllerRange(scaled, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 12: // Foot Controller Assign
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Foot Controller Assign %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setFootControllerTarget(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 13: // Aftertouch Sensitivity
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int scaled = (val * 99) / 15; |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Aftertouch Sensitivity %d to %d (scaled %d)", nTG, val & 0x0F, scaled); |
|
|
|
|
|
|
|
m_pSynthesizer->setAftertouchRange(scaled, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 14: // Aftertouch Assign
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Aftertouch Assign %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setAftertouchTarget(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 15: // Breath Controller Sensitivity
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int scaled = (val * 99) / 15; |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Breath Controller Sensitivity %d to %d (scaled %d)", nTG, val & 0x0F, scaled); |
|
|
|
|
|
|
|
m_pSynthesizer->setBreathControllerRange(scaled, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 16: // Breath Controller Assign
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Breath Controller Assign %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
m_pSynthesizer->setBreathControllerTarget(val, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 26: // Audio Output Level Attenuator
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Audio Output Level Attenuator %d to %d", nTG, val & 0x0F); |
|
|
|
|
|
|
|
// Example: F0 43 10 04 1A 00 F7 to F0 43 10 04 1A 07 F7
|
|
|
|
|
|
|
|
unsigned attenVal = val & 0x07; |
|
|
|
|
|
|
|
// unsigned newVolume = (unsigned)(127.0 * pow(attenVal / 7.0, 2.0) + 0.5); // Logarithmic mapping
|
|
|
|
|
|
|
|
// But on the T816, there is an exponential (not logarithmic!) mapping, and 0 results in the same volume as 1:
|
|
|
|
|
|
|
|
// 7=127, 6=63, 5=31, 4=15, 3=7, 2=3, 1=1, 0=1
|
|
|
|
|
|
|
|
unsigned newVolume = (attenVal == 0) ? 0 : (127 >> (7 - attenVal)); |
|
|
|
|
|
|
|
if (newVolume == 0) newVolume = 1; // 0 is like 1 to avoid silence
|
|
|
|
|
|
|
|
m_pSynthesizer->SetVolume(newVolume, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 64: // Master Tuning
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Set Master Tuning"); |
|
|
|
|
|
|
|
// TX812 scales from -75 to +75 cents.
|
|
|
|
|
|
|
|
m_pSynthesizer->SetMasterTune(maplong(val, 1, 127, -37, 37), nTG); // Would need 37.5 here, due to wrong constrain on dexed_synth module?
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
// Unknown or unsupported parameter
|
|
|
|
|
|
|
|
LOGNOTE("MIDI-SYSEX: Unknown parameter %d for TG %d", par, nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
HandleSystemExclusive(pMessage, nLength, nCable, nTG); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -431,7 +551,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign |
|
|
|
case MIDI_CC_SOSTENUTO: |
|
|
|
case MIDI_CC_SOSTENUTO: |
|
|
|
m_pSynthesizer->setSostenuto (pMessage[2] >= 64, nTG); |
|
|
|
m_pSynthesizer->setSostenuto (pMessage[2] >= 64, nTG); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case MIDI_CC_PORTAMENTO: |
|
|
|
case MIDI_CC_PORTAMENTO: |
|
|
|
m_pSynthesizer->setPortamentoMode (pMessage[2] >= 64, nTG); |
|
|
|
m_pSynthesizer->setPortamentoMode (pMessage[2] >= 64, nTG); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -439,7 +559,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign |
|
|
|
case MIDI_CC_HOLD2: |
|
|
|
case MIDI_CC_HOLD2: |
|
|
|
m_pSynthesizer->setHoldMode (pMessage[2] >= 64, nTG); |
|
|
|
m_pSynthesizer->setHoldMode (pMessage[2] >= 64, nTG); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case MIDI_CC_RESONANCE: |
|
|
|
case MIDI_CC_RESONANCE: |
|
|
|
m_pSynthesizer->SetResonance (maplong (pMessage[2], 0, 127, 0, 99), nTG); |
|
|
|
m_pSynthesizer->SetResonance (maplong (pMessage[2], 0, 127, 0, 99), nTG); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -455,11 +575,12 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign |
|
|
|
case MIDI_CC_DETUNE_LEVEL: |
|
|
|
case MIDI_CC_DETUNE_LEVEL: |
|
|
|
if (pMessage[2] == 0) |
|
|
|
if (pMessage[2] == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// "0 to 127, with 0 being no celeste (detune) effect applied at all."
|
|
|
|
// 0 to 127, with 0 being no detune effect applied at all
|
|
|
|
m_pSynthesizer->SetMasterTune (0, nTG); |
|
|
|
m_pSynthesizer->SetMasterTune (0, nTG); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
// Scale to -99 to +99 cents
|
|
|
|
m_pSynthesizer->SetMasterTune (maplong (pMessage[2], 1, 127, -99, 99), nTG); |
|
|
|
m_pSynthesizer->SetMasterTune (maplong (pMessage[2], 1, 127, -99, 99), nTG); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
@ -594,10 +715,12 @@ bool CMIDIDevice::HandleMIDISystemCC(const u8 ucCC, const u8 ucCCval) |
|
|
|
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCDetune][tg]) { |
|
|
|
if (ucCC == MIDISystemCCMap[m_nMIDISystemCCDetune][tg]) { |
|
|
|
if (ucCCval == 0) |
|
|
|
if (ucCCval == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
// 0 to 127, with 0 being no detune effect applied at all
|
|
|
|
m_pSynthesizer->SetMasterTune (0, tg); |
|
|
|
m_pSynthesizer->SetMasterTune (0, tg); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
// Scale to -99 to +99 cents
|
|
|
|
m_pSynthesizer->SetMasterTune (maplong (ucCCval, 1, 127, -99, 99), tg); |
|
|
|
m_pSynthesizer->SetMasterTune (maplong (ucCCval, 1, 127, -99, 99), tg); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -649,62 +772,6 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL |
|
|
|
case -11: |
|
|
|
case -11: |
|
|
|
LOGERR("Unknown SysEx message."); |
|
|
|
LOGERR("Unknown SysEx message."); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case 64: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setMonoMode(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 65: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setPitchbendRange(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 66: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setPitchbendStep(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 67: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoMode(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 68: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoGlissando(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 69: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setPortamentoTime(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 70: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setModWheelRange(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 71: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setModWheelTarget(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 72: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setFootControllerRange(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 73: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setFootControllerTarget(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 74: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setBreathControllerRange(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 75: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setBreathControllerTarget(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 76: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setAftertouchRange(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 77: |
|
|
|
|
|
|
|
LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); |
|
|
|
|
|
|
|
m_pSynthesizer->setAftertouchTarget(pMessage[5],nTG); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 100: |
|
|
|
case 100: |
|
|
|
// load sysex-data into voice memory
|
|
|
|
// load sysex-data into voice memory
|
|
|
|
LOGDBG("One Voice bulk upload"); |
|
|
|
LOGDBG("One Voice bulk upload"); |
|
|
@ -756,4 +823,4 @@ void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable |
|
|
|
Iterator->second->Send (voicedump, sizeof(voicedump)*sizeof(uint8_t)); |
|
|
|
Iterator->second->Send (voicedump, sizeof(voicedump)*sizeof(uint8_t)); |
|
|
|
// LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
|
|
|
|
// LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str());
|
|
|
|
} |
|
|
|
} |
|
|
|
}
|
|
|
|
} |
|
|
|