pull/884/merge
probonopd 4 days ago committed by GitHub
commit 85499a4d72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 183
      src/mididevice.cpp
  2. 35
      src/uimenu.cpp

@ -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
@ -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");

@ -1098,12 +1098,14 @@ string CUIMenu::GetOPValueString (unsigned nOPParameter, int nValue)
string CUIMenu::ToVolume (int nValue) string CUIMenu::ToVolume (int nValue)
{ {
static const size_t MaxChars = CConfig::LCDColumns-2; constexpr size_t NumSquares = 14;
char VolumeBar[MaxChars+1]; char VolumeBar[NumSquares + 1];
memset (VolumeBar, 0xFF, sizeof VolumeBar); // 0xFF is the block character size_t filled = (nValue * NumSquares + 63) / 127;
VolumeBar[nValue * MaxChars / 127] = '\0'; for (size_t i = 0; i < NumSquares; ++i) {
VolumeBar[i] = (i < filled) ? (char)0xFF : '.';
return VolumeBar; }
VolumeBar[NumSquares] = '\0';
return VolumeBar;
} }
string CUIMenu::ToPan (int nValue) string CUIMenu::ToPan (int nValue)
@ -1394,11 +1396,11 @@ void CUIMenu::PgmUpDownHandler (TMenuEvent Event)
|| voiceName == "----------" || voiceName == "----------"
|| voiceName == "~~~~~~~~~~" ) || voiceName == "~~~~~~~~~~" )
{ {
if (Event == MenuEventPgmUp) { if (Event == MenuEventStepUp) {
PgmUpDownHandler (MenuEventPgmUp); PgmUpDownHandler (MenuEventStepUp);
} }
if (Event == MenuEventPgmDown) { if (Event == MenuEventStepDown) {
PgmUpDownHandler (MenuEventPgmDown); PgmUpDownHandler (MenuEventStepDown);
} }
} }
} }
@ -2043,6 +2045,15 @@ void CUIMenu::EditMasterVolume(CUIMenu *pUIMenu, TMenuEvent Event)
default: default:
return; return;
} }
std::string valueStr = ToVolume(pUIMenu->m_pMiniDexed->GetMasterVolume127()); unsigned lcdCols = pUIMenu->m_pConfig->GetLCDColumns();
pUIMenu->m_pUI->DisplayWrite("Master Volume", "", valueStr.c_str(), nValue > rParam.Minimum, nValue < rParam.Maximum); unsigned barLen = (lcdCols > 2) ? lcdCols - 2 : 0;
std::string valueStr(barLen, '.');
if (barLen > 0) {
size_t filled = (nValue * barLen + 63) / 127;
for (unsigned i = 0; i < barLen; ++i) {
if (i < filled) valueStr[i] = (char)0xFF;
}
}
// Do NOT add < or > here; let DisplayWrite handle it
pUIMenu->m_pUI->DisplayWrite("Master Volume", "", valueStr.c_str(), true, true);
} }

Loading…
Cancel
Save