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 4 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. 256
      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. 103
      src/uimenu.cpp
  12. 6
      src/uimenu.h
  13. 2
      src/userinterface.cpp

@ -36,6 +36,20 @@ void CConfig::Load (void)
{ {
m_Properties.Load (); 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_bUSBGadget = m_Properties.GetNumber ("USBGadget", 0) != 0;
m_nUSBGadgetPin = m_Properties.GetNumber ("USBGadgetPin", 0); // Default OFF m_nUSBGadgetPin = m_Properties.GetNumber ("USBGadgetPin", 0); // Default OFF
SetUSBGadgetMode(m_bUSBGadget); // Might get overriden later by USBGadgetPin state 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); 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 bool CConfig::GetUSBGadget (void) const
{ {
return m_bUSBGadget; return m_bUSBGadget;

@ -35,18 +35,49 @@
class CConfig // Configuration for MiniDexed class CConfig // Configuration for MiniDexed
{ {
public: 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 #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 #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 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 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 #endif
// Set maximum polyphony, depending on PI version. This can be changed via config settings
#if RASPPI == 1 #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 #else
static const unsigned MaxNotes = 16; static const unsigned MaxNotes = 16;
static const unsigned DefaultNotes = 16;
#endif #endif
static const unsigned MaxChunkSize = 4096; static const unsigned MaxChunkSize = 4096;
@ -67,6 +98,12 @@ public:
void Load (void); void Load (void);
// TGs and Polyphony
unsigned GetToneGenerators (void) const;
unsigned GetPolyphony (void) const;
unsigned GetTGsCore1 (void) const;
unsigned GetTGsCore23 (void) const;
// USB Mode // USB Mode
bool GetUSBGadget (void) const; bool GetUSBGadget (void) const;
unsigned GetUSBGadgetPin (void) const; unsigned GetUSBGadgetPin (void) const;
@ -195,6 +232,9 @@ public:
private: private:
CPropertiesFatFsFile m_Properties; CPropertiesFatFsFile m_Properties;
unsigned m_nToneGenerators;
unsigned m_nPolyphony;
bool m_bUSBGadget; bool m_bUSBGadget;
unsigned m_nUSBGadgetPin; unsigned m_nUSBGadgetPin;
bool m_bUSBGadgetMode; bool m_bUSBGadgetMode;

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

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

@ -46,7 +46,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pSoundDevice (0), m_pSoundDevice (0),
m_bChannelsSwapped (pConfig->GetChannelsSwapped ()), m_bChannelsSwapped (pConfig->GetChannelsSwapped ()),
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
m_nActiveTGsLog2 (0), // m_nActiveTGsLog2 (0),
#endif #endif
m_GetChunkTimer ("GetChunk", m_GetChunkTimer ("GetChunk",
1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()), 1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()),
@ -62,7 +62,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
{ {
assert (m_pConfig); 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_nVoiceBankID[i] = 0;
m_nVoiceBankIDMSB[i] = 0; m_nVoiceBankIDMSB[i] = 0;
@ -93,14 +97,19 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_nAftertouchTarget[i]=0; m_nAftertouchTarget[i]=0;
m_nReverbSend[i] = 0; m_nReverbSend[i] = 0;
// Active the required number of active TGs
if (i<m_nToneGenerators)
{
m_uchOPMask[i] = 0b111111; // All operators on m_uchOPMask[i] = 0b111111; // All operators on
m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()); m_pTG[i] = new CDexedAdapter (m_nPolyphony, pConfig->GetSampleRate ());
assert (m_pTG[i]); assert (m_pTG[i]);
m_pTG[i]->setEngineType(pConfig->GetEngineType ()); m_pTG[i]->setEngineType(pConfig->GetEngineType ());
m_pTG[i]->activate (); m_pTG[i]->activate ();
} }
}
unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin(); unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin();
bool bUSBGadget = pConfig->GetUSBGadget(); bool bUSBGadget = pConfig->GetUSBGadget();
@ -156,6 +165,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
// Quad DAC 8-channel mono only an option for RPI 5 // Quad DAC 8-channel mono only an option for RPI 5
m_bQuadDAC8Chan = pConfig->GetQuadDAC8Chan (); m_bQuadDAC8Chan = pConfig->GetQuadDAC8Chan ();
#endif #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) { if (m_bQuadDAC8Chan) {
LOGNOTE ("Configured for Quad DAC 8-channel Mono audio"); LOGNOTE ("Configured for Quad DAC 8-channel Mono audio");
m_pSoundDevice = new CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), m_pSoundDevice = new CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
@ -206,11 +220,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
setMasterVolume(1.0); setMasterVolume(1.0);
// BEGIN setup tg_mixer // 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 // END setup tgmixer
// BEGIN setup reverb // 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()); reverb = new AudioEffectPlateReverb(pConfig->GetSampleRate());
SetParameter (ParameterReverbEnable, 1); SetParameter (ParameterReverbEnable, 1);
SetParameter (ParameterReverbSize, 70); SetParameter (ParameterReverbSize, 70);
@ -261,7 +275,7 @@ bool CMiniDexed::Initialize (void)
LOGNOTE("Program Change: Disabled"); LOGNOTE("Program Change: Disabled");
} }
for (unsigned i = 0; i < CConfig::ToneGenerators; i++) for (unsigned i = 0; i < m_nToneGenerators; i++)
{ {
assert (m_pTG[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)); 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 ()) if (m_PerformanceConfig.Load ())
{ {
LoadPerformanceParameters(); LoadPerformanceParameters();
@ -453,15 +467,19 @@ void CMiniDexed::Run (unsigned nCore)
// process the TGs, assigned to this core (2 or 3) // process the TGs, assigned to this core (2 or 3)
assert (m_nFramesToProcess <= CConfig::MaxChunkSize); assert (m_nFramesToProcess <= m_pConfig->MaxChunkSize);
unsigned nTG = CConfig::TGsCore1 + (nCore-2)*CConfig::TGsCore23; unsigned nTG = m_pConfig->GetTGsCore1() + (nCore-2)*m_pConfig->GetTGsCore23();
for (unsigned i = 0; i < CConfig::TGsCore23; i++, nTG++) for (unsigned i = 0; i < m_pConfig->GetTGsCore23(); i++, nTG++)
{
assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_pConfig->GetToneGenerators())
{ {
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
m_pTG[nTG]->getSamples (m_OutputLevel[nTG],m_nFramesToProcess); m_pTG[nTG]->getSamples (m_OutputLevel[nTG],m_nFramesToProcess);
} }
} }
} }
}
} }
#endif #endif
@ -480,7 +498,8 @@ void CMiniDexed::BankSelect (unsigned nBank, unsigned nTG)
{ {
nBank=constrain((int)nBank,0,16383); 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)) if (GetSysExFileLoader ()->IsValidBank(nBank))
{ {
@ -509,7 +528,9 @@ void CMiniDexed::BankSelectMSB (unsigned nBankMSB, unsigned nTG)
{ {
nBankMSB=constrain((int)nBankMSB,0,127); 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: // MIDI Spec 1.0 "BANK SELECT" states:
// "The transmitter must transmit the MSB and LSB as a pair, // "The transmitter must transmit the MSB and LSB as a pair,
// and the Program Change must be sent immediately after // 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); 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 nBank = m_nVoiceBankID[nTG];
unsigned nBankMSB = m_nVoiceBankIDMSB[nTG]; unsigned nBankMSB = m_nVoiceBankIDMSB[nTG];
nBank = (nBankMSB << 7) + nBankLSB; nBank = (nBankMSB << 7) + nBankLSB;
@ -578,7 +601,9 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG)
nProgram=constrain((int)nProgram,0,31); 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; m_nProgram[nTG] = nProgram;
uint8_t Buffer[156]; uint8_t Buffer[156];
@ -617,7 +642,9 @@ void CMiniDexed::SetVolume (unsigned nVolume, unsigned nTG)
{ {
nVolume=constrain((int)nVolume,0,127); 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; m_nVolume[nTG] = nVolume;
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
@ -630,7 +657,9 @@ void CMiniDexed::SetPan (unsigned nPan, unsigned nTG)
{ {
nPan=constrain((int)nPan,0,127); 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; m_nPan[nTG] = nPan;
tg_mixer->pan(nTG,mapfloat(nPan,0,127,0.0f,1.0f)); 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); 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; m_nReverbSend[nTG] = nReverbSend;
reverb_send_mixer->gain(nTG,mapfloat(nReverbSend,0,99,0.0f,1.0f)); 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); 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; m_nMasterTune[nTG] = nMasterTune;
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
@ -668,7 +701,9 @@ void CMiniDexed::SetCutoff (int nCutoff, unsigned nTG)
{ {
nCutoff = constrain (nCutoff, 0, 99); 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; m_nCutoff[nTG] = nCutoff;
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
@ -681,7 +716,9 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG)
{ {
nResonance = constrain (nResonance, 0, 99); 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; m_nResonance[nTG] = nResonance;
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
@ -694,7 +731,9 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG)
void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, 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); assert (uchChannel < CMIDIDevice::ChannelUnknown);
m_nMIDIChannel[nTG] = uchChannel; m_nMIDIChannel[nTG] = uchChannel;
@ -713,6 +752,7 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
} }
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
/* This doesn't appear to be used anywhere...
unsigned nActiveTGs = 0; unsigned nActiveTGs = 0;
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
{ {
@ -725,6 +765,7 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
assert (nActiveTGs <= 8); assert (nActiveTGs <= 8);
static const unsigned Log2[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; static const unsigned Log2[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
m_nActiveTGsLog2 = Log2[nActiveTGs]; m_nActiveTGsLog2 = Log2[nActiveTGs];
*/
#endif #endif
m_UI.ParameterChanged (); m_UI.ParameterChanged ();
@ -732,7 +773,9 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG)
void CMiniDexed::keyup (int16_t pitch, 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]); assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, 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) 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]); assert (m_pTG[nTG]);
pitch = ApplyNoteLimits (pitch, 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) 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] if ( pitch < (int16_t) m_nNoteLimitLow[nTG]
|| pitch > (int16_t) m_nNoteLimitHigh[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) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setSustain (sustain); m_pTG[nTG]->setSustain (sustain);
} }
void CMiniDexed::panic(uint8_t value, unsigned nTG) 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]); assert (m_pTG[nTG]);
if (value == 0) { if (value == 0) {
m_pTG[nTG]->panic (); m_pTG[nTG]->panic ();
@ -793,7 +843,9 @@ void CMiniDexed::panic(uint8_t value, unsigned nTG)
void CMiniDexed::notesOff(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]); assert (m_pTG[nTG]);
if (value == 0) { if (value == 0) {
m_pTG[nTG]->notesOff (); m_pTG[nTG]->notesOff ();
@ -802,7 +854,9 @@ void CMiniDexed::notesOff(uint8_t value, unsigned nTG)
void CMiniDexed::setModWheel (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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setModWheel (value); 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) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setFootController (value); m_pTG[nTG]->setFootController (value);
} }
void CMiniDexed::setBreathController (uint8_t value, unsigned nTG) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setBreathController (value); m_pTG[nTG]->setBreathController (value);
} }
void CMiniDexed::setAftertouch (uint8_t value, unsigned nTG) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setAftertouch (value); m_pTG[nTG]->setAftertouch (value);
} }
void CMiniDexed::setPitchbend (int16_t value, unsigned nTG) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setPitchbend (value); m_pTG[nTG]->setPitchbend (value);
} }
void CMiniDexed::ControllersRefresh (unsigned nTG) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->ControllersRefresh (); m_pTG[nTG]->ControllersRefresh ();
} }
@ -853,7 +917,7 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue)
switch (Parameter) switch (Parameter)
{ {
case ParameterCompressorEnable: case ParameterCompressorEnable:
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) for (unsigned nTG = 0; nTG < m_nToneGenerators; nTG++)
{ {
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
m_pTG[nTG]->setCompressor (!!nValue); m_pTG[nTG]->setCompressor (!!nValue);
@ -931,7 +995,8 @@ int CMiniDexed::GetParameter (TParameter Parameter)
void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nTG) 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) switch (Parameter)
{ {
@ -986,7 +1051,7 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
switch (Parameter) 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) 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 (m_pTG[nTG]);
assert (nOP <= 6); 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) 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 (m_pTG[nTG]);
assert (nOP <= 6); assert (nOP <= 6);
@ -1094,13 +1163,15 @@ std::string CMiniDexed::GetVoiceName (unsigned nTG)
{ {
char VoiceName[11]; char VoiceName[11];
memset (VoiceName, 0, sizeof VoiceName); memset (VoiceName, 0, sizeof VoiceName);
VoiceName[0] = 32; // space
assert (nTG < CConfig::AllToneGenerators);
assert (nTG < CConfig::ToneGenerators); if (nTG < m_nToneGenerators)
{
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
m_pTG[nTG]->setName (VoiceName); m_pTG[nTG]->setName (VoiceName);
}
std::string Result (VoiceName); std::string Result (VoiceName);
return Result; return Result;
} }
@ -1142,6 +1213,7 @@ void CMiniDexed::ProcessSound (void)
void CMiniDexed::ProcessSound (void) void CMiniDexed::ProcessSound (void)
{ {
assert (m_pSoundDevice); assert (m_pSoundDevice);
assert (m_pConfig);
unsigned nFrames = m_nQueueSizeFrames - m_pSoundDevice->GetQueueFramesAvail (); unsigned nFrames = m_nQueueSizeFrames - m_pSoundDevice->GetQueueFramesAvail ();
if (nFrames >= m_nQueueSizeFrames/2) if (nFrames >= m_nQueueSizeFrames/2)
@ -1162,7 +1234,7 @@ void CMiniDexed::ProcessSound (void)
// process the TGs assigned to core 1 // process the TGs assigned to core 1
assert (nFrames <= CConfig::MaxChunkSize); 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]); assert (m_pTG[i]);
m_pTG[i]->getSamples (m_OutputLevel[i], nFrames); m_pTG[i]->getSamples (m_OutputLevel[i], nFrames);
@ -1181,9 +1253,10 @@ void CMiniDexed::ProcessSound (void)
// Audio signal path after tone generators starts here // Audio signal path after tone generators starts here
// //
assert (CConfig::ToneGenerators == 8);
if (m_bQuadDAC8Chan) { 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. // No mixing is performed by MiniDexed, sound is output in 8 channels.
// Note: one TG per audio channel; output=mono; no processing. // Note: one TG per audio channel; output=mono; no processing.
const int Channels = 8; // One TG per channel const int Channels = 8; // One TG per channel
@ -1233,7 +1306,7 @@ void CMiniDexed::ProcessSound (void)
if(nMasterVolume > 0.0) 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]); tg_mixer->doAddMix(i,m_OutputLevel[i]);
reverb_send_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) 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.SetBankNumber (m_nVoiceBankID[nTG], nTG);
m_PerformanceConfig.SetVoiceNumber (m_nProgram[nTG], nTG); m_PerformanceConfig.SetVoiceNumber (m_nProgram[nTG], nTG);
@ -1377,7 +1450,13 @@ bool CMiniDexed::DoSavePerformance (void)
m_PerformanceConfig.SetNoteLimitLow (m_nNoteLimitLow[nTG], nTG); m_PerformanceConfig.SetNoteLimitLow (m_nNoteLimitLow[nTG], nTG);
m_PerformanceConfig.SetNoteLimitHigh (m_nNoteLimitHigh[nTG], nTG); m_PerformanceConfig.SetNoteLimitHigh (m_nNoteLimitHigh[nTG], nTG);
m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG); m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG);
if (nTG < m_pConfig->GetToneGenerators())
{
m_pTG[nTG]->getVoiceData(m_nRawVoiceData); 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.SetVoiceDataToTxt (m_nRawVoiceData, nTG);
m_PerformanceConfig.SetMonoMode (m_bMonoMode[nTG], nTG); m_PerformanceConfig.SetMonoMode (m_bMonoMode[nTG], nTG);
@ -1412,7 +1491,9 @@ bool CMiniDexed::DoSavePerformance (void)
void CMiniDexed::setMonoMode(uint8_t mono, uint8_t nTG) 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]); assert (m_pTG[nTG]);
m_bMonoMode[nTG]= mono != 0; m_bMonoMode[nTG]= mono != 0;
m_pTG[nTG]->setMonoMode(constrain(mono, 0, 1)); 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) void CMiniDexed::setPitchbendRange(uint8_t range, uint8_t nTG)
{ {
range = constrain (range, 0, 12); 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]); assert (m_pTG[nTG]);
m_nPitchBendRange[nTG] = range; 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) void CMiniDexed::setPitchbendStep(uint8_t step, uint8_t nTG)
{ {
step= constrain (step, 0, 12); 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]); assert (m_pTG[nTG]);
m_nPitchBendStep[nTG] = step; m_nPitchBendStep[nTG] = step;
@ -1448,7 +1533,9 @@ void CMiniDexed::setPortamentoMode(uint8_t mode, uint8_t nTG)
{ {
mode= constrain (mode, 0, 1); 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]); assert (m_pTG[nTG]);
m_nPortamentoMode[nTG] = mode; 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) void CMiniDexed::setPortamentoGlissando(uint8_t glissando, uint8_t nTG)
{ {
glissando = constrain (glissando, 0, 1); 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]); assert (m_pTG[nTG]);
m_nPortamentoGlissando[nTG] = glissando; 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) void CMiniDexed::setPortamentoTime(uint8_t time, uint8_t nTG)
{ {
time = constrain (time, 0, 99); 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]); assert (m_pTG[nTG]);
m_nPortamentoTime[nTG] = time; 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) 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]); assert (m_pTG[nTG]);
m_nModulationWheelRange[nTG] = range; 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) 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]); assert (m_pTG[nTG]);
m_nModulationWheelTarget[nTG] = target; 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) 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]); assert (m_pTG[nTG]);
m_nFootControlRange[nTG]=range; 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) 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]); assert (m_pTG[nTG]);
m_nFootControlTarget[nTG] = target; 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) 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]); assert (m_pTG[nTG]);
m_nBreathControlRange[nTG]=range; 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) 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]); assert (m_pTG[nTG]);
m_nBreathControlTarget[nTG]=target; 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) 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]); assert (m_pTG[nTG]);
m_nAftertouchRange[nTG]=range; 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) 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]); assert (m_pTG[nTG]);
m_nAftertouchTarget[nTG]=target; 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) 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]); assert (m_pTG[nTG]);
uint8_t voice[161]; 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) 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]); assert (m_pTG[nTG]);
m_pTG[nTG]->setVoiceDataElement(constrain(data, 0, 155),constrain(number, 0, 99)); 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) 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]); assert (m_pTG[nTG]);
return(m_pTG[nTG]->checkSystemExclusive(pMessage, nLength)); 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 checksum = 0;
uint8_t data[155]; uint8_t data[155];
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_nToneGenerators)
{
assert (m_pTG[nTG]); assert (m_pTG[nTG]);
m_pTG[nTG]->getVoiceData(data); 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[0] = 0xF0; // SysEx start
dest[1] = 0x43; // ID=Yamaha dest[1] = 0x43; // ID=Yamaha
@ -1791,7 +1911,7 @@ bool CMiniDexed::DoSavePerformanceNewFile (void)
void CMiniDexed::LoadPerformanceParameters(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); BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG);
@ -1865,7 +1985,9 @@ bool CMiniDexed::IsValidPerformanceBank(unsigned nBankID)
void CMiniDexed::SetVoiceName (std::string VoiceName, unsigned nTG) 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]); assert (m_pTG[nTG]);
char Name[11]; char Name[11];
strncpy(Name, VoiceName.c_str(),10); strncpy(Name, VoiceName.c_str(),10);

@ -230,7 +230,7 @@ public:
private: private:
int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note 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 LoadPerformanceParameters(void);
void ProcessSound (void); void ProcessSound (void);
@ -250,40 +250,43 @@ private:
int m_nParameter[ParameterUnknown]; // global (non-TG) parameters int m_nParameter[ParameterUnknown]; // global (non-TG) parameters
CDexedAdapter *m_pTG[CConfig::ToneGenerators]; unsigned m_nToneGenerators;
unsigned m_nPolyphony;
unsigned m_nVoiceBankID[CConfig::ToneGenerators]; CDexedAdapter *m_pTG[CConfig::AllToneGenerators];
unsigned m_nVoiceBankIDMSB[CConfig::ToneGenerators];
unsigned m_nVoiceBankID[CConfig::AllToneGenerators];
unsigned m_nVoiceBankIDMSB[CConfig::AllToneGenerators];
unsigned m_nVoiceBankIDPerformance; unsigned m_nVoiceBankIDPerformance;
unsigned m_nVoiceBankIDMSBPerformance; unsigned m_nVoiceBankIDMSBPerformance;
unsigned m_nProgram[CConfig::ToneGenerators]; unsigned m_nProgram[CConfig::AllToneGenerators];
unsigned m_nVolume[CConfig::ToneGenerators]; unsigned m_nVolume[CConfig::AllToneGenerators];
unsigned m_nPan[CConfig::ToneGenerators]; unsigned m_nPan[CConfig::AllToneGenerators];
int m_nMasterTune[CConfig::ToneGenerators]; int m_nMasterTune[CConfig::AllToneGenerators];
int m_nCutoff[CConfig::ToneGenerators]; int m_nCutoff[CConfig::AllToneGenerators];
int m_nResonance[CConfig::ToneGenerators]; int m_nResonance[CConfig::AllToneGenerators];
unsigned m_nMIDIChannel[CConfig::ToneGenerators]; unsigned m_nMIDIChannel[CConfig::AllToneGenerators];
unsigned m_nPitchBendRange[CConfig::ToneGenerators]; unsigned m_nPitchBendRange[CConfig::AllToneGenerators];
unsigned m_nPitchBendStep[CConfig::ToneGenerators]; unsigned m_nPitchBendStep[CConfig::AllToneGenerators];
unsigned m_nPortamentoMode[CConfig::ToneGenerators]; unsigned m_nPortamentoMode[CConfig::AllToneGenerators];
unsigned m_nPortamentoGlissando[CConfig::ToneGenerators]; unsigned m_nPortamentoGlissando[CConfig::AllToneGenerators];
unsigned m_nPortamentoTime[CConfig::ToneGenerators]; unsigned m_nPortamentoTime[CConfig::AllToneGenerators];
bool m_bMonoMode[CConfig::ToneGenerators]; bool m_bMonoMode[CConfig::AllToneGenerators];
unsigned m_nModulationWheelRange[CConfig::ToneGenerators]; unsigned m_nModulationWheelRange[CConfig::AllToneGenerators];
unsigned m_nModulationWheelTarget[CConfig::ToneGenerators]; unsigned m_nModulationWheelTarget[CConfig::AllToneGenerators];
unsigned m_nFootControlRange[CConfig::ToneGenerators]; unsigned m_nFootControlRange[CConfig::AllToneGenerators];
unsigned m_nFootControlTarget[CConfig::ToneGenerators]; unsigned m_nFootControlTarget[CConfig::AllToneGenerators];
unsigned m_nBreathControlRange[CConfig::ToneGenerators]; unsigned m_nBreathControlRange[CConfig::AllToneGenerators];
unsigned m_nBreathControlTarget[CConfig::ToneGenerators]; unsigned m_nBreathControlTarget[CConfig::AllToneGenerators];
unsigned m_nAftertouchRange[CConfig::ToneGenerators]; unsigned m_nAftertouchRange[CConfig::AllToneGenerators];
unsigned m_nAftertouchTarget[CConfig::ToneGenerators]; unsigned m_nAftertouchTarget[CConfig::AllToneGenerators];
unsigned m_nNoteLimitLow[CConfig::ToneGenerators]; unsigned m_nNoteLimitLow[CConfig::AllToneGenerators];
unsigned m_nNoteLimitHigh[CConfig::ToneGenerators]; unsigned m_nNoteLimitHigh[CConfig::AllToneGenerators];
int m_nNoteShift[CConfig::ToneGenerators]; int m_nNoteShift[CConfig::AllToneGenerators];
unsigned m_nReverbSend[CConfig::ToneGenerators]; unsigned m_nReverbSend[CConfig::AllToneGenerators];
uint8_t m_nRawVoiceData[156]; uint8_t m_nRawVoiceData[156];
@ -305,18 +308,18 @@ private:
unsigned m_nQueueSizeFrames; unsigned m_nQueueSizeFrames;
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
unsigned m_nActiveTGsLog2; // unsigned m_nActiveTGsLog2;
volatile TCoreStatus m_CoreStatus[CORES]; volatile TCoreStatus m_CoreStatus[CORES];
volatile unsigned m_nFramesToProcess; volatile unsigned m_nFramesToProcess;
float32_t m_OutputLevel[CConfig::ToneGenerators][CConfig::MaxChunkSize]; float32_t m_OutputLevel[CConfig::AllToneGenerators][CConfig::MaxChunkSize];
#endif #endif
CPerformanceTimer m_GetChunkTimer; CPerformanceTimer m_GetChunkTimer;
bool m_bProfileEnabled; bool m_bProfileEnabled;
AudioEffectPlateReverb* reverb; AudioEffectPlateReverb* reverb;
AudioStereoMixer<CConfig::ToneGenerators>* tg_mixer; AudioStereoMixer<CConfig::AllToneGenerators>* tg_mixer;
AudioStereoMixer<CConfig::ToneGenerators>* reverb_send_mixer; AudioStereoMixer<CConfig::AllToneGenerators>* reverb_send_mixer;
CSpinLock m_ReverbSpinLock; 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 // Check intermal performance directory exists
DIR Directory; DIR Directory;
FRESULT Result; FRESULT Result;
@ -95,7 +107,7 @@ bool CPerformanceConfig::Load (void)
bool bResult = false; bool bResult = false;
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++)
{ {
CString PropertyName; CString PropertyName;
@ -110,7 +122,7 @@ bool CPerformanceConfig::Load (void)
} }
PropertyName.Format ("MIDIChannel%u", nTG+1); PropertyName.Format ("MIDIChannel%u", nTG+1);
unsigned nMIDIChannel = m_Properties.GetNumber (PropertyName, 255); unsigned nMIDIChannel = m_Properties.GetNumber (PropertyName, 0);
if (nMIDIChannel == 0) if (nMIDIChannel == 0)
{ {
m_nMIDIChannel[nTG] = CMIDIDevice::Disabled; m_nMIDIChannel[nTG] = CMIDIDevice::Disabled;
@ -217,7 +229,7 @@ bool CPerformanceConfig::Save (void)
{ {
m_Properties.RemoveAll (); m_Properties.RemoveAll ();
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) for (unsigned nTG = 0; nTG < m_nToneGenerators; nTG++)
{ {
CString PropertyName; CString PropertyName;
@ -333,145 +345,145 @@ bool CPerformanceConfig::Save (void)
unsigned CPerformanceConfig::GetBankNumber (unsigned nTG) const unsigned CPerformanceConfig::GetBankNumber (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nBankNumber[nTG]; return m_nBankNumber[nTG];
} }
unsigned CPerformanceConfig::GetVoiceNumber (unsigned nTG) const unsigned CPerformanceConfig::GetVoiceNumber (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nVoiceNumber[nTG]; return m_nVoiceNumber[nTG];
} }
unsigned CPerformanceConfig::GetMIDIChannel (unsigned nTG) const unsigned CPerformanceConfig::GetMIDIChannel (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nMIDIChannel[nTG]; return m_nMIDIChannel[nTG];
} }
unsigned CPerformanceConfig::GetVolume (unsigned nTG) const unsigned CPerformanceConfig::GetVolume (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nVolume[nTG]; return m_nVolume[nTG];
} }
unsigned CPerformanceConfig::GetPan (unsigned nTG) const unsigned CPerformanceConfig::GetPan (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPan[nTG]; return m_nPan[nTG];
} }
int CPerformanceConfig::GetDetune (unsigned nTG) const int CPerformanceConfig::GetDetune (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nDetune[nTG]; return m_nDetune[nTG];
} }
unsigned CPerformanceConfig::GetCutoff (unsigned nTG) const unsigned CPerformanceConfig::GetCutoff (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nCutoff[nTG]; return m_nCutoff[nTG];
} }
unsigned CPerformanceConfig::GetResonance (unsigned nTG) const unsigned CPerformanceConfig::GetResonance (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nResonance[nTG]; return m_nResonance[nTG];
} }
unsigned CPerformanceConfig::GetNoteLimitLow (unsigned nTG) const unsigned CPerformanceConfig::GetNoteLimitLow (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nNoteLimitLow[nTG]; return m_nNoteLimitLow[nTG];
} }
unsigned CPerformanceConfig::GetNoteLimitHigh (unsigned nTG) const unsigned CPerformanceConfig::GetNoteLimitHigh (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nNoteLimitHigh[nTG]; return m_nNoteLimitHigh[nTG];
} }
int CPerformanceConfig::GetNoteShift (unsigned nTG) const int CPerformanceConfig::GetNoteShift (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nNoteShift[nTG]; return m_nNoteShift[nTG];
} }
unsigned CPerformanceConfig::GetReverbSend (unsigned nTG) const unsigned CPerformanceConfig::GetReverbSend (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nReverbSend[nTG]; return m_nReverbSend[nTG];
} }
void CPerformanceConfig::SetBankNumber (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetBankNumber (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nBankNumber[nTG] = nValue; m_nBankNumber[nTG] = nValue;
} }
void CPerformanceConfig::SetVoiceNumber (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetVoiceNumber (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nVoiceNumber[nTG] = nValue; m_nVoiceNumber[nTG] = nValue;
} }
void CPerformanceConfig::SetMIDIChannel (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetMIDIChannel (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nMIDIChannel[nTG] = nValue; m_nMIDIChannel[nTG] = nValue;
} }
void CPerformanceConfig::SetVolume (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetVolume (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nVolume[nTG] = nValue; m_nVolume[nTG] = nValue;
} }
void CPerformanceConfig::SetPan (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPan (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPan[nTG] = nValue; m_nPan[nTG] = nValue;
} }
void CPerformanceConfig::SetDetune (int nValue, unsigned nTG) void CPerformanceConfig::SetDetune (int nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nDetune[nTG] = nValue; m_nDetune[nTG] = nValue;
} }
void CPerformanceConfig::SetCutoff (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetCutoff (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nCutoff[nTG] = nValue; m_nCutoff[nTG] = nValue;
} }
void CPerformanceConfig::SetResonance (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetResonance (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nResonance[nTG] = nValue; m_nResonance[nTG] = nValue;
} }
void CPerformanceConfig::SetNoteLimitLow (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetNoteLimitLow (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nNoteLimitLow[nTG] = nValue; m_nNoteLimitLow[nTG] = nValue;
} }
void CPerformanceConfig::SetNoteLimitHigh (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetNoteLimitHigh (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nNoteLimitHigh[nTG] = nValue; m_nNoteLimitHigh[nTG] = nValue;
} }
void CPerformanceConfig::SetNoteShift (int nValue, unsigned nTG) void CPerformanceConfig::SetNoteShift (int nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nNoteShift[nTG] = nValue; m_nNoteShift[nTG] = nValue;
} }
void CPerformanceConfig::SetReverbSend (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetReverbSend (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nReverbSend[nTG] = nValue; m_nReverbSend[nTG] = nValue;
} }
@ -557,71 +569,71 @@ void CPerformanceConfig::SetReverbLevel (unsigned nValue)
// Pitch bender and portamento: // Pitch bender and portamento:
void CPerformanceConfig::SetPitchBendRange (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPitchBendRange (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPitchBendRange[nTG] = nValue; m_nPitchBendRange[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetPitchBendRange (unsigned nTG) const unsigned CPerformanceConfig::GetPitchBendRange (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPitchBendRange[nTG]; return m_nPitchBendRange[nTG];
} }
void CPerformanceConfig::SetPitchBendStep (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPitchBendStep (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPitchBendStep[nTG] = nValue; m_nPitchBendStep[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetPitchBendStep (unsigned nTG) const unsigned CPerformanceConfig::GetPitchBendStep (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPitchBendStep[nTG]; return m_nPitchBendStep[nTG];
} }
void CPerformanceConfig::SetPortamentoMode (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPortamentoMode (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoMode[nTG] = nValue; m_nPortamentoMode[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetPortamentoMode (unsigned nTG) const unsigned CPerformanceConfig::GetPortamentoMode (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoMode[nTG]; return m_nPortamentoMode[nTG];
} }
void CPerformanceConfig::SetPortamentoGlissando (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPortamentoGlissando (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoGlissando[nTG] = nValue; m_nPortamentoGlissando[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetPortamentoGlissando (unsigned nTG) const unsigned CPerformanceConfig::GetPortamentoGlissando (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoGlissando[nTG]; return m_nPortamentoGlissando[nTG];
} }
void CPerformanceConfig::SetPortamentoTime (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetPortamentoTime (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nPortamentoTime[nTG] = nValue; m_nPortamentoTime[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetPortamentoTime (unsigned nTG) const unsigned CPerformanceConfig::GetPortamentoTime (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nPortamentoTime[nTG]; return m_nPortamentoTime[nTG];
} }
void CPerformanceConfig::SetMonoMode (bool bValue, unsigned nTG) void CPerformanceConfig::SetMonoMode (bool bValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_bMonoMode[nTG] = bValue; m_bMonoMode[nTG] = bValue;
} }
@ -632,103 +644,103 @@ bool CPerformanceConfig::GetMonoMode (unsigned nTG) const
void CPerformanceConfig::SetModulationWheelRange (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetModulationWheelRange (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nModulationWheelRange[nTG] = nValue; m_nModulationWheelRange[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetModulationWheelRange (unsigned nTG) const unsigned CPerformanceConfig::GetModulationWheelRange (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nModulationWheelRange[nTG]; return m_nModulationWheelRange[nTG];
} }
void CPerformanceConfig::SetModulationWheelTarget (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetModulationWheelTarget (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nModulationWheelTarget[nTG] = nValue; m_nModulationWheelTarget[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetModulationWheelTarget (unsigned nTG) const unsigned CPerformanceConfig::GetModulationWheelTarget (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nModulationWheelTarget[nTG]; return m_nModulationWheelTarget[nTG];
} }
void CPerformanceConfig::SetFootControlRange (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetFootControlRange (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nFootControlRange[nTG] = nValue; m_nFootControlRange[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetFootControlRange (unsigned nTG) const unsigned CPerformanceConfig::GetFootControlRange (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nFootControlRange[nTG]; return m_nFootControlRange[nTG];
} }
void CPerformanceConfig::SetFootControlTarget (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetFootControlTarget (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nFootControlTarget[nTG] = nValue; m_nFootControlTarget[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetFootControlTarget (unsigned nTG) const unsigned CPerformanceConfig::GetFootControlTarget (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nFootControlTarget[nTG]; return m_nFootControlTarget[nTG];
} }
void CPerformanceConfig::SetBreathControlRange (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetBreathControlRange (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nBreathControlRange[nTG] = nValue; m_nBreathControlRange[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetBreathControlRange (unsigned nTG) const unsigned CPerformanceConfig::GetBreathControlRange (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nBreathControlRange[nTG]; return m_nBreathControlRange[nTG];
} }
void CPerformanceConfig::SetBreathControlTarget (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetBreathControlTarget (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nBreathControlTarget[nTG] = nValue; m_nBreathControlTarget[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetBreathControlTarget (unsigned nTG) const unsigned CPerformanceConfig::GetBreathControlTarget (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nBreathControlTarget[nTG]; return m_nBreathControlTarget[nTG];
} }
void CPerformanceConfig::SetAftertouchRange (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetAftertouchRange (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nAftertouchRange[nTG] = nValue; m_nAftertouchRange[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetAftertouchRange (unsigned nTG) const unsigned CPerformanceConfig::GetAftertouchRange (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nAftertouchRange[nTG]; return m_nAftertouchRange[nTG];
} }
void CPerformanceConfig::SetAftertouchTarget (unsigned nValue, unsigned nTG) void CPerformanceConfig::SetAftertouchTarget (unsigned nValue, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nAftertouchTarget[nTG] = nValue; m_nAftertouchTarget[nTG] = nValue;
} }
unsigned CPerformanceConfig::GetAftertouchTarget (unsigned nTG) const unsigned CPerformanceConfig::GetAftertouchTarget (unsigned nTG) const
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
return m_nAftertouchTarget[nTG]; return m_nAftertouchTarget[nTG];
} }
void CPerformanceConfig::SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG) void CPerformanceConfig::SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
m_nVoiceDataTxt[nTG] = ""; m_nVoiceDataTxt[nTG] = "";
char nDtoH[]="0123456789ABCDEF"; char nDtoH[]="0123456789ABCDEF";
for (int i = 0; i < NUM_VOICE_PARAM; i++) 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) uint8_t *CPerformanceConfig::GetVoiceDataFromTxt (unsigned nTG)
{ {
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
static uint8_t pData[NUM_VOICE_PARAM]; static uint8_t pData[NUM_VOICE_PARAM];
std::string nHtoD="0123456789ABCDEF"; std::string nHtoD="0123456789ABCDEF";

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

@ -273,6 +273,23 @@ std::string CSysExFileLoader::GetBankName (unsigned nBankID)
return "NO NAME"; 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) unsigned CSysExFileLoader::GetNextBankUp (unsigned nBankID)
{ {
// Find the next loaded bank "up" from the provided bank ID // Find the next loaded bank "up" from the provided bank ID

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

@ -51,6 +51,16 @@ const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] =
{"TG6", MenuHandler, s_TGMenu, 5}, {"TG6", MenuHandler, s_TGMenu, 5},
{"TG7", MenuHandler, s_TGMenu, 6}, {"TG7", MenuHandler, s_TGMenu, 6},
{"TG8", MenuHandler, s_TGMenu, 7}, {"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 #endif
{"Effects", MenuHandler, s_EffectsMenu}, {"Effects", MenuHandler, s_EffectsMenu},
{"Performance", MenuHandler, s_PerformanceMenu}, {"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_pUI (pUI),
m_pMiniDexed (pMiniDexed), m_pMiniDexed (pMiniDexed),
m_pConfig (pConfig),
m_pParentMenu (s_MenuRoot), m_pParentMenu (s_MenuRoot),
m_pCurrentMenu (s_MainMenu), m_pCurrentMenu (s_MainMenu),
m_nCurrentMenuItem (0), m_nCurrentMenuItem (0),
@ -344,7 +355,11 @@ CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed)
m_nCurrentParameter (0), m_nCurrentParameter (0),
m_nCurrentMenuDepth (0) m_nCurrentMenuDepth (0)
{ {
#ifndef ARM_ALLOW_MULTI_CORE assert (m_pConfig);
m_nToneGenerators = m_pConfig->GetToneGenerators();
if (m_nToneGenerators == 1)
{
// If there is just one core, then there is only a single // If there is just one core, then there is only a single
// tone generator so start on the TG1 menu... // tone generator so start on the TG1 menu...
m_pParentMenu = s_MainMenu; m_pParentMenu = s_MainMenu;
@ -360,7 +375,7 @@ CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed)
m_nMenuStackItem[0] = 0; m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0; m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0; m_nMenuStackParameter[0] = 0;
#endif }
} }
void CUIMenu::EventHandler (TMenuEvent Event) void CUIMenu::EventHandler (TMenuEvent Event)
@ -383,14 +398,8 @@ void CUIMenu::EventHandler (TMenuEvent Event)
break; break;
case MenuEventHome: case MenuEventHome:
#ifdef ARM_ALLOW_MULTI_CORE if (m_nToneGenerators == 1)
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 // "Home" is the TG0 menu if only one TG active
m_pParentMenu = s_MainMenu; m_pParentMenu = s_MainMenu;
m_pCurrentMenu = s_TGMenu; m_pCurrentMenu = s_TGMenu;
@ -404,7 +413,16 @@ void CUIMenu::EventHandler (TMenuEvent Event)
m_nMenuStackItem[0] = 0; m_nMenuStackItem[0] = 0;
m_nMenuStackSelection[0] = 0; m_nMenuStackSelection[0] = 0;
m_nMenuStackParameter[0] = 0; m_nMenuStackParameter[0] = 0;
#endif }
else
{
m_pParentMenu = s_MenuRoot;
m_pCurrentMenu = s_MainMenu;
m_nCurrentMenuItem = 0;
m_nCurrentSelection = 0;
m_nCurrentParameter = 0;
m_nCurrentMenuDepth = 0;
}
EventHandler (MenuEventUpdate); EventHandler (MenuEventUpdate);
break; break;
@ -453,7 +471,30 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
break; break;
case MenuEventStepDown: 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--; pUIMenu->m_nCurrentSelection--;
} }
@ -463,8 +504,28 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event)
++pUIMenu->m_nCurrentSelection; ++pUIMenu->m_nCurrentSelection;
if (!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name) // more entries? if (!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name) // more entries?
{ {
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--; 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; break;
default: default:
@ -1151,7 +1212,7 @@ void CUIMenu::TGShortcutHandler (TMenuEvent Event)
assert (m_nCurrentMenuDepth >= 2); assert (m_nCurrentMenuDepth >= 2);
assert (m_MenuStackMenu[0] = s_MainMenu); assert (m_MenuStackMenu[0] = s_MainMenu);
unsigned nTG = m_nMenuStackSelection[0]; unsigned nTG = m_nMenuStackSelection[0];
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
assert (m_nMenuStackItem[1] == nTG); assert (m_nMenuStackItem[1] == nTG);
assert (m_nMenuStackParameter[1] == nTG); assert (m_nMenuStackParameter[1] == nTG);
@ -1166,7 +1227,7 @@ void CUIMenu::TGShortcutHandler (TMenuEvent Event)
nTG++; nTG++;
} }
if (nTG < CConfig::ToneGenerators) if (nTG < m_nToneGenerators)
{ {
m_nMenuStackSelection[0] = nTG; m_nMenuStackSelection[0] = nTG;
m_nMenuStackItem[1] = nTG; m_nMenuStackItem[1] = nTG;
@ -1262,8 +1323,9 @@ void CUIMenu::PgmUpDownHandler (TMenuEvent Event)
if (m_MenuStackMenu[0] == s_MainMenu && (m_pCurrentMenu == s_TGMenu) || (m_MenuStackMenu[1] == s_TGMenu)) { if (m_MenuStackMenu[0] == s_MainMenu && (m_pCurrentMenu == s_TGMenu) || (m_MenuStackMenu[1] == s_TGMenu)) {
nTG = m_nMenuStackSelection[0]; nTG = m_nMenuStackSelection[0];
} }
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
if (nTG < m_nToneGenerators)
{
int nPgm = m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterProgram, nTG); int nPgm = m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterProgram, nTG);
assert (Event == MenuEventPgmDown || Event == MenuEventPgmUp); assert (Event == MenuEventPgmDown || Event == MenuEventPgmUp);
@ -1310,6 +1372,7 @@ void CUIMenu::PgmUpDownHandler (TMenuEvent Event)
} }
} }
} }
}
} }
void CUIMenu::TGUpDownHandler (TMenuEvent Event) void CUIMenu::TGUpDownHandler (TMenuEvent Event)
@ -1317,7 +1380,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
// This will update the menus to position it for the next TG up or down // This will update the menus to position it for the next TG up or down
unsigned nTG = 0; unsigned nTG = 0;
if (CConfig::ToneGenerators <= 1) { if (m_nToneGenerators <= 1) {
// Nothing to do if only a single TG // Nothing to do if only a single TG
return; return;
} }
@ -1328,7 +1391,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
nTG = m_nMenuStackSelection[0]; nTG = m_nMenuStackSelection[0];
} }
assert (nTG < CConfig::ToneGenerators); assert (nTG < CConfig::AllToneGenerators);
assert (Event == MenuEventTGDown || Event == MenuEventTGUp); assert (Event == MenuEventTGDown || Event == MenuEventTGUp);
if (Event == MenuEventTGDown) if (Event == MenuEventTGDown)
{ {
@ -1340,7 +1403,7 @@ void CUIMenu::TGUpDownHandler (TMenuEvent Event)
else else
{ {
//LOGNOTE("TGUp"); //LOGNOTE("TGUp");
if (nTG < CConfig::ToneGenerators - 1) { if (nTG < m_nToneGenerators - 1) {
nTG++; nTG++;
} }
} }

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

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

Loading…
Cancel
Save