Initial Unison support

Note that this doesn't increase the total number of TGs, the other ones will just stay silent.
Menu integration still to be improved.
pull/901/head
probonopd 2 weeks ago
parent 83ea7ee551
commit ce6810a8b7
  1. 199
      src/minidexed.cpp
  2. 8
      src/minidexed.h
  3. 49
      src/performanceconfig.cpp
  4. 9
      src/performanceconfig.h
  5. 36
      src/uimenu.cpp

@ -31,6 +31,9 @@
#include <assert.h> #include <assert.h>
#include "arm_float_to_q23.h" #include "arm_float_to_q23.h"
// Forward declaration for getPhysicalTG
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices);
const char WLANFirmwarePath[] = "SD:firmware/"; const char WLANFirmwarePath[] = "SD:firmware/";
const char WLANConfigFile[] = "SD:wpa_supplicant.conf"; const char WLANConfigFile[] = "SD:wpa_supplicant.conf";
#define FTPUSERNAME "admin" #define FTPUSERNAME "admin"
@ -126,6 +129,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pTG[i]->setEngineType(pConfig->GetEngineType ()); m_pTG[i]->setEngineType(pConfig->GetEngineType ());
m_pTG[i]->activate (); m_pTG[i]->activate ();
} }
m_nUnisonVoices[i] = 1;
m_nUnisonDetune[i] = 0;
m_nUnisonSpread[i] = 0;
} }
unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin(); unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin();
@ -848,9 +854,34 @@ void CMiniDexed::keyup (int16_t pitch, unsigned nTG)
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, nTG); pitch = ApplyNoteLimits (pitch, nTG);
if (pitch >= 0) if (pitch < 0) return;
{
m_pTG[nTG]->keyup (pitch); unsigned unisonVoices = m_nUnisonVoices[nTG];
if (unisonVoices < 1) unisonVoices = 1;
int baseDetune = m_nMasterTune[nTG];
unsigned basePan = m_nPan[nTG];
unsigned unisonDetune = m_nUnisonDetune[nTG];
unsigned unisonSpread = m_nUnisonSpread[nTG];
for (unsigned v = 0; v < unisonVoices; ++v) {
unsigned physicalTG = getPhysicalTG(nTG, v, unisonVoices);
if (physicalTG >= m_nToneGenerators) break;
// Ensure virtual TG plays the same voice as logical TG
if (physicalTG != nTG) {
uint8_t voiceData[156];
m_pTG[nTG]->getVoiceData(voiceData);
m_pTG[physicalTG]->loadVoiceParameters(voiceData);
}
float detuneOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonDetune;
float panOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonSpread;
int detune = baseDetune + (int)detuneOffset;
unsigned pan = basePan + (int)panOffset;
detune = constrain(detune, -99, 99);
pan = constrain((int)pan, 0, 127);
m_pTG[physicalTG]->setMasterTune((int8_t)detune);
tg_mixer->pan(physicalTG, mapfloat(pan, 0, 127, 0.0f, 1.0f));
m_pTG[physicalTG]->keyup(pitch);
} }
} }
@ -862,9 +893,30 @@ void CMiniDexed::keydown (int16_t pitch, uint8_t velocity, unsigned nTG)
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, nTG); pitch = ApplyNoteLimits (pitch, nTG);
if (pitch >= 0) if (pitch < 0) return;
{
m_pTG[nTG]->keydown (pitch, velocity); unsigned unisonVoices = m_nUnisonVoices[nTG];
if (unisonVoices < 1) unisonVoices = 1;
unsigned maxLogicalTGs = m_nToneGenerators / unisonVoices;
if (nTG >= maxLogicalTGs) return; // Don't exceed available physical TGs
int baseDetune = m_nMasterTune[nTG];
unsigned basePan = m_nPan[nTG];
unsigned unisonDetune = m_nUnisonDetune[nTG];
unsigned unisonSpread = m_nUnisonSpread[nTG];
for (unsigned v = 0; v < unisonVoices; ++v) {
unsigned physicalTG = getPhysicalTG(nTG, v, unisonVoices);
if (physicalTG >= m_nToneGenerators) break;
float detuneOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonDetune;
float panOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonSpread;
int detune = baseDetune + (int)detuneOffset;
unsigned pan = basePan + (int)panOffset;
detune = constrain(detune, -99, 99);
pan = constrain((int)pan, 0, 127);
m_pTG[physicalTG]->setMasterTune((int8_t)detune);
tg_mixer->pan(physicalTG, mapfloat(pan, 0, 127, 0.0f, 1.0f));
m_pTG[physicalTG]->keydown(pitch, velocity);
} }
} }
@ -1129,11 +1181,21 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT
break; break;
case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; case TGParameterReverbSend: SetReverbSend (nValue, nTG); break;
default: case TGParameterUnisonVoices:
assert (0); m_nUnisonVoices[nTG] = constrain(nValue, 1, 4);
break; break;
case TGParameterUnisonDetune:
m_nUnisonDetune[nTG] = constrain(nValue, 0, 99);
break;
case TGParameterUnisonSpread:
m_nUnisonSpread[nTG] = constrain(nValue, 0, 99);
break;
case TGParameterUnknown:
// No action needed for unknown parameter
break;
} }
} }
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
@ -1180,7 +1242,12 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
case TGParameterATAmplitude: return getModController(3, 2, nTG); case TGParameterATAmplitude: return getModController(3, 2, nTG);
case TGParameterATEGBias: return getModController(3, 3, nTG); case TGParameterATEGBias: return getModController(3, 3, nTG);
case TGParameterUnisonVoices:
return m_nUnisonVoices[nTG];
case TGParameterUnisonDetune:
return m_nUnisonDetune[nTG];
case TGParameterUnisonSpread:
return m_nUnisonSpread[nTG];
default: default:
assert (0); assert (0);
return 0; return 0;
@ -1802,11 +1869,11 @@ void CMiniDexed::loadVoiceParameters(const uint8_t* data, uint8_t nTG)
memcpy(voice, data, sizeof(uint8_t)*161); memcpy(voice, data, sizeof(uint8_t)*161);
// fix voice name // fix voice name
for (uint8_t i = 0; i < 10; i++) for (uint8_t i = 0; i <10; i++)
{ {
if (voice[151 + i] > 126) // filter characters if (voice[151 + i] > 126) // filter characters
voice[151 + i] = 32; voice[151 +i] = 32;
} }
m_pTG[nTG]->loadVoiceParameters(&voice[6]); m_pTG[nTG]->loadVoiceParameters(&voice[6]);
m_pTG[nTG]->doRefreshVoice(); m_pTG[nTG]->doRefreshVoice();
@ -2024,58 +2091,60 @@ bool CMiniDexed::DoSavePerformanceNewFile (void)
void CMiniDexed::LoadPerformanceParameters(void) void CMiniDexed::LoadPerformanceParameters(void)
{ {
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++) for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{ {
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG);
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG); ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG);
ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG);
SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG);
SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG); SetPan (m_PerformanceConfig.GetPan (nTG), nTG);
SetPan (m_PerformanceConfig.GetPan (nTG), nTG); SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG);
SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG); SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG);
SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG); SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG);
SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG); setPitchbendRange (m_PerformanceConfig.GetPitchBendRange (nTG), nTG);
setPitchbendRange (m_PerformanceConfig.GetPitchBendRange (nTG), nTG); setPitchbendStep (m_PerformanceConfig.GetPitchBendStep (nTG), nTG);
setPitchbendStep (m_PerformanceConfig.GetPitchBendStep (nTG), nTG); setPortamentoMode (m_PerformanceConfig.GetPortamentoMode (nTG), nTG);
setPortamentoMode (m_PerformanceConfig.GetPortamentoMode (nTG), nTG); setPortamentoGlissando (m_PerformanceConfig.GetPortamentoGlissando (nTG), nTG);
setPortamentoGlissando (m_PerformanceConfig.GetPortamentoGlissando (nTG), nTG); setPortamentoTime (m_PerformanceConfig.GetPortamentoTime (nTG), nTG);
setPortamentoTime (m_PerformanceConfig.GetPortamentoTime (nTG), nTG);
m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG);
m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG);
m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG);
m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG);
if(m_PerformanceConfig.VoiceDataFilled(nTG))
{
uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG);
m_pTG[nTG]->loadVoiceParameters(tVoiceData);
setOPMask(0b111111, nTG);
}
setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG);
SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG);
setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG);
setModWheelTarget (m_PerformanceConfig.GetModulationWheelTarget (nTG), nTG);
setFootControllerRange (m_PerformanceConfig.GetFootControlRange (nTG), nTG);
setFootControllerTarget (m_PerformanceConfig.GetFootControlTarget (nTG), nTG);
setBreathControllerRange (m_PerformanceConfig.GetBreathControlRange (nTG), nTG);
setBreathControllerTarget (m_PerformanceConfig.GetBreathControlTarget (nTG), nTG);
setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG);
setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG);
if(m_PerformanceConfig.VoiceDataFilled(nTG))
{
uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG);
m_pTG[nTG]->loadVoiceParameters(tVoiceData);
setOPMask(0b111111, nTG);
} }
setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG);
SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG);
setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG);
setModWheelTarget (m_PerformanceConfig.GetModulationWheelTarget (nTG), nTG);
setFootControllerRange (m_PerformanceConfig.GetFootControlRange (nTG), nTG);
setFootControllerTarget (m_PerformanceConfig.GetFootControlTarget (nTG), nTG);
setBreathControllerRange (m_PerformanceConfig.GetBreathControlRange (nTG), nTG);
setBreathControllerTarget (m_PerformanceConfig.GetBreathControlTarget (nTG), nTG);
setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG);
setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG);
// Unison parameters
m_nUnisonVoices[nTG] = m_PerformanceConfig.GetUnisonVoices(nTG);
m_nUnisonDetune[nTG] = m_PerformanceConfig.GetUnisonDetune(nTG);
m_nUnisonSpread[nTG] = m_PerformanceConfig.GetUnisonSpread(nTG);
}
// Effects // Effects
SetParameter (ParameterCompressorEnable, m_PerformanceConfig.GetCompressorEnable () ? 1 : 0); SetParameter (ParameterCompressorEnable, m_PerformanceConfig.GetCompressorEnable () ? 1 : 0);
SetParameter (ParameterReverbEnable, m_PerformanceConfig.GetReverbEnable () ? 1 : 0); SetParameter (ParameterReverbEnable, m_PerformanceConfig.GetReverbEnable () ? 1 : 0);
SetParameter (ParameterReverbSize, m_PerformanceConfig.GetReverbSize ()); SetParameter (ParameterReverbSize, m_PerformanceConfig.GetReverbSize ());
SetParameter (ParameterReverbHighDamp, m_PerformanceConfig.GetReverbHighDamp ()); SetParameter (ParameterReverbHighDamp, m_PerformanceConfig.GetReverbHighDamp ());
SetParameter (ParameterReverbLowDamp, m_PerformanceConfig.GetReverbLowDamp ()); SetParameter (ParameterReverbLowDamp, m_PerformanceConfig.GetReverbLowDamp ());
SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ()); SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ());
SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ()); SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ());
SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ());
m_UI.DisplayChanged (); m_UI.DisplayChanged ();
} }
std::string CMiniDexed::GetNewPerformanceDefaultName(void) std::string CMiniDexed::GetNewPerformanceDefaultName(void)
@ -2493,3 +2562,9 @@ bool CMiniDexed::InitNetwork()
return false; return false;
} }
} }
// Forward declaration and definition for getPhysicalTG
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices);
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices) {
return logicalTG * unisonVoices + unisonVoice;
}

@ -222,6 +222,10 @@ public:
TGParameterATAmplitude, TGParameterATAmplitude,
TGParameterATEGBias, TGParameterATEGBias,
TGParameterUnisonVoices,
TGParameterUnisonDetune,
TGParameterUnisonSpread,
TGParameterUnknown TGParameterUnknown
}; };
@ -305,7 +309,9 @@ private:
int m_nNoteShift[CConfig::AllToneGenerators]; int m_nNoteShift[CConfig::AllToneGenerators];
unsigned m_nReverbSend[CConfig::AllToneGenerators]; unsigned m_nReverbSend[CConfig::AllToneGenerators];
unsigned m_nUnisonVoices[CConfig::AllToneGenerators];
unsigned m_nUnisonDetune[CConfig::AllToneGenerators];
unsigned m_nUnisonSpread[CConfig::AllToneGenerators];
uint8_t m_nRawVoiceData[156]; uint8_t m_nRawVoiceData[156];

@ -209,8 +209,15 @@ bool CPerformanceConfig::Load (void)
PropertyName.Format ("AftertouchTarget%u", nTG+1); PropertyName.Format ("AftertouchTarget%u", nTG+1);
m_nAftertouchTarget[nTG] = m_Properties.GetNumber (PropertyName, 0); m_nAftertouchTarget[nTG] = m_Properties.GetNumber (PropertyName, 0);
} // Unison parameters
PropertyName.Format ("UnisonVoices%u", nTG+1);
m_nUnisonVoices[nTG] = m_Properties.GetNumber(PropertyName, 1);
PropertyName.Format ("UnisonDetune%u", nTG+1);
m_nUnisonDetune[nTG] = m_Properties.GetNumber(PropertyName, 0);
PropertyName.Format ("UnisonSpread%u", nTG+1);
m_nUnisonSpread[nTG] = m_Properties.GetNumber(PropertyName, 0);
}
m_bCompressorEnable = m_Properties.GetNumber ("CompressorEnable", 1) != 0; m_bCompressorEnable = m_Properties.GetNumber ("CompressorEnable", 1) != 0;
@ -326,9 +333,16 @@ bool CPerformanceConfig::Save (void)
m_Properties.SetNumber (PropertyName, m_nAftertouchRange[nTG]); m_Properties.SetNumber (PropertyName, m_nAftertouchRange[nTG]);
PropertyName.Format ("AftertouchTarget%u", nTG+1); PropertyName.Format ("AftertouchTarget%u", nTG+1);
m_Properties.SetNumber (PropertyName, m_nAftertouchTarget[nTG]); m_Properties.SetNumber (PropertyName, m_nAftertouchTarget[nTG]);
} // Unison parameters
PropertyName.Format ("UnisonVoices%u", nTG+1);
m_Properties.SetNumber(PropertyName, m_nUnisonVoices[nTG]);
PropertyName.Format ("UnisonDetune%u", nTG+1);
m_Properties.SetNumber(PropertyName, m_nUnisonDetune[nTG]);
PropertyName.Format ("UnisonSpread%u", nTG+1);
m_Properties.SetNumber(PropertyName, m_nUnisonSpread[nTG]);
}
m_Properties.SetNumber ("CompressorEnable", m_bCompressorEnable ? 1 : 0); m_Properties.SetNumber ("CompressorEnable", m_bCompressorEnable ? 1 : 0);
@ -1328,3 +1342,28 @@ bool CPerformanceConfig::IsValidPerformanceBank(unsigned nBankID)
} }
return true; return true;
} }
unsigned CPerformanceConfig::GetUnisonVoices(unsigned nTG) const {
assert(nTG < CConfig::AllToneGenerators);
return m_nUnisonVoices[nTG];
}
unsigned CPerformanceConfig::GetUnisonDetune(unsigned nTG) const {
assert(nTG < CConfig::AllToneGenerators);
return m_nUnisonDetune[nTG];
}
unsigned CPerformanceConfig::GetUnisonSpread(unsigned nTG) const {
assert(nTG < CConfig::AllToneGenerators);
return m_nUnisonSpread[nTG];
}
void CPerformanceConfig::SetUnisonVoices(unsigned nValue, unsigned nTG) {
assert(nTG < CConfig::AllToneGenerators);
m_nUnisonVoices[nTG] = nValue;
}
void CPerformanceConfig::SetUnisonDetune(unsigned nValue, unsigned nTG) {
assert(nTG < CConfig::AllToneGenerators);
m_nUnisonDetune[nTG] = nValue;
}
void CPerformanceConfig::SetUnisonSpread(unsigned nValue, unsigned nTG) {
assert(nTG < CConfig::AllToneGenerators);
m_nUnisonSpread[nTG] = nValue;
}

@ -70,6 +70,12 @@ public:
unsigned GetBreathControlTarget (unsigned nTG) const; // 0 .. 7 unsigned GetBreathControlTarget (unsigned nTG) const; // 0 .. 7
unsigned GetAftertouchRange (unsigned nTG) const; // 0 .. 99 unsigned GetAftertouchRange (unsigned nTG) const; // 0 .. 99
unsigned GetAftertouchTarget (unsigned nTG) const; // 0 .. 7 unsigned GetAftertouchTarget (unsigned nTG) const; // 0 .. 7
unsigned GetUnisonVoices(unsigned nTG) const; // 1..4
unsigned GetUnisonDetune(unsigned nTG) const; // 0..99
unsigned GetUnisonSpread(unsigned nTG) const; // 0..99
void SetUnisonVoices(unsigned nValue, unsigned nTG);
void SetUnisonDetune(unsigned nValue, unsigned nTG);
void SetUnisonSpread(unsigned nValue, unsigned nTG);
void SetBankNumber (unsigned nValue, unsigned nTG); void SetBankNumber (unsigned nValue, unsigned nTG);
void SetVoiceNumber (unsigned nValue, unsigned nTG); void SetVoiceNumber (unsigned nValue, unsigned nTG);
@ -182,6 +188,9 @@ private:
unsigned m_nBreathControlTarget[CConfig::AllToneGenerators]; unsigned m_nBreathControlTarget[CConfig::AllToneGenerators];
unsigned m_nAftertouchRange[CConfig::AllToneGenerators]; unsigned m_nAftertouchRange[CConfig::AllToneGenerators];
unsigned m_nAftertouchTarget[CConfig::AllToneGenerators]; unsigned m_nAftertouchTarget[CConfig::AllToneGenerators];
unsigned m_nUnisonVoices[CConfig::AllToneGenerators];
unsigned m_nUnisonDetune[CConfig::AllToneGenerators];
unsigned m_nUnisonSpread[CConfig::AllToneGenerators];
unsigned m_nLastPerformance; unsigned m_nLastPerformance;
unsigned m_nActualPerformance = 0; unsigned m_nActualPerformance = 0;

@ -71,22 +71,25 @@ const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] =
const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] = const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] =
{ {
{"Voice", EditProgramNumber}, {"Voice", EditProgramNumber},
{"Bank", EditVoiceBankNumber}, {"Bank", EditVoiceBankNumber},
{"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume}, {"Volume", EditTGParameter, 0, CMiniDexed::TGParameterVolume},
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
{"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan}, {"Pan", EditTGParameter, 0, CMiniDexed::TGParameterPan},
{"Reverb-Send", EditTGParameter, 0, CMiniDexed::TGParameterReverbSend}, {"Reverb-Send", EditTGParameter, 0, CMiniDexed::TGParameterReverbSend},
#endif #endif
{"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune}, {"Detune", EditTGParameter, 0, CMiniDexed::TGParameterMasterTune},
{"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff}, {"Cutoff", EditTGParameter, 0, CMiniDexed::TGParameterCutoff},
{"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance}, {"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance},
{"Pitch Bend", MenuHandler, s_EditPitchBendMenu}, {"Unison Voices", EditTGParameter, 0, CMiniDexed::TGParameterUnisonVoices},
{"Portamento", MenuHandler, s_EditPortamentoMenu}, {"Unison Detune", EditTGParameter, 0, CMiniDexed::TGParameterUnisonDetune},
{"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, {"Unison Spread", EditTGParameter, 0, CMiniDexed::TGParameterUnisonSpread},
{"Modulation", MenuHandler, s_ModulationMenu}, {"Pitch Bend", MenuHandler, s_EditPitchBendMenu},
{"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, {"Portamento", MenuHandler, s_EditPortamentoMenu},
{"Edit Voice", MenuHandler, s_EditVoiceMenu}, {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode},
{"Modulation", MenuHandler, s_ModulationMenu},
{"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel},
{"Edit Voice", MenuHandler, s_EditVoiceMenu},
{0} {0}
}; };
@ -265,7 +268,10 @@ const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown]
{0, 99, 1}, //AT Range {0, 99, 1}, //AT Range
{0, 1, 1, ToOnOff}, //AT Pitch {0, 1, 1, ToOnOff}, //AT Pitch
{0, 1, 1, ToOnOff}, //AT Amp {0, 1, 1, ToOnOff}, //AT Amp
{0, 1, 1, ToOnOff} //AT EGBias {0, 1, 1, ToOnOff}, //AT EGBias
{1, 4, 1}, // Unison Voices
{0, 99, 1}, // Unison Detune
{0, 99, 1}, // Unison Spread
}; };
// must match DexedVoiceParameters in Synth_Dexed // must match DexedVoiceParameters in Synth_Dexed

Loading…
Cancel
Save