Merge branch 'probonopd:main' into main

pull/443/head
Luca 2 years ago committed by GitHub
commit b13dd882b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      src/config.cpp
  2. 4
      src/config.h
  3. 6
      src/mididevice.cpp
  4. 73
      src/minidexed.cpp
  5. 7
      src/minidexed.h
  6. 2
      src/minidexed.ini
  7. 247
      src/sysexfileloader.cpp
  8. 21
      src/sysexfileloader.h
  9. 50
      src/uimenu.cpp
  10. 13
      submod.sh

@ -81,6 +81,8 @@ void CConfig::Load (void)
m_bMIDIRXProgramChange = m_Properties.GetNumber ("MIDIRXProgramChange", 1) != 0;
m_bIgnoreAllNotesOff = m_Properties.GetNumber ("IgnoreAllNotesOff", 0) != 0;
m_bMIDIAutoVoiceDumpOnPC = m_Properties.GetNumber ("MIDIAutoVoiceDumpOnPC", 1) != 0;
m_bHeaderlessSysExVoices = m_Properties.GetNumber ("HeaderlessSysExVoices", 0) != 0;
m_bExpandPCAcrossBanks = m_Properties.GetNumber ("ExpandPCAcrossBanks", 1) != 0;
m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0;
m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4);
@ -194,6 +196,16 @@ bool CConfig::GetMIDIAutoVoiceDumpOnPC (void) const
return m_bMIDIAutoVoiceDumpOnPC;
}
bool CConfig::GetHeaderlessSysExVoices (void) const
{
return m_bHeaderlessSysExVoices;
}
bool CConfig::GetExpandPCAcrossBanks (void) const
{
return m_bExpandPCAcrossBanks;
}
bool CConfig::GetLCDEnabled (void) const
{
return m_bLCDEnabled;

@ -78,6 +78,8 @@ public:
bool GetMIDIRXProgramChange (void) const; // true if not specified
bool GetIgnoreAllNotesOff (void) const;
bool GetMIDIAutoVoiceDumpOnPC (void) const; // true if not specified
bool GetHeaderlessSysExVoices (void) const; // false if not specified
bool GetExpandPCAcrossBanks (void) const; // true if not specified
// HD44780 LCD
// GPIO pin numbers are chip numbers, not header positions
@ -159,6 +161,8 @@ private:
bool m_bMIDIRXProgramChange;
bool m_bIgnoreAllNotesOff;
bool m_bMIDIAutoVoiceDumpOnPC;
bool m_bHeaderlessSysExVoices;
bool m_bExpandPCAcrossBanks;
bool m_bLCDEnabled;
unsigned m_nLCDPinEnable;

@ -36,7 +36,7 @@ LOGMODULE ("mididevice");
#define MIDI_AFTERTOUCH 0b1010 // TODO
#define MIDI_CHANNEL_AFTERTOUCH 0b1101 // right now Synth_Dexed just manage Channel Aftertouch not Polyphonic AT -> 0b1010
#define MIDI_CONTROL_CHANGE 0b1011
#define MIDI_CC_BANK_SELECT_MSB 0 // TODO
#define MIDI_CC_BANK_SELECT_MSB 0
#define MIDI_CC_MODULATION 1
#define MIDI_CC_BREATH_CONTROLLER 2
#define MIDI_CC_FOOT_PEDAL 4
@ -283,6 +283,10 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign
m_pSynthesizer->SetPan (pMessage[2], nTG);
break;
case MIDI_CC_BANK_SELECT_MSB:
m_pSynthesizer->BankSelectMSB (pMessage[2], nTG);
break;
case MIDI_CC_BANK_SELECT_LSB:
m_pSynthesizer->BankSelectLSB (pMessage[2], nTG);
break;

@ -61,6 +61,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
m_nVoiceBankID[i] = 0;
m_nVoiceBankIDMSB[i] = 0;
m_nProgram[i] = 0;
m_nVolume[i] = 100;
m_nPan[i] = 64;
@ -170,7 +171,7 @@ bool CMiniDexed::Initialize (void)
return false;
}
m_SysExFileLoader.Load ();
m_SysExFileLoader.Load (m_pConfig->GetHeaderlessSysExVoices ());
if (m_SerialMIDI.Initialize ())
{
@ -366,27 +367,81 @@ CSysExFileLoader *CMiniDexed::GetSysExFileLoader (void)
return &m_SysExFileLoader;
}
void CMiniDexed::BankSelect (unsigned nBank, unsigned nTG)
{
nBank=constrain((int)nBank,0,16383);
assert (nTG < CConfig::ToneGenerators);
if (GetSysExFileLoader ()->IsValidBank(nBank))
{
// Only change if we have the bank loaded
m_nVoiceBankID[nTG] = nBank;
m_UI.ParameterChanged ();
}
}
void CMiniDexed::BankSelectMSB (unsigned nBankMSB, unsigned nTG)
{
nBankMSB=constrain((int)nBankMSB,0,127);
assert (nTG < CConfig::ToneGenerators);
// 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
// the Bank Select pair."
//
// So it isn't possible to validate the selected bank ID until
// we receive both MSB and LSB so just store the MSB for now.
m_nVoiceBankIDMSB[nTG] = nBankMSB;
}
void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG)
{
nBankLSB=constrain((int)nBankLSB,0,127);
assert (nTG < CConfig::ToneGenerators);
m_nVoiceBankID[nTG] = nBankLSB;
unsigned nBank = m_nVoiceBankID[nTG];
unsigned nBankMSB = m_nVoiceBankIDMSB[nTG];
nBank = (nBankMSB << 7) + nBankLSB;
m_UI.ParameterChanged ();
// Now should have both MSB and LSB so enable the BankSelect
BankSelect(nBank, nTG);
}
void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG)
{
assert (m_pConfig);
nProgram=constrain((int)nProgram,0,31);
unsigned nBankOffset;
bool bPCAcrossBanks = m_pConfig->GetExpandPCAcrossBanks();
if (bPCAcrossBanks)
{
// Note: This doesn't actually change the bank in use
// but will allow PC messages of 0..127
// to select across four consecutive banks of voices.
//
// So if the current bank = 5 then:
// PC 0-31 = Bank 5, Program 0-31
// PC 32-63 = Bank 6, Program 0-31
// PC 64-95 = Bank 7, Program 0-31
// PC 96-127 = Bank 8, Program 0-31
nProgram=constrain((int)nProgram,0,127);
nBankOffset = nProgram >> 5;
nProgram = nProgram % 32;
}
else
{
nBankOffset = 0;
nProgram=constrain((int)nProgram,0,31);
}
assert (nTG < CConfig::ToneGenerators);
m_nProgram[nTG] = nProgram;
uint8_t Buffer[156];
m_SysExFileLoader.GetVoice (m_nVoiceBankID[nTG], nProgram, Buffer);
m_SysExFileLoader.GetVoice (m_nVoiceBankID[nTG]+nBankOffset, nProgram, Buffer);
assert (m_pTG[nTG]);
m_pTG[nTG]->loadVoiceParameters (Buffer);
@ -718,7 +773,9 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT
switch (Parameter)
{
case TGParameterVoiceBank: BankSelectLSB (nValue, nTG); break;
case TGParameterVoiceBank: BankSelect (nValue, nTG); break;
case TGParameterVoiceBankMSB: BankSelectMSB (nValue, nTG); break;
case TGParameterVoiceBankLSB: BankSelectLSB (nValue, nTG); break;
case TGParameterProgram: ProgramChange (nValue, nTG); break;
case TGParameterVolume: SetVolume (nValue, nTG); break;
case TGParameterPan: SetPan (nValue, nTG); break;
@ -772,6 +829,8 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG)
switch (Parameter)
{
case TGParameterVoiceBank: return m_nVoiceBankID[nTG];
case TGParameterVoiceBankMSB: return m_nVoiceBankID[nTG] >> 7;
case TGParameterVoiceBankLSB: return m_nVoiceBankID[nTG] & 0x7F;
case TGParameterProgram: return m_nProgram[nTG];
case TGParameterVolume: return m_nVolume[nTG];
case TGParameterPan: return m_nPan[nTG];
@ -1446,7 +1505,7 @@ void CMiniDexed::LoadPerformanceParameters(void)
for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++)
{
BankSelectLSB (m_PerformanceConfig.GetBankNumber (nTG), nTG);
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG);
ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG);
SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG);
SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG);

@ -63,6 +63,8 @@ public:
CSysExFileLoader *GetSysExFileLoader (void);
void BankSelect (unsigned nBank, unsigned nTG);
void BankSelectMSB (unsigned nBankMSB, unsigned nTG);
void BankSelectLSB (unsigned nBankLSB, unsigned nTG);
void ProgramChange (unsigned nProgram, unsigned nTG);
void SetVolume (unsigned nVolume, unsigned nTG);
@ -124,6 +126,7 @@ public:
bool GetPerformanceSelectToLoad(void);
bool SavePerformance (bool bSaveAsDeault);
// Must match the order in CUIMenu::TParameter
enum TParameter
{
ParameterCompressorEnable,
@ -146,9 +149,12 @@ public:
bool DeletePerformance(unsigned nID);
bool DoDeletePerformance(void);
// Must match the order in CUIMenu::TGParameter
enum TTGParameter
{
TGParameterVoiceBank,
TGParameterVoiceBankMSB,
TGParameterVoiceBankLSB,
TGParameterProgram,
TGParameterVolume,
TGParameterPan,
@ -227,6 +233,7 @@ private:
CDexedAdapter *m_pTG[CConfig::ToneGenerators];
unsigned m_nVoiceBankID[CConfig::ToneGenerators];
unsigned m_nVoiceBankIDMSB[CConfig::ToneGenerators];
unsigned m_nProgram[CConfig::ToneGenerators];
unsigned m_nVolume[CConfig::ToneGenerators];
unsigned m_nPan[CConfig::ToneGenerators];

@ -19,6 +19,8 @@ MIDIBaudRate=31250
MIDIRXProgramChange=1
IgnoreAllNotesOff=0
MIDIAutoVoiceDumpOnPC=1
HeaderlessSysExVoices=0
ExpandPCAcrossBanks=1
# HD44780 LCD
LCDEnabled=1

@ -65,7 +65,7 @@ CSysExFileLoader::CSysExFileLoader (const char *pDirName)
: m_DirName (pDirName)
{
m_DirName += "/voice";
m_nNumLoadedBanks = 0;
m_nNumHighestBank = 0;
for (unsigned i = 0; i <= MaxVoiceBankID; i++)
{
@ -81,9 +81,10 @@ CSysExFileLoader::~CSysExFileLoader (void)
}
}
void CSysExFileLoader::Load (void)
void CSysExFileLoader::Load (bool bHeaderlessSysExVoices)
{
m_nNumLoadedBanks = 0;
m_nNumHighestBank = 0;
m_nBanksLoaded = 0;
DIR *pDirectory = opendir (m_DirName.c_str ());
if (!pDirectory)
@ -96,71 +97,155 @@ void CSysExFileLoader::Load (void)
dirent *pEntry;
while ((pEntry = readdir (pDirectory)) != nullptr)
{
unsigned nBank;
size_t nLen = strlen (pEntry->d_name);
LoadBank(m_DirName.c_str (), pEntry->d_name, bHeaderlessSysExVoices, 0);
}
LOGDBG ("%u Banks loaded. Highest Bank loaded: #%u", m_nBanksLoaded, m_nNumHighestBank);
if ( nLen < 5 // "[NNNN]N[_name].syx"
|| strcasecmp (&pEntry->d_name[nLen-4], ".syx") != 0
|| sscanf (pEntry->d_name, "%u", &nBank) != 1)
{
LOGWARN ("%s: Invalid filename format", pEntry->d_name);
closedir (pDirectory);
}
continue;
}
void CSysExFileLoader::LoadBank (const char * sDirName, const char * sBankName, bool bHeaderlessSysExVoices, unsigned nSubDirCount)
{
unsigned nBank;
size_t nLen = strlen (sBankName);
if ( nLen < 5 // "[NNNN]N[_name].syx"
|| strcasecmp (&sBankName[nLen-4], ".syx") != 0
|| sscanf (sBankName, "%u", &nBank) != 1)
{
// See if this is a subdirectory...
std::string Dirname (sDirName);
Dirname += "/";
Dirname += sBankName;
if (nBank > MaxVoiceBankID)
DIR *pDirectory = opendir (Dirname.c_str ());
if (pDirectory)
{
LOGWARN ("Bank #%u is not supported", nBank);
if (nSubDirCount >= MaxSubDirs)
{
LOGWARN ("Too many nested subdirectories: %s", sBankName);
return;
}
LOGDBG ("Processing subdirectory %s", sBankName);
continue;
dirent *pEntry;
while ((pEntry = readdir (pDirectory)) != nullptr)
{
LoadBank(Dirname.c_str (), pEntry->d_name, bHeaderlessSysExVoices, nSubDirCount+1);
}
closedir (pDirectory);
}
if (m_pVoiceBank[nBank])
else
{
LOGWARN ("Bank #%u already loaded", nBank);
continue;
LOGWARN ("%s: Invalid filename format", sBankName);
}
m_pVoiceBank[nBank] = new TVoiceBank;
assert (m_pVoiceBank[nBank]);
return;
}
// File and UI handling requires banks to be 1..indexed.
// Internally (and via MIDI) we need 0..indexed.
// Any mention of a BankID internally is assumed to be 0..indexed.
unsigned nBankIdx = nBank - 1;
// BankIdx goes from 0 to MaxVoiceBankID inclusive
if (nBankIdx > MaxVoiceBankID)
{
LOGWARN ("Bank #%u is not supported", nBank);
return;
}
if (m_pVoiceBank[nBankIdx])
{
LOGWARN ("Bank #%u already loaded", nBank);
return;
}
m_pVoiceBank[nBankIdx] = new TVoiceBank;
assert (m_pVoiceBank[nBankIdx]);
assert (sizeof(TVoiceBank) == VoiceSysExHdrSize + VoiceSysExSize);
std::string Filename (m_DirName);
Filename += "/";
Filename += pEntry->d_name;
std::string Filename (sDirName);
Filename += "/";
Filename += sBankName;
FILE *pFile = fopen (Filename.c_str (), "rb");
if (pFile)
FILE *pFile = fopen (Filename.c_str (), "rb");
if (pFile)
{
bool bBankLoaded = false;
if ( fread (m_pVoiceBank[nBankIdx], VoiceSysExHdrSize+VoiceSysExSize, 1, pFile) == 1
&& m_pVoiceBank[nBankIdx]->StatusStart == 0xF0
&& m_pVoiceBank[nBankIdx]->CompanyID == 0x43
&& m_pVoiceBank[nBankIdx]->Format == 0x09
&& m_pVoiceBank[nBankIdx]->StatusEnd == 0xF7)
{
if ( fread (m_pVoiceBank[nBank], sizeof (TVoiceBank), 1, pFile) == 1
&& m_pVoiceBank[nBank]->StatusStart == 0xF0
&& m_pVoiceBank[nBank]->CompanyID == 0x43
&& m_pVoiceBank[nBank]->Format == 0x09
&& m_pVoiceBank[nBank]->StatusEnd == 0xF7)
if (m_nBanksLoaded % 100 == 0)
{
LOGDBG ("Bank #%u successfully loaded", nBank);
LOGDBG ("Banks successfully loaded #%u", m_nBanksLoaded);
}
//LOGDBG ("Bank #%u successfully loaded", nBank);
m_BankFileName[nBank] = pEntry->d_name;
m_nNumLoadedBanks++;
m_BankFileName[nBankIdx] = sBankName;
if (nBank > m_nNumHighestBank)
{
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank;
}
else
m_nBanksLoaded++;
bBankLoaded = true;
}
else if (bHeaderlessSysExVoices)
{
// Config says to accept headerless SysEx Voice Banks
// so reset file pointer and try again.
fseek (pFile, 0, SEEK_SET);
if (fread (m_pVoiceBank[nBankIdx]->Voice, VoiceSysExSize, 1, pFile) == 1)
{
LOGWARN ("%s: Invalid size or format", Filename.c_str ());
delete m_pVoiceBank[nBank];
m_pVoiceBank[nBank] = nullptr;
if (m_nBanksLoaded % 100 == 0)
{
LOGDBG ("Banks successfully loaded #%u", m_nBanksLoaded);
}
//LOGDBG ("Bank #%u successfully loaded (headerless)", nBank);
// Add in the missing header items.
// Naturally it isn't possible to validate these!
m_pVoiceBank[nBankIdx]->StatusStart = 0xF0;
m_pVoiceBank[nBankIdx]->CompanyID = 0x43;
m_pVoiceBank[nBankIdx]->Format = 0x09;
m_pVoiceBank[nBankIdx]->ByteCountMS = 0x20;
m_pVoiceBank[nBankIdx]->ByteCountLS = 0x00;
m_pVoiceBank[nBankIdx]->Checksum = 0x00;
m_pVoiceBank[nBankIdx]->StatusEnd = 0xF7;
m_BankFileName[nBankIdx] = sBankName;
if (nBank > m_nNumHighestBank)
{
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank;
}
bBankLoaded = true;
m_nBanksLoaded++;
}
fclose (pFile);
}
else
if (!bBankLoaded)
{
delete m_pVoiceBank[nBank];
m_pVoiceBank[nBank] = nullptr;
LOGWARN ("%s: Invalid size or format", Filename.c_str ());
delete m_pVoiceBank[nBankIdx];
m_pVoiceBank[nBankIdx] = nullptr;
}
}
closedir (pDirectory);
fclose (pFile);
}
else
{
delete m_pVoiceBank[nBankIdx];
m_pVoiceBank[nBankIdx] = nullptr;
}
}
std::string CSysExFileLoader::GetBankName (unsigned nBankID)
@ -188,9 +273,71 @@ std::string CSysExFileLoader::GetBankName (unsigned nBankID)
return "NO NAME";
}
unsigned CSysExFileLoader::GetNumLoadedBanks (void)
unsigned CSysExFileLoader::GetNextBankUp (unsigned nBankID)
{
// Find the next loaded bank "up" from the provided bank ID
for (unsigned id=nBankID+1; id <= m_nNumHighestBank; id++)
{
if (IsValidBank(id))
{
return id;
}
}
// Handle wrap-around
for (unsigned id=0; id<nBankID; id++)
{
if (IsValidBank(id))
{
return id;
}
}
// If we get here there are no other banks!
return nBankID;
}
unsigned CSysExFileLoader::GetNextBankDown (unsigned nBankID)
{
// Find the next loaded bank "down" from the provided bank ID
for (int id=((int)nBankID)-1; id >= 0; id--)
{
if (IsValidBank((unsigned)id))
{
return id;
}
}
// Handle wrap-around
for (unsigned id=m_nNumHighestBank; id>nBankID; id--)
{
if (IsValidBank(id))
{
return id;
}
}
// If we get here there are no other banks!
return nBankID;
}
bool CSysExFileLoader::IsValidBank (unsigned nBankID)
{
if (m_pVoiceBank[nBankID])
{
// Use a valid "status start/end" as an indicator of a valid loaded bank
if ((m_pVoiceBank[nBankID]->StatusStart == 0xF0) &&
(m_pVoiceBank[nBankID]->StatusEnd == 0xF7))
{
return true;
}
}
return false;
}
unsigned CSysExFileLoader::GetNumHighestBank (void)
{
return m_nNumLoadedBanks;
return m_nNumHighestBank;
}
void CSysExFileLoader::GetVoice (unsigned nBankID, unsigned nVoiceID, uint8_t *pVoiceData)
@ -198,7 +345,7 @@ void CSysExFileLoader::GetVoice (unsigned nBankID, unsigned nVoiceID, uint8_t *p
if ( nBankID <= MaxVoiceBankID
&& nVoiceID <= VoicesPerBank)
{
if (m_pVoiceBank[nBankID])
if (IsValidBank(nBankID))
{
DecodePackedVoice (m_pVoiceBank[nBankID]->Voice[nVoiceID], pVoiceData);

@ -29,10 +29,13 @@
class CSysExFileLoader // Loader for DX7 .syx files
{
public:
static const unsigned MaxVoiceBankID = 16383;
static const unsigned MaxVoiceBankID = 16383; // i.e. 14-bit MSB/LSB value between 0 and 16383
static const unsigned VoicesPerBank = 32;
static const size_t SizePackedVoice = 128;
static const size_t SizeSingleVoice = 156;
static const unsigned VoiceSysExHdrSize = 8; // Additional (optional) Header/Footer bytes for bank of 32 voices
static const unsigned VoiceSysExSize = 4096; // Bank of 32 voices as per DX7 MIDI Spec
static const unsigned MaxSubDirs = 3; // Number of nested subdirectories supported.
struct TVoiceBank
{
@ -54,12 +57,15 @@ public:
CSysExFileLoader (const char *pDirName = "/sysex");
~CSysExFileLoader (void);
void Load (void);
void Load (bool bHeaderlessSysExVoices = false);
std::string GetBankName (unsigned nBankID); // 0 .. 127
unsigned GetNumLoadedBanks (); // 0 .. MaxVoiceBankID
std::string GetBankName (unsigned nBankID); // 0 .. MaxVoiceBankID
unsigned GetNumHighestBank (); // 0 .. MaxVoiceBankID
bool IsValidBank (unsigned nBankID);
unsigned GetNextBankUp (unsigned nBankID);
unsigned GetNextBankDown (unsigned nBankID);
void GetVoice (unsigned nBankID, // 0 .. 127
void GetVoice (unsigned nBankID, // 0 .. MaxVoiceBankID
unsigned nVoiceID, // 0 .. 31
uint8_t *pVoiceData); // returns unpacked format (156 bytes)
@ -69,12 +75,15 @@ private:
private:
std::string m_DirName;
unsigned m_nNumLoadedBanks;
unsigned m_nNumHighestBank;
unsigned m_nBanksLoaded;
TVoiceBank *m_pVoiceBank[MaxVoiceBankID+1];
std::string m_BankFileName[MaxVoiceBankID+1];
static uint8_t s_DefaultVoice[SizeSingleVoice];
void LoadBank (const char * sDirName, const char * sBankName, bool bHeaderlessSysExVoices, unsigned nSubDirCount);
};
#endif

@ -219,6 +219,8 @@ const CUIMenu::TParameter CUIMenu::s_GlobalParameter[CMiniDexed::ParameterUnknow
const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown] =
{
{0, CSysExFileLoader::MaxVoiceBankID, 1}, // TGParameterVoiceBank
{0, 0, 0}, // TGParameterVoiceBankMSB (not used in menus)
{0, 0, 0}, // TGParameterVoiceBankLSB (not used in menus)
{0, CSysExFileLoader::VoicesPerBank-1, 1}, // TGParameterProgram
{0, 127, 8, ToVolume}, // TGParameterVolume
{0, 127, 8, ToPan}, // TGParameterPan
@ -249,7 +251,6 @@ const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown]
{0, 1, 1, ToOnOff}, //AT Pitch
{0, 1, 1, ToOnOff}, //AT Amp
{0, 1, 1, ToOnOff} //AT EGBias
};
// must match DexedVoiceParameters in Synth_Dexed
@ -486,7 +487,6 @@ void CUIMenu::EditGlobalParameter (CUIMenu *pUIMenu, TMenuEvent Event)
void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
{
unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-1];
int nLoadedBanks = pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetNumLoadedBanks();
int nValue = pUIMenu->m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterVoiceBank, nTG);
@ -496,19 +496,13 @@ void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
break;
case MenuEventStepDown:
if (--nValue < 0)
{
nValue = 0;
}
nValue = pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetNextBankDown(nValue);
pUIMenu->m_pMiniDexed->SetTGParameter (
CMiniDexed::TGParameterVoiceBank, nValue, nTG);
break;
case MenuEventStepUp:
if (++nValue > (int) nLoadedBanks-1)
{
nValue = nLoadedBanks-1;
}
nValue = pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetNextBankUp(nValue);
pUIMenu->m_pMiniDexed->SetTGParameter (
CMiniDexed::TGParameterVoiceBank, nValue, nTG);
break;
@ -537,7 +531,7 @@ void CUIMenu::EditVoiceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event)
void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
{
unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-1];
int nLoadedBanks = pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetNumLoadedBanks();
int nHighestBank = pUIMenu->m_pMiniDexed->GetSysExFileLoader ()->GetNumHighestBank();
int nValue = pUIMenu->m_pMiniDexed->GetTGParameter (CMiniDexed::TGParameterProgram, nTG);
@ -555,7 +549,7 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
if (--nVB < 0)
{
// Wrap around to last loaded bank
nVB = nLoadedBanks-1;
nVB = nHighestBank;
}
pUIMenu->m_pMiniDexed->SetTGParameter (CMiniDexed::TGParameterVoiceBank, nVB, nTG);
}
@ -568,7 +562,7 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
// Switch up a voice bank and reset to voice 0
nValue = 0;
int nVB = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterVoiceBank, nTG);
if (++nVB > (int) nLoadedBanks-1)
if (++nVB > (int) nHighestBank)
{
// Wrap around to first bank
nVB = 0;
@ -587,15 +581,29 @@ void CUIMenu::EditProgramNumber (CUIMenu *pUIMenu, TMenuEvent Event)
return;
}
string TG ("TG");
TG += to_string (nTG+1);
string voiceName = pUIMenu->m_pMiniDexed->GetVoiceName (nTG); // Skip empty voices
if (voiceName == "EMPTY "
|| voiceName == " "
|| voiceName == "----------"
|| voiceName == "~~~~~~~~~~" )
{
if (Event == MenuEventStepUp) {
CUIMenu::EditProgramNumber (pUIMenu, MenuEventStepUp);
}
if (Event == MenuEventStepDown) {
CUIMenu::EditProgramNumber (pUIMenu, MenuEventStepDown);
}
} else {
string TG ("TG");
TG += to_string (nTG+1);
string Value = to_string (nValue+1) + "=" + pUIMenu->m_pMiniDexed->GetVoiceName (nTG);
string Value = to_string (nValue+1) + "=" + pUIMenu->m_pMiniDexed->GetVoiceName (nTG);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1);
pUIMenu->m_pUI->DisplayWrite (TG.c_str (),
pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name,
Value.c_str (),
nValue > 0, nValue < (int) CSysExFileLoader::VoicesPerBank-1);
}
}
void CUIMenu::EditTGParameter (CUIMenu *pUIMenu, TMenuEvent Event)
@ -1474,8 +1482,6 @@ void CUIMenu::EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event)
unsigned nController = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-1];
unsigned nParameter = pUIMenu->m_nCurrentParameter + nController;
CMiniDexed::TTGParameter Param = (CMiniDexed::TTGParameter) nParameter;
const TParameter &rParam = s_TGParameter[Param];

@ -0,0 +1,13 @@
#!/bin/bash
set -ex
git submodule update --init --recursive
cd circle-stdlib/
git checkout e318f89 # Needed to support Circle develop?
cd -
cd circle-stdlib/libs/circle
git checkout ec09d7e # develop
cd -
cd circle-stdlib/libs/circle-newlib
git checkout 48bf91d # needed for circle ec09d7e
cd -
Loading…
Cancel
Save