Another attempt to support configuration TGs and polyphony (#690)

* Initial commit for configuration TGs and polyphony across RPI1-5.

* Ensure unused TGs in a performance are MIDI disabled.  Set polyphony to higher defaults on Pi 4 and 5.

* Actually, can just default to MIDI "disabled" directly in performance config if not present.

* Fix issue with choosing max polyphony
pull/714/head
Kevin 3 months ago committed by GitHub
parent dd5459eece
commit f6ebd7871d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 56
      src/config.cpp
  2. 46
      src/config.h
  3. 10
      src/mididevice.cpp
  4. 2
      src/mididevice.h
  5. 280
      src/minidexed.cpp
  6. 75
      src/minidexed.h
  7. 126
      src/performanceconfig.cpp
  8. 60
      src/performanceconfig.h
  9. 17
      src/sysexfileloader.cpp
  10. 1
      src/sysexfileloader.h
  11. 233
      src/uimenu.cpp
  12. 6
      src/uimenu.h
  13. 2
      src/userinterface.cpp

@ -36,6 +36,20 @@ void CConfig::Load (void)
{
m_Properties.Load ();
// Number of Tone Generators and Polyphony
m_nToneGenerators = m_Properties.GetNumber ("ToneGenerators", DefToneGenerators);
m_nPolyphony = m_Properties.GetNumber ("Polyphony", DefaultNotes);
// At present there are only two options for tone generators: min or max
// and for the Pi 1,2,3 these are the same anyway.
if ((m_nToneGenerators != MinToneGenerators) && (m_nToneGenerators != AllToneGenerators))
{
m_nToneGenerators = DefToneGenerators;
}
if (m_nPolyphony > MaxNotes)
{
m_nPolyphony = DefaultNotes;
}
m_bUSBGadget = m_Properties.GetNumber ("USBGadget", 0) != 0;
m_nUSBGadgetPin = m_Properties.GetNumber ("USBGadgetPin", 0); // Default OFF
SetUSBGadgetMode(m_bUSBGadget); // Might get overriden later by USBGadgetPin state
@ -177,6 +191,48 @@ void CConfig::Load (void)
m_bPerformanceSelectChannel = m_Properties.GetNumber ("PerformanceSelectChannel", 0);
}
unsigned CConfig::GetToneGenerators (void) const
{
return m_nToneGenerators;
}
unsigned CConfig::GetPolyphony (void) const
{
return m_nPolyphony;
}
unsigned CConfig::GetTGsCore1 (void) const
{
#ifndef ARM_ALLOW_MULTI_CORE
return 0;
#else
if (m_nToneGenerators > MinToneGenerators)
{
return TGsCore1 + TGsCore1Opt;
}
else
{
return TGsCore1;
}
#endif
}
unsigned CConfig::GetTGsCore23 (void) const
{
#ifndef ARM_ALLOW_MULTI_CORE
return 0;
#else
if (m_nToneGenerators > MinToneGenerators)
{
return TGsCore23 + TGsCore23Opt;
}
else
{
return TGsCore23;
}
#endif
}
bool CConfig::GetUSBGadget (void) const
{
return m_bUSBGadget;

@ -35,18 +35,49 @@
class CConfig // Configuration for MiniDexed
{
public:
// Set maximum, minimum and default numbers of tone generators, depending on Pi version.
// Actual number in can be changed via config settings for some Pis.
#ifndef ARM_ALLOW_MULTI_CORE
static const unsigned ToneGenerators = 1;
// Pi V1 or Zero (single core)
static const unsigned MinToneGenerators = 1;
static const unsigned AllToneGenerators = 1;
static const unsigned DefToneGenerators = AllToneGenerators;
#else
#if (RASPPI==4 || RASPPI==5)
// Pi 4 and 5 quad core
// These are max values, default is to support 8 in total with optional 16 TGs
static const unsigned TGsCore1 = 2; // process 2 TGs on core 1
static const unsigned TGsCore23 = 3; // process 3 TGs on core 2 and 3 each
static const unsigned ToneGenerators = TGsCore1 + 2*TGsCore23;
static const unsigned TGsCore1Opt = 2; // process optional additional 2 TGs on core 1
static const unsigned TGsCore23Opt = 3; // process optional additional 3 TGs on core 2 and 3 each
static const unsigned MinToneGenerators = TGsCore1 + 2*TGsCore23;
static const unsigned AllToneGenerators = TGsCore1 + TGsCore1Opt + 2*TGsCore23 + 2*TGsCore23Opt;
static const unsigned DefToneGenerators = MinToneGenerators;
#else
// Pi 2 or 3 quad core
static const unsigned TGsCore1 = 2; // process 2 TGs on core 1
static const unsigned TGsCore23 = 3; // process 3 TGs on core 2 and 3 each
static const unsigned TGsCore1Opt = 0;
static const unsigned TGsCore23Opt = 0;
static const unsigned MinToneGenerators = TGsCore1 + 2*TGsCore23;
static const unsigned AllToneGenerators = MinToneGenerators;
static const unsigned DefToneGenerators = AllToneGenerators;
#endif
#endif
// Set maximum polyphony, depending on PI version. This can be changed via config settings
#if RASPPI == 1
static const unsigned MaxNotes = 8; // polyphony
static const unsigned MaxNotes = 8;
static const unsigned DefaultNotes = 8;
#elif RASPPI == 4
static const unsigned MaxNotes = 32;
static const unsigned DefaultNotes = 24;
#elif RASPPI == 5
static const unsigned MaxNotes = 32;
static const unsigned DefaultNotes = 32;
#else
static const unsigned MaxNotes = 16;
static const unsigned DefaultNotes = 16;
#endif
static const unsigned MaxChunkSize = 4096;
@ -67,6 +98,12 @@ public:
void Load (void);
// TGs and Polyphony
unsigned GetToneGenerators (void) const;
unsigned GetPolyphony (void) const;
unsigned GetTGsCore1 (void) const;
unsigned GetTGsCore23 (void) const;
// USB Mode
bool GetUSBGadget (void) const;
unsigned GetUSBGadgetPin (void) const;
@ -195,6 +232,9 @@ public:
private:
CPropertiesFatFsFile m_Properties;
unsigned m_nToneGenerators;
unsigned m_nPolyphony;
bool m_bUSBGadget;
unsigned m_nUSBGadgetPin;
bool m_bUSBGadgetMode;

@ -65,7 +65,7 @@ CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig, CUserInter
m_pConfig (pConfig),
m_pUI (pUI)
{
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{
m_ChannelMap[nTG] = Disabled;
}
@ -78,13 +78,13 @@ CMIDIDevice::~CMIDIDevice (void)
void CMIDIDevice::SetChannel (u8 ucChannel, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_ChannelMap[nTG] = ucChannel;
}
u8 CMIDIDevice::GetChannel (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_ChannelMap[nTG];
}
@ -238,8 +238,8 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
break;
}
// Process MIDI for each Tone Generator
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
// Process MIDI for each active Tone Generator
for (unsigned nTG = 0; nTG < m_pConfig->GetToneGenerators(); nTG++)
{
if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN)
{

@ -65,7 +65,7 @@ private:
CConfig *m_pConfig;
CUserInterface *m_pUI;
u8 m_ChannelMap[CConfig::ToneGenerators];
u8 m_ChannelMap[CConfig::AllToneGenerators];
std::string m_DeviceName;

@ -46,7 +46,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pSoundDevice (0),
m_bChannelsSwapped (pConfig->GetChannelsSwapped ()),
#ifdef ARM_ALLOW_MULTI_CORE
m_nActiveTGsLog2 (0),
// m_nActiveTGsLog2 (0),
#endif
m_GetChunkTimer ("GetChunk",
1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()),
@ -62,7 +62,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
{
assert (m_pConfig);
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
m_nToneGenerators = m_pConfig->GetToneGenerators();
m_nPolyphony = m_pConfig->GetPolyphony();
LOGNOTE("Tone Generators=%d, Polyphony=%d", m_nToneGenerators, m_nPolyphony);
for (unsigned i = 0; i < CConfig::AllToneGenerators; i++)
{
m_nVoiceBankID[i] = 0;
m_nVoiceBankIDMSB[i] = 0;
@ -93,13 +97,18 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_nAftertouchTarget[i]=0;
m_nReverbSend[i] = 0;
m_uchOPMask[i] = 0b111111; // All operators on
m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ());
assert (m_pTG[i]);
// Active the required number of active TGs
if (i<m_nToneGenerators)
{
m_uchOPMask[i] = 0b111111; // All operators on
m_pTG[i] = new CDexedAdapter (m_nPolyphony, pConfig->GetSampleRate ());
assert (m_pTG[i]);
m_pTG[i]->setEngineType(pConfig->GetEngineType ());
m_pTG[i]->activate ();
m_pTG[i]->setEngineType(pConfig->GetEngineType ());
m_pTG[i]->activate ();
}
}
unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin();
@ -156,6 +165,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
// Quad DAC 8-channel mono only an option for RPI 5
m_bQuadDAC8Chan = pConfig->GetQuadDAC8Chan ();
#endif
if (m_bQuadDAC8Chan && (m_nToneGenerators != 8))
{
LOGNOTE("ERROR: Quad DAC Mode is only valid when number of TGs = 8. Defaulting to non-Quad DAC mode,");
m_bQuadDAC8Chan = false;
}
if (m_bQuadDAC8Chan) {
LOGNOTE ("Configured for Quad DAC 8-channel Mono audio");
m_pSoundDevice = new CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
@ -206,11 +220,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
setMasterVolume(1.0);
// BEGIN setup tg_mixer
tg_mixer = new AudioStereoMixer<CConfig::ToneGenerators>(pConfig->GetChunkSize()/2);
tg_mixer = new AudioStereoMixer<CConfig::AllToneGenerators>(pConfig->GetChunkSize()/2);
// END setup tgmixer
// BEGIN setup reverb
reverb_send_mixer = new AudioStereoMixer<CConfig::ToneGenerators>(pConfig->GetChunkSize()/2);
reverb_send_mixer = new AudioStereoMixer<CConfig::AllToneGenerators>(pConfig->GetChunkSize()/2);
reverb = new AudioEffectPlateReverb(pConfig->GetSampleRate());
SetParameter (ParameterReverbEnable, 1);
SetParameter (ParameterReverbSize, 70);
@ -261,7 +275,7 @@ bool CMiniDexed::Initialize (void)
LOGNOTE("Program Change: Disabled");
}
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
for (unsigned i = 0; i < m_nToneGenerators; i++)
{
assert (m_pTG[i]);
@ -283,7 +297,7 @@ bool CMiniDexed::Initialize (void)
reverb_send_mixer->gain(i,mapfloat(m_nReverbSend[i],0,99,0.0f,1.0f));
}
m_PerformanceConfig.Init();
m_PerformanceConfig.Init(m_nToneGenerators);
if (m_PerformanceConfig.Load ())
{
LoadPerformanceParameters();
@ -453,12 +467,16 @@ void CMiniDexed::Run (unsigned nCore)
// process the TGs, assigned to this core (2 or 3)
assert (m_nFramesToProcess <= CConfig::MaxChunkSize);
unsigned nTG = CConfig::TGsCore1 + (nCore-2)*CConfig::TGsCore23;
for (unsigned i = 0; i < CConfig::TGsCore23; i++, nTG++)
assert (m_nFramesToProcess <= m_pConfig->MaxChunkSize);
unsigned nTG = m_pConfig->GetTGsCore1() + (nCore-2)*m_pConfig->GetTGsCore23();
for (unsigned i = 0; i < m_pConfig->GetTGsCore23(); i++, nTG++)
{
assert (m_pTG[nTG]);
m_pTG[nTG]->getSamples (m_OutputLevel[nTG],m_nFramesToProcess);
assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_pConfig->GetToneGenerators())
{
assert (m_pTG[nTG]);
m_pTG[nTG]->getSamples (m_OutputLevel[nTG],m_nFramesToProcess);
}
}
}
}
@ -480,7 +498,8 @@ void CMiniDexed::BankSelect (unsigned nBank, unsigned nTG)
{
nBank=constrain((int)nBank,0,16383);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
if (GetSysExFileLoader ()->IsValidBank(nBank))
{
@ -509,7 +528,9 @@ void CMiniDexed::BankSelectMSB (unsigned nBankMSB, unsigned nTG)
{
nBankMSB=constrain((int)nBankMSB,0,127);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
// MIDI Spec 1.0 "BANK SELECT" states:
// "The transmitter must transmit the MSB and LSB as a pair,
// and the Program Change must be sent immediately after
@ -530,7 +551,9 @@ void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG)
{
nBankLSB=constrain((int)nBankLSB,0,127);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
unsigned nBank = m_nVoiceBankID[nTG];
unsigned nBankMSB = m_nVoiceBankIDMSB[nTG];
nBank = (nBankMSB << 7) + nBankLSB;
@ -578,7 +601,9 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG)
nProgram=constrain((int)nProgram,0,31);
}
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nProgram[nTG] = nProgram;
uint8_t Buffer[156];
@ -617,7 +642,9 @@ void CMiniDexed::SetVolume (unsigned nVolume, unsigned nTG)
{
nVolume=constrain((int)nVolume,0,127);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nVolume[nTG] = nVolume;
assert (m_pTG[nTG]);
@ -630,7 +657,9 @@ void CMiniDexed::SetPan (unsigned nPan, unsigned nTG)
{
nPan=constrain((int)nPan,0,127);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nPan[nTG] = nPan;
tg_mixer->pan(nTG,mapfloat(nPan,0,127,0.0f,1.0f));
@ -643,7 +672,9 @@ void CMiniDexed::SetReverbSend (unsigned nReverbSend, unsigned nTG)
{
nReverbSend=constrain((int)nReverbSend,0,99);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nReverbSend[nTG] = nReverbSend;
reverb_send_mixer->gain(nTG,mapfloat(nReverbSend,0,99,0.0f,1.0f));
@ -655,7 +686,9 @@ void CMiniDexed::SetMasterTune (int nMasterTune, unsigned nTG)
{
nMasterTune=constrain((int)nMasterTune,-99,99);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nMasterTune[nTG] = nMasterTune;
assert (m_pTG[nTG]);
@ -668,7 +701,9 @@ void CMiniDexed::SetCutoff (int nCutoff, unsigned nTG)
{
nCutoff = constrain (nCutoff, 0, 99);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nCutoff[nTG] = nCutoff;
assert (m_pTG[nTG]);
@ -681,7 +716,9 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG)
{
nResonance = constrain (nResonance, 0, 99);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
m_nResonance[nTG] = nResonance;
assert (m_pTG[nTG]);
@ -694,7 +731,9 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG)
void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (uchChannel < CMIDIDevice::ChannelUnknown);
m_nMIDIChannel[nTG] = uchChannel;
@ -713,6 +752,7 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
}
#ifdef ARM_ALLOW_MULTI_CORE
/* This doesn't appear to be used anywhere...
unsigned nActiveTGs = 0;
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
{
@ -725,6 +765,7 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
assert (nActiveTGs <= 8);
static const unsigned Log2[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
m_nActiveTGsLog2 = Log2[nActiveTGs];
*/
#endif
m_UI.ParameterChanged ();
@ -732,7 +773,9 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
void CMiniDexed::keyup (int16_t pitch, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, nTG);
@ -744,7 +787,9 @@ void CMiniDexed::keyup (int16_t pitch, unsigned nTG)
void CMiniDexed::keydown (int16_t pitch, uint8_t velocity, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, nTG);
@ -756,7 +801,8 @@ void CMiniDexed::keydown (int16_t pitch, uint8_t velocity, unsigned nTG)
int16_t CMiniDexed::ApplyNoteLimits (int16_t pitch, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return -1; // Not an active TG
if ( pitch < (int16_t) m_nNoteLimitLow[nTG]
|| pitch > (int16_t) m_nNoteLimitHigh[nTG])
@ -777,14 +823,18 @@ int16_t CMiniDexed::ApplyNoteLimits (int16_t pitch, unsigned nTG)
void CMiniDexed::setSustain(bool sustain, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setSustain (sustain);
}
void CMiniDexed::panic(uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
if (value == 0) {
m_pTG[nTG]->panic ();
@ -793,7 +843,9 @@ void CMiniDexed::panic(uint8_t value, unsigned nTG)
void CMiniDexed::notesOff(uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
if (value == 0) {
m_pTG[nTG]->notesOff ();
@ -802,7 +854,9 @@ void CMiniDexed::notesOff(uint8_t value, unsigned nTG)
void CMiniDexed::setModWheel (uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setModWheel (value);
}
@ -810,35 +864,45 @@ void CMiniDexed::setModWheel (uint8_t value, unsigned nTG)
void CMiniDexed::setFootController (uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setFootController (value);
}
void CMiniDexed::setBreathController (uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setBreathController (value);
}
void CMiniDexed::setAftertouch (uint8_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setAftertouch (value);
}
void CMiniDexed::setPitchbend (int16_t value, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setPitchbend (value);
}
void CMiniDexed::ControllersRefresh (unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->ControllersRefresh ();
}
@ -853,7 +917,7 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
switch (Parameter)
{
case ParameterCompressorEnable:
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < m_nToneGenerators; nTG++)
{
assert (m_pTG[nTG]);
m_pTG[nTG]->setCompressor (!!nValue);
@ -931,7 +995,8 @@ int CMiniDexed::GetParameter (TParameter Parameter)
void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
switch (Parameter)
{
@ -986,7 +1051,7 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
switch (Parameter)
{
@ -1037,7 +1102,9 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
void CMiniDexed::SetVoiceParameter (uint8_t uchOffset, uint8_t uchValue, unsigned nOP, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
assert (nOP <= 6);
@ -1070,7 +1137,9 @@ void CMiniDexed::SetVoiceParameter (uint8_t uchOffset, uint8_t uchValue, unsigne
uint8_t CMiniDexed::GetVoiceParameter (uint8_t uchOffset, unsigned nOP, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return 0; // Not an active TG
assert (m_pTG[nTG]);
assert (nOP <= 6);
@ -1094,13 +1163,15 @@ std::string CMiniDexed::GetVoiceName (unsigned nTG)
{
char VoiceName[11];
memset (VoiceName, 0, sizeof VoiceName);
VoiceName[0] = 32; // space
assert (nTG < CConfig::AllToneGenerators);
assert (nTG < CConfig::ToneGenerators);
assert (m_pTG[nTG]);
m_pTG[nTG]->setName (VoiceName);
if (nTG < m_nToneGenerators)
{
assert (m_pTG[nTG]);
m_pTG[nTG]->setName (VoiceName);
}
std::string Result (VoiceName);
return Result;
}
@ -1142,6 +1213,7 @@ void CMiniDexed::ProcessSound (void)
void CMiniDexed::ProcessSound (void)
{
assert (m_pSoundDevice);
assert (m_pConfig);
unsigned nFrames = m_nQueueSizeFrames - m_pSoundDevice->GetQueueFramesAvail ();
if (nFrames >= m_nQueueSizeFrames/2)
@ -1162,7 +1234,7 @@ void CMiniDexed::ProcessSound (void)
// process the TGs assigned to core 1
assert (nFrames <= CConfig::MaxChunkSize);
for (unsigned i = 0; i < CConfig::TGsCore1; i++)
for (unsigned i = 0; i < m_pConfig->GetTGsCore1(); i++)
{
assert (m_pTG[i]);
m_pTG[i]->getSamples (m_OutputLevel[i], nFrames);
@ -1181,9 +1253,10 @@ void CMiniDexed::ProcessSound (void)
// Audio signal path after tone generators starts here
//
assert (CConfig::ToneGenerators == 8);
if (m_bQuadDAC8Chan) {
// This is only supported when there are 8 TGs
assert (m_nToneGenerators == 8);
// No mixing is performed by MiniDexed, sound is output in 8 channels.
// Note: one TG per audio channel; output=mono; no processing.
const int Channels = 8; // One TG per channel
@ -1233,7 +1306,7 @@ void CMiniDexed::ProcessSound (void)
if(nMasterVolume > 0.0)
{
for (uint8_t i = 0; i < CConfig::ToneGenerators; i++)
for (uint8_t i = 0; i < m_nToneGenerators; i++)
{
tg_mixer->doAddMix(i,m_OutputLevel[i]);
reverb_send_mixer->doAddMix(i,m_OutputLevel[i]);
@ -1358,7 +1431,7 @@ bool CMiniDexed::SavePerformance (bool bSaveAsDeault)
bool CMiniDexed::DoSavePerformance (void)
{
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{
m_PerformanceConfig.SetBankNumber (m_nVoiceBankID[nTG], nTG);
m_PerformanceConfig.SetVoiceNumber (m_nProgram[nTG], nTG);
@ -1377,8 +1450,14 @@ bool CMiniDexed::DoSavePerformance (void)
m_PerformanceConfig.SetNoteLimitLow (m_nNoteLimitLow[nTG], nTG);
m_PerformanceConfig.SetNoteLimitHigh (m_nNoteLimitHigh[nTG], nTG);
m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG);
m_pTG[nTG]->getVoiceData(m_nRawVoiceData);
m_PerformanceConfig.SetVoiceDataToTxt (m_nRawVoiceData, nTG);
if (nTG < m_pConfig->GetToneGenerators())
{
m_pTG[nTG]->getVoiceData(m_nRawVoiceData);
} else {
// Not an active TG so provide default voice by asking for an invalid voice ID.
m_SysExFileLoader.GetVoice(CSysExFileLoader::MaxVoiceBankID, CSysExFileLoader::VoicesPerBank+1, m_nRawVoiceData);
}
m_PerformanceConfig.SetVoiceDataToTxt (m_nRawVoiceData, nTG);
m_PerformanceConfig.SetMonoMode (m_bMonoMode[nTG], nTG);
m_PerformanceConfig.SetModulationWheelRange (m_nModulationWheelRange[nTG], nTG);
@ -1412,7 +1491,9 @@ bool CMiniDexed::DoSavePerformance (void)
void CMiniDexed::setMonoMode(uint8_t mono, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_bMonoMode[nTG]= mono != 0;
m_pTG[nTG]->setMonoMode(constrain(mono, 0, 1));
@ -1423,7 +1504,9 @@ void CMiniDexed::setMonoMode(uint8_t mono, uint8_t nTG)
void CMiniDexed::setPitchbendRange(uint8_t range, uint8_t nTG)
{
range = constrain (range, 0, 12);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nPitchBendRange[nTG] = range;
@ -1435,7 +1518,9 @@ void CMiniDexed::setPitchbendRange(uint8_t range, uint8_t nTG)
void CMiniDexed::setPitchbendStep(uint8_t step, uint8_t nTG)
{
step= constrain (step, 0, 12);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nPitchBendStep[nTG] = step;
@ -1448,7 +1533,9 @@ void CMiniDexed::setPortamentoMode(uint8_t mode, uint8_t nTG)
{
mode= constrain (mode, 0, 1);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nPortamentoMode[nTG] = mode;
@ -1460,7 +1547,9 @@ void CMiniDexed::setPortamentoMode(uint8_t mode, uint8_t nTG)
void CMiniDexed::setPortamentoGlissando(uint8_t glissando, uint8_t nTG)
{
glissando = constrain (glissando, 0, 1);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nPortamentoGlissando[nTG] = glissando;
@ -1472,7 +1561,9 @@ void CMiniDexed::setPortamentoGlissando(uint8_t glissando, uint8_t nTG)
void CMiniDexed::setPortamentoTime(uint8_t time, uint8_t nTG)
{
time = constrain (time, 0, 99);
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nPortamentoTime[nTG] = time;
@ -1483,7 +1574,9 @@ void CMiniDexed::setPortamentoTime(uint8_t time, uint8_t nTG)
void CMiniDexed::setModWheelRange(uint8_t range, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nModulationWheelRange[nTG] = range;
@ -1496,7 +1589,9 @@ void CMiniDexed::setModWheelRange(uint8_t range, uint8_t nTG)
void CMiniDexed::setModWheelTarget(uint8_t target, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nModulationWheelTarget[nTG] = target;
@ -1508,7 +1603,9 @@ void CMiniDexed::setModWheelTarget(uint8_t target, uint8_t nTG)
void CMiniDexed::setFootControllerRange(uint8_t range, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nFootControlRange[nTG]=range;
@ -1521,7 +1618,9 @@ void CMiniDexed::setFootControllerRange(uint8_t range, uint8_t nTG)
void CMiniDexed::setFootControllerTarget(uint8_t target, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nFootControlTarget[nTG] = target;
@ -1533,7 +1632,9 @@ void CMiniDexed::setFootControllerTarget(uint8_t target, uint8_t nTG)
void CMiniDexed::setBreathControllerRange(uint8_t range, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nBreathControlRange[nTG]=range;
@ -1546,7 +1647,9 @@ void CMiniDexed::setBreathControllerRange(uint8_t range, uint8_t nTG)
void CMiniDexed::setBreathControllerTarget(uint8_t target, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nBreathControlTarget[nTG]=target;
@ -1558,7 +1661,9 @@ void CMiniDexed::setBreathControllerTarget(uint8_t target, uint8_t nTG)
void CMiniDexed::setAftertouchRange(uint8_t range, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nAftertouchRange[nTG]=range;
@ -1571,7 +1676,9 @@ void CMiniDexed::setAftertouchRange(uint8_t range, uint8_t nTG)
void CMiniDexed::setAftertouchTarget(uint8_t target, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_nAftertouchTarget[nTG]=target;
@ -1583,7 +1690,9 @@ void CMiniDexed::setAftertouchTarget(uint8_t target, uint8_t nTG)
void CMiniDexed::loadVoiceParameters(const uint8_t* data, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
uint8_t voice[161];
@ -1604,7 +1713,9 @@ void CMiniDexed::loadVoiceParameters(const uint8_t* data, uint8_t nTG)
void CMiniDexed::setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
m_pTG[nTG]->setVoiceDataElement(constrain(data, 0, 155),constrain(number, 0, 99));
@ -1614,7 +1725,9 @@ 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 (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return 0; // Not an active TG
assert (m_pTG[nTG]);
return(m_pTG[nTG]->checkSystemExclusive(pMessage, nLength));
@ -1625,10 +1738,17 @@ 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);
assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_nToneGenerators)
{
assert (m_pTG[nTG]);
m_pTG[nTG]->getVoiceData(data);
}
else
{
// Not an active TG so grab a default voice
m_SysExFileLoader.GetVoice(CSysExFileLoader::MaxVoiceBankID, CSysExFileLoader::VoicesPerBank+1, data);
}
dest[0] = 0xF0; // SysEx start
dest[1] = 0x43; // ID=Yamaha
@ -1791,7 +1911,7 @@ bool CMiniDexed::DoSavePerformanceNewFile (void)
void CMiniDexed::LoadPerformanceParameters(void)
{
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG);
@ -1865,7 +1985,9 @@ bool CMiniDexed::IsValidPerformanceBank(unsigned nBankID)
void CMiniDexed::SetVoiceName (std::string VoiceName, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
if (nTG >= m_nToneGenerators) return; // Not an active TG
assert (m_pTG[nTG]);
char Name[11];
strncpy(Name, VoiceName.c_str(),10);

@ -230,7 +230,7 @@ public:
private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note
uint8_t m_uchOPMask[CConfig::ToneGenerators];
uint8_t m_uchOPMask[CConfig::AllToneGenerators];
void LoadPerformanceParameters(void);
void ProcessSound (void);
@ -250,40 +250,43 @@ private:
int m_nParameter[ParameterUnknown]; // global (non-TG) parameters
CDexedAdapter *m_pTG[CConfig::ToneGenerators];
unsigned m_nToneGenerators;
unsigned m_nPolyphony;
unsigned m_nVoiceBankID[CConfig::ToneGenerators];
unsigned m_nVoiceBankIDMSB[CConfig::ToneGenerators];
CDexedAdapter *m_pTG[CConfig::AllToneGenerators];
unsigned m_nVoiceBankID[CConfig::AllToneGenerators];
unsigned m_nVoiceBankIDMSB[CConfig::AllToneGenerators];
unsigned m_nVoiceBankIDPerformance;
unsigned m_nVoiceBankIDMSBPerformance;
unsigned m_nProgram[CConfig::ToneGenerators];
unsigned m_nVolume[CConfig::ToneGenerators];
unsigned m_nPan[CConfig::ToneGenerators];
int m_nMasterTune[CConfig::ToneGenerators];
int m_nCutoff[CConfig::ToneGenerators];
int m_nResonance[CConfig::ToneGenerators];
unsigned m_nMIDIChannel[CConfig::ToneGenerators];
unsigned m_nPitchBendRange[CConfig::ToneGenerators];
unsigned m_nPitchBendStep[CConfig::ToneGenerators];
unsigned m_nPortamentoMode[CConfig::ToneGenerators];
unsigned m_nPortamentoGlissando[CConfig::ToneGenerators];
unsigned m_nPortamentoTime[CConfig::ToneGenerators];
bool m_bMonoMode[CConfig::ToneGenerators];
unsigned m_nModulationWheelRange[CConfig::ToneGenerators];
unsigned m_nModulationWheelTarget[CConfig::ToneGenerators];
unsigned m_nFootControlRange[CConfig::ToneGenerators];
unsigned m_nFootControlTarget[CConfig::ToneGenerators];
unsigned m_nBreathControlRange[CConfig::ToneGenerators];
unsigned m_nBreathControlTarget[CConfig::ToneGenerators];
unsigned m_nAftertouchRange[CConfig::ToneGenerators];
unsigned m_nAftertouchTarget[CConfig::ToneGenerators];
unsigned m_nNoteLimitLow[CConfig::ToneGenerators];
unsigned m_nNoteLimitHigh[CConfig::ToneGenerators];
int m_nNoteShift[CConfig::ToneGenerators];
unsigned m_nReverbSend[CConfig::ToneGenerators];
unsigned m_nProgram[CConfig::AllToneGenerators];
unsigned m_nVolume[CConfig::AllToneGenerators];
unsigned m_nPan[CConfig::AllToneGenerators];
int m_nMasterTune[CConfig::AllToneGenerators];
int m_nCutoff[CConfig::AllToneGenerators];
int m_nResonance[CConfig::AllToneGenerators];
unsigned m_nMIDIChannel[CConfig::AllToneGenerators];
unsigned m_nPitchBendRange[CConfig::AllToneGenerators];
unsigned m_nPitchBendStep[CConfig::AllToneGenerators];
unsigned m_nPortamentoMode[CConfig::AllToneGenerators];
unsigned m_nPortamentoGlissando[CConfig::AllToneGenerators];
unsigned m_nPortamentoTime[CConfig::AllToneGenerators];
bool m_bMonoMode[CConfig::AllToneGenerators];
unsigned m_nModulationWheelRange[CConfig::AllToneGenerators];
unsigned m_nModulationWheelTarget[CConfig::AllToneGenerators];
unsigned m_nFootControlRange[CConfig::AllToneGenerators];
unsigned m_nFootControlTarget[CConfig::AllToneGenerators];
unsigned m_nBreathControlRange[CConfig::AllToneGenerators];
unsigned m_nBreathControlTarget[CConfig::AllToneGenerators];
unsigned m_nAftertouchRange[CConfig::AllToneGenerators];
unsigned m_nAftertouchTarget[CConfig::AllToneGenerators];
unsigned m_nNoteLimitLow[CConfig::AllToneGenerators];
unsigned m_nNoteLimitHigh[CConfig::AllToneGenerators];
int m_nNoteShift[CConfig::AllToneGenerators];
unsigned m_nReverbSend[CConfig::AllToneGenerators];
uint8_t m_nRawVoiceData[156];
@ -305,18 +308,18 @@ private:
unsigned m_nQueueSizeFrames;
#ifdef ARM_ALLOW_MULTI_CORE
unsigned m_nActiveTGsLog2;
// unsigned m_nActiveTGsLog2;
volatile TCoreStatus m_CoreStatus[CORES];
volatile unsigned m_nFramesToProcess;
float32_t m_OutputLevel[CConfig::ToneGenerators][CConfig::MaxChunkSize];
float32_t m_OutputLevel[CConfig::AllToneGenerators][CConfig::MaxChunkSize];
#endif
CPerformanceTimer m_GetChunkTimer;
bool m_bProfileEnabled;
AudioEffectPlateReverb* reverb;
AudioStereoMixer<CConfig::ToneGenerators>* tg_mixer;
AudioStereoMixer<CConfig::ToneGenerators>* reverb_send_mixer;
AudioStereoMixer<CConfig::AllToneGenerators>* tg_mixer;
AudioStereoMixer<CConfig::AllToneGenerators>* reverb_send_mixer;
CSpinLock m_ReverbSpinLock;

@ -45,8 +45,20 @@ CPerformanceConfig::~CPerformanceConfig (void)
{
}
bool CPerformanceConfig::Init (void)
bool CPerformanceConfig::Init (unsigned nToneGenerators)
{
// Different versions of Pi allow different TG configurations.
// On loading, performances will load up to the number of
// supported/active TGs.
//
// On saving, the active/supported number of TGs is used.
//
// This means that if an 8TG performance is loaded into
// a 16 TG system and then saved, the saved performance
// will include all 16 TG configurations.
//
m_nToneGenerators = nToneGenerators;
// Check intermal performance directory exists
DIR Directory;
FRESULT Result;
@ -95,7 +107,7 @@ bool CPerformanceConfig::Load (void)
bool bResult = false;
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{
CString PropertyName;
@ -110,7 +122,7 @@ bool CPerformanceConfig::Load (void)
}
PropertyName.Format ("MIDIChannel%u", nTG+1);
unsigned nMIDIChannel = m_Properties.GetNumber (PropertyName, 255);
unsigned nMIDIChannel = m_Properties.GetNumber (PropertyName, 0);
if (nMIDIChannel == 0)
{
m_nMIDIChannel[nTG] = CMIDIDevice::Disabled;
@ -217,7 +229,7 @@ bool CPerformanceConfig::Save (void)
{
m_Properties.RemoveAll ();
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
for (unsigned nTG = 0; nTG < m_nToneGenerators; nTG++)
{
CString PropertyName;
@ -333,145 +345,145 @@ bool CPerformanceConfig::Save (void)
unsigned CPerformanceConfig::GetBankNumber (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nBankNumber[nTG];
}
unsigned CPerformanceConfig::GetVoiceNumber (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nVoiceNumber[nTG];
}
unsigned CPerformanceConfig::GetMIDIChannel (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nMIDIChannel[nTG];
}
unsigned CPerformanceConfig::GetVolume (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nVolume[nTG];
}
unsigned CPerformanceConfig::GetPan (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPan[nTG];
}
int CPerformanceConfig::GetDetune (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nDetune[nTG];
}
unsigned CPerformanceConfig::GetCutoff (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nCutoff[nTG];
}
unsigned CPerformanceConfig::GetResonance (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nResonance[nTG];
}
unsigned CPerformanceConfig::GetNoteLimitLow (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nNoteLimitLow[nTG];
}
unsigned CPerformanceConfig::GetNoteLimitHigh (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nNoteLimitHigh[nTG];
}
int CPerformanceConfig::GetNoteShift (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nNoteShift[nTG];
}
unsigned CPerformanceConfig::GetReverbSend (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nReverbSend[nTG];
}
void CPerformanceConfig::SetBankNumber (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nBankNumber[nTG] = nValue;
}
void CPerformanceConfig::SetVoiceNumber (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nVoiceNumber[nTG] = nValue;
}
void CPerformanceConfig::SetMIDIChannel (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nMIDIChannel[nTG] = nValue;
}
void CPerformanceConfig::SetVolume (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nVolume[nTG] = nValue;
}
void CPerformanceConfig::SetPan (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPan[nTG] = nValue;
}
void CPerformanceConfig::SetDetune (int nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nDetune[nTG] = nValue;
}
void CPerformanceConfig::SetCutoff (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nCutoff[nTG] = nValue;
}
void CPerformanceConfig::SetResonance (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nResonance[nTG] = nValue;
}
void CPerformanceConfig::SetNoteLimitLow (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nNoteLimitLow[nTG] = nValue;
}
void CPerformanceConfig::SetNoteLimitHigh (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nNoteLimitHigh[nTG] = nValue;
}
void CPerformanceConfig::SetNoteShift (int nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nNoteShift[nTG] = nValue;
}
void CPerformanceConfig::SetReverbSend (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nReverbSend[nTG] = nValue;
}
@ -557,71 +569,71 @@ void CPerformanceConfig::SetReverbLevel (unsigned nValue)
// Pitch bender and portamento:
void CPerformanceConfig::SetPitchBendRange (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPitchBendRange[nTG] = nValue;
}
unsigned CPerformanceConfig::GetPitchBendRange (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPitchBendRange[nTG];
}
void CPerformanceConfig::SetPitchBendStep (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPitchBendStep[nTG] = nValue;
}
unsigned CPerformanceConfig::GetPitchBendStep (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPitchBendStep[nTG];
}
void CPerformanceConfig::SetPortamentoMode (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoMode[nTG] = nValue;
}
unsigned CPerformanceConfig::GetPortamentoMode (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoMode[nTG];
}
void CPerformanceConfig::SetPortamentoGlissando (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoGlissando[nTG] = nValue;
}
unsigned CPerformanceConfig::GetPortamentoGlissando (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoGlissando[nTG];
}
void CPerformanceConfig::SetPortamentoTime (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoTime[nTG] = nValue;
}
unsigned CPerformanceConfig::GetPortamentoTime (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoTime[nTG];
}
void CPerformanceConfig::SetMonoMode (bool bValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_bMonoMode[nTG] = bValue;
}
@ -632,103 +644,103 @@ bool CPerformanceConfig::GetMonoMode (unsigned nTG) const
void CPerformanceConfig::SetModulationWheelRange (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nModulationWheelRange[nTG] = nValue;
}
unsigned CPerformanceConfig::GetModulationWheelRange (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nModulationWheelRange[nTG];
}
void CPerformanceConfig::SetModulationWheelTarget (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nModulationWheelTarget[nTG] = nValue;
}
unsigned CPerformanceConfig::GetModulationWheelTarget (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nModulationWheelTarget[nTG];
}
void CPerformanceConfig::SetFootControlRange (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nFootControlRange[nTG] = nValue;
}
unsigned CPerformanceConfig::GetFootControlRange (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nFootControlRange[nTG];
}
void CPerformanceConfig::SetFootControlTarget (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nFootControlTarget[nTG] = nValue;
}
unsigned CPerformanceConfig::GetFootControlTarget (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nFootControlTarget[nTG];
}
void CPerformanceConfig::SetBreathControlRange (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nBreathControlRange[nTG] = nValue;
}
unsigned CPerformanceConfig::GetBreathControlRange (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nBreathControlRange[nTG];
}
void CPerformanceConfig::SetBreathControlTarget (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nBreathControlTarget[nTG] = nValue;
}
unsigned CPerformanceConfig::GetBreathControlTarget (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nBreathControlTarget[nTG];
}
void CPerformanceConfig::SetAftertouchRange (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nAftertouchRange[nTG] = nValue;
}
unsigned CPerformanceConfig::GetAftertouchRange (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nAftertouchRange[nTG];
}
void CPerformanceConfig::SetAftertouchTarget (unsigned nValue, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nAftertouchTarget[nTG] = nValue;
}
unsigned CPerformanceConfig::GetAftertouchTarget (unsigned nTG) const
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
return m_nAftertouchTarget[nTG];
}
void CPerformanceConfig::SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
m_nVoiceDataTxt[nTG] = "";
char nDtoH[]="0123456789ABCDEF";
for (int i = 0; i < NUM_VOICE_PARAM; i++)
@ -744,7 +756,7 @@ void CPerformanceConfig::SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG)
uint8_t *CPerformanceConfig::GetVoiceDataFromTxt (unsigned nTG)
{
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
static uint8_t pData[NUM_VOICE_PARAM];
std::string nHtoD="0123456789ABCDEF";

@ -36,7 +36,7 @@ public:
CPerformanceConfig (FATFS *pFileSystem);
~CPerformanceConfig (void);
bool Init (void);
bool Init (unsigned nToneGenerators);
bool Load (void);
@ -152,34 +152,36 @@ public:
private:
CPropertiesFatFsFile m_Properties;
unsigned m_nBankNumber[CConfig::ToneGenerators];
unsigned m_nVoiceNumber[CConfig::ToneGenerators];
unsigned m_nMIDIChannel[CConfig::ToneGenerators];
unsigned m_nVolume[CConfig::ToneGenerators];
unsigned m_nPan[CConfig::ToneGenerators];
int m_nDetune[CConfig::ToneGenerators];
unsigned m_nCutoff[CConfig::ToneGenerators];
unsigned m_nResonance[CConfig::ToneGenerators];
unsigned m_nNoteLimitLow[CConfig::ToneGenerators];
unsigned m_nNoteLimitHigh[CConfig::ToneGenerators];
int m_nNoteShift[CConfig::ToneGenerators];
int m_nReverbSend[CConfig::ToneGenerators];
unsigned m_nPitchBendRange[CConfig::ToneGenerators];
unsigned m_nPitchBendStep[CConfig::ToneGenerators];
unsigned m_nPortamentoMode[CConfig::ToneGenerators];
unsigned m_nPortamentoGlissando[CConfig::ToneGenerators];
unsigned m_nPortamentoTime[CConfig::ToneGenerators];
std::string m_nVoiceDataTxt[CConfig::ToneGenerators];
bool m_bMonoMode[CConfig::ToneGenerators];
unsigned m_nModulationWheelRange[CConfig::ToneGenerators];
unsigned m_nModulationWheelTarget[CConfig::ToneGenerators];
unsigned m_nFootControlRange[CConfig::ToneGenerators];
unsigned m_nFootControlTarget[CConfig::ToneGenerators];
unsigned m_nBreathControlRange[CConfig::ToneGenerators];
unsigned m_nBreathControlTarget[CConfig::ToneGenerators];
unsigned m_nAftertouchRange[CConfig::ToneGenerators];
unsigned m_nAftertouchTarget[CConfig::ToneGenerators];
unsigned m_nToneGenerators;
unsigned m_nBankNumber[CConfig::AllToneGenerators];
unsigned m_nVoiceNumber[CConfig::AllToneGenerators];
unsigned m_nMIDIChannel[CConfig::AllToneGenerators];
unsigned m_nVolume[CConfig::AllToneGenerators];
unsigned m_nPan[CConfig::AllToneGenerators];
int m_nDetune[CConfig::AllToneGenerators];
unsigned m_nCutoff[CConfig::AllToneGenerators];
unsigned m_nResonance[CConfig::AllToneGenerators];
unsigned m_nNoteLimitLow[CConfig::AllToneGenerators];
unsigned m_nNoteLimitHigh[CConfig::AllToneGenerators];
int m_nNoteShift[CConfig::AllToneGenerators];
int m_nReverbSend[CConfig::AllToneGenerators];
unsigned m_nPitchBendRange[CConfig::AllToneGenerators];
unsigned m_nPitchBendStep[CConfig::AllToneGenerators];
unsigned m_nPortamentoMode[CConfig::AllToneGenerators];
unsigned m_nPortamentoGlissando[CConfig::AllToneGenerators];
unsigned m_nPortamentoTime[CConfig::AllToneGenerators];
std::string m_nVoiceDataTxt[CConfig::AllToneGenerators];
bool m_bMonoMode[CConfig::AllToneGenerators];
unsigned m_nModulationWheelRange[CConfig::AllToneGenerators];
unsigned m_nModulationWheelTarget[CConfig::AllToneGenerators];
unsigned m_nFootControlRange[CConfig::AllToneGenerators];
unsigned m_nFootControlTarget[CConfig::AllToneGenerators];
unsigned m_nBreathControlRange[CConfig::AllToneGenerators];
unsigned m_nBreathControlTarget[CConfig::AllToneGenerators];
unsigned m_nAftertouchRange[CConfig::AllToneGenerators];
unsigned m_nAftertouchTarget[CConfig::AllToneGenerators];
unsigned m_nLastPerformance;
unsigned m_nActualPerformance = 0;

@ -273,6 +273,23 @@ std::string CSysExFileLoader::GetBankName (unsigned nBankID)
return "NO NAME";
}
std::string CSysExFileLoader::GetVoiceName (unsigned nBankID, unsigned nVoiceID)
{
if ((nBankID <= MaxVoiceBankID) && (nVoiceID < VoicesPerBank))
{
if (IsValidBank(nBankID))
{
// The name is the last 10 characters of the voice data
char sVoiceName[11];
strncpy (sVoiceName, (char *)((char *)&(m_pVoiceBank[nBankID]->Voice[nVoiceID]) + SizePackedVoice - 10), 10);
sVoiceName[10] = 0;
std::string result(sVoiceName);
return result;
}
}
return "INIT VOICE";
}
unsigned CSysExFileLoader::GetNextBankUp (unsigned nBankID)
{
// Find the next loaded bank "up" from the provided bank ID

@ -60,6 +60,7 @@ public:
void Load (bool bHeaderlessSysExVoices = false);
std::string GetBankName (unsigned nBankID); // 0 .. MaxVoiceBankID
std::string GetVoiceName (unsigned nBankID, unsigned nVoice); // 0 .. MaxVoiceBankID, 0 .. VoicesPerBank-1
unsigned GetNumHighestBank (); // 0 .. MaxVoiceBankID
bool IsValidBank (unsigned nBankID);
unsigned GetNextBankUp (unsigned nBankID);

@ -51,6 +51,16 @@ const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] =
{"TG6", MenuHandler, s_TGMenu, 5},
{"TG7", MenuHandler, s_TGMenu, 6},
{"TG8", MenuHandler, s_TGMenu, 7},
#if (RASPPI==4 || RASPPI==5)
{"TG9", MenuHandler, s_TGMenu, 8},
{"TG10", MenuHandler, s_TGMenu, 9},
{"TG11", MenuHandler, s_TGMenu, 10},
{"TG12", MenuHandler, s_TGMenu, 11},
{"TG13", MenuHandler, s_TGMenu, 12},
{"TG14", MenuHandler, s_TGMenu, 13},
{"TG15", MenuHandler, s_TGMenu, 14},
{"TG16", MenuHandler, s_TGMenu, 15},
#endif
#endif
{"Effects", MenuHandler, s_EffectsMenu},
{"Performance", MenuHandler, s_PerformanceMenu},
@ -334,9 +344,10 @@ const CUIMenu::TMenuItem CUIMenu::s_PerformanceMenu[] =
};
CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed)
CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed, CConfig *pConfig)
: m_pUI (pUI),
m_pMiniDexed (pMiniDexed),
m_pConfig (pConfig),
m_pParentMenu (s_MenuRoot),
m_pCurrentMenu (s_MainMenu),
m_nCurrentMenuItem (0),
@ -344,23 +355,27 @@ CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed)
m_nCurrentParameter (0),
m_nCurrentMenuDepth (0)
{
#ifndef ARM_ALLOW_MULTI_CORE
// If there is just one core, then there is only a single
// tone generator so start on the TG1 menu...
m_pParentMenu = s_MainMenu;
m_pCurrentMenu = s_TGMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 1;
assert (m_pConfig);
m_nToneGenerators = m_pConfig->GetToneGenerators();
// Place the "root" menu at the top of the stack
m_MenuStackParent[0] = s_MenuRoot;
m_MenuStackMenu[0] = s_MainMenu;
m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0;
#endif
if (m_nToneGenerators == 1)
{
// If there is just one core, then there is only a single
// tone generator so start on the TG1 menu...
m_pParentMenu = s_MainMenu;
m_pCurrentMenu = s_TGMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 1;
// Place the "root" menu at the top of the stack
m_MenuStackParent[0] = s_MenuRoot;
m_MenuStackMenu[0] = s_MainMenu;
m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0;
}
}
void CUIMenu::EventHandler (TMenuEvent Event)
@ -383,28 +398,31 @@ void CUIMenu::EventHandler (TMenuEvent Event)
break;
case MenuEventHome:
#ifdef ARM_ALLOW_MULTI_CORE
m_pParentMenu = s_MenuRoot;
m_pCurrentMenu = s_MainMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 0;
#else
// "Home" is the TG0 menu if only one TG active
m_pParentMenu = s_MainMenu;
m_pCurrentMenu = s_TGMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 1;
// Place the "root" menu at the top of the stack
m_MenuStackParent[0] = s_MenuRoot;
m_MenuStackMenu[0] = s_MainMenu;
m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0;
#endif
if (m_nToneGenerators == 1)
{
// "Home" is the TG0 menu if only one TG active
m_pParentMenu = s_MainMenu;
m_pCurrentMenu = s_TGMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 1;
// Place the "root" menu at the top of the stack
m_MenuStackParent[0] = s_MenuRoot;
m_MenuStackMenu[0] = s_MainMenu;
m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0;
}
else
{
m_pParentMenu = s_MenuRoot;
m_pCurrentMenu = s_MainMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 0;
}
EventHandler (MenuEventUpdate);
break;
@ -453,7 +471,30 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
break;
case MenuEventStepDown:
if (pUIMenu->m_nCurrentSelection > 0)
if (pUIMenu->m_nCurrentSelection == 0)
{
// If in main mennu, wrap around
if (pUIMenu->m_pCurrentMenu == s_MainMenu)
{
// Find last entry with a name
while (pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection+1].Name)
{
pUIMenu->m_nCurrentSelection++;
}
}
}
else if (pUIMenu->m_nCurrentSelection > 0)
{
pUIMenu->m_nCurrentSelection--;
}
// Might need to trim menu if number of TGs is configured to be less than the maximum supported
while ((pUIMenu->m_pCurrentMenu == s_MainMenu) && (pUIMenu->m_nCurrentSelection > 0) &&
( // Skip any unused menus
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].MenuItem == s_TGMenu) &&
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter >= pUIMenu->m_nToneGenerators) &&
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter < CConfig::AllToneGenerators)
)
)
{
pUIMenu->m_nCurrentSelection--;
}
@ -463,7 +504,27 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
++pUIMenu->m_nCurrentSelection;
if (!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name) // more entries?
{
pUIMenu->m_nCurrentSelection--;
if (pUIMenu->m_pCurrentMenu == s_MainMenu)
{
// If in main mennu, wrap around
pUIMenu->m_nCurrentSelection = 0;
}
else
{
// Return to last known good item
pUIMenu->m_nCurrentSelection--;
}
}
// Might need to trim menu if number of TGs is configured to be less than the maximum supported
while ((pUIMenu->m_pCurrentMenu == s_MainMenu) && (pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection+1].Name) &&
( // Skip any unused TG menus
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].MenuItem == s_TGMenu) &&
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter >= pUIMenu->m_nToneGenerators) &&
(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter < CConfig::AllToneGenerators)
)
)
{
pUIMenu->m_nCurrentSelection++;
}
break;
@ -1151,7 +1212,7 @@ void CUIMenu::TGShortcutHandler (TMenuEvent Event)
assert (m_nCurrentMenuDepth >= 2);
assert (m_MenuStackMenu[0] = s_MainMenu);
unsigned nTG = m_nMenuStackSelection[0];
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
assert (m_nMenuStackItem[1] == nTG);
assert (m_nMenuStackParameter[1] == nTG);
@ -1166,7 +1227,7 @@ void CUIMenu::TGShortcutHandler (TMenuEvent Event)
nTG++;
}
if (nTG < CConfig::ToneGenerators)
if (nTG < m_nToneGenerators)
{
m_nMenuStackSelection[0] = nTG;
m_nMenuStackItem[1] = nTG;
@ -1262,51 +1323,53 @@ void CUIMenu::PgmUpDownHandler (TMenuEvent Event)
if (m_MenuStackMenu[0] == s_MainMenu && (m_pCurrentMenu == s_TGMenu) || (m_MenuStackMenu[1] == s_TGMenu)) {
nTG = m_nMenuStackSelection[0];
}
assert (nTG < CConfig::ToneGenerators);
int nPgm = m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterProgram, nTG);
assert (Event == MenuEventPgmDown || Event == MenuEventPgmUp);
if (Event == MenuEventPgmDown)
assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_nToneGenerators)
{
//LOGNOTE("PgmDown");
if (--nPgm < 0)
int nPgm = m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterProgram, nTG);
assert (Event == MenuEventPgmDown || Event == MenuEventPgmUp);
if (Event == MenuEventPgmDown)
{
// Switch down a voice bank and set to the last voice
nPgm = CSysExFileLoader::VoicesPerBank-1;
int nVB = m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterVoiceBank, nTG);
nVB = m_pMiniDexed->GetSysExFileLoader ()->GetNextBankDown(nVB);
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterVoiceBank, nVB, nTG);
//LOGNOTE("PgmDown");
if (--nPgm < 0)
{
// Switch down a voice bank and set to the last voice
nPgm = CSysExFileLoader::VoicesPerBank-1;
int nVB = m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterVoiceBank, nTG);
nVB = m_pMiniDexed->GetSysExFileLoader ()->GetNextBankDown(nVB);
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterVoiceBank, nVB, nTG);
}
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterProgram, nPgm, nTG);
}
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterProgram, nPgm, nTG);
}
else
{
//LOGNOTE("PgmUp");
if (++nPgm > (int) CSysExFileLoader::VoicesPerBank-1)
else
{
// Switch up a voice bank and reset to voice 0
nPgm = 0;
int nVB = m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterVoiceBank, nTG);
nVB = m_pMiniDexed->GetSysExFileLoader ()->GetNextBankUp(nVB);
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterVoiceBank, nVB, nTG);
//LOGNOTE("PgmUp");
if (++nPgm > (int) CSysExFileLoader::VoicesPerBank-1)
{
// Switch up a voice bank and reset to voice 0
nPgm = 0;
int nVB = m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterVoiceBank, nTG);
nVB = m_pMiniDexed->GetSysExFileLoader ()->GetNextBankUp(nVB);
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterVoiceBank, nVB, nTG);
}
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterProgram, nPgm, nTG);
}
m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterProgram, nPgm, nTG);
}
// Skip empty voices.
// Use same criteria in EditProgramNumber () too.
string voiceName = m_pMiniDexed->GetVoiceName (nTG);
if (voiceName == "EMPTY "
|| voiceName == " "
|| voiceName == "----------"
|| voiceName == "~~~~~~~~~~" )
{
if (Event == MenuEventPgmUp) {
PgmUpDownHandler (MenuEventPgmUp);
}
if (Event == MenuEventPgmDown) {
PgmUpDownHandler (MenuEventPgmDown);
// Skip empty voices.
// Use same criteria in EditProgramNumber () too.
string voiceName = m_pMiniDexed->GetVoiceName (nTG);
if (voiceName == "EMPTY "
|| voiceName == " "
|| voiceName == "----------"
|| voiceName == "~~~~~~~~~~" )
{
if (Event == MenuEventPgmUp) {
PgmUpDownHandler (MenuEventPgmUp);
}
if (Event == MenuEventPgmDown) {
PgmUpDownHandler (MenuEventPgmDown);
}
}
}
}
@ -1317,7 +1380,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
// This will update the menus to position it for the next TG up or down
unsigned nTG = 0;
if (CConfig::ToneGenerators <= 1) {
if (m_nToneGenerators <= 1) {
// Nothing to do if only a single TG
return;
}
@ -1328,7 +1391,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
nTG = m_nMenuStackSelection[0];
}
assert (nTG < CConfig::ToneGenerators);
assert (nTG < CConfig::AllToneGenerators);
assert (Event == MenuEventTGDown || Event == MenuEventTGUp);
if (Event == MenuEventTGDown)
{
@ -1340,7 +1403,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
else
{
//LOGNOTE("TGUp");
if (nTG < CConfig::ToneGenerators - 1) {
if (nTG < m_nToneGenerators - 1) {
nTG++;
}
}

@ -25,6 +25,7 @@
#include <string>
#include <circle/timer.h>
#include "config.h"
class CMiniDexed;
class CUserInterface;
@ -53,7 +54,7 @@ public:
};
public:
CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed);
CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed, CConfig *pConfig);
void EventHandler (TMenuEvent Event);
@ -128,6 +129,9 @@ private:
private:
CUserInterface *m_pUI;
CMiniDexed *m_pMiniDexed;
CConfig *m_pConfig;
unsigned m_nToneGenerators;
const TMenuItem *m_pParentMenu;
const TMenuItem *m_pCurrentMenu;

@ -38,7 +38,7 @@ CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManag
m_pUIButtons (0),
m_pRotaryEncoder (0),
m_bSwitchPressed (false),
m_Menu (this, pMiniDexed)
m_Menu (this, pMiniDexed, pConfig)
{
}

Loading…
Cancel
Save