Support for headerless SysEx Voice Banks (#463)

* Fix for Issue #457 - changed m_nNumLoadedBanks to be m_nNumHighestBank and updated functionality in menus accordingly.

* Fix for Issue #460 implements MIDI Bank Select MSB/LSB based on PR #395 submitted by @abscisys

* Fix for Issue #458 to not show blank banks in the menus.  Also handles MIDI bank select messages and won't change banks if the final selected bank isn't loaded.

* Firm up bank validity handling slightly.

* Fix for Issue #459 Initial support for loading of headerless SysEx voice banks as a configuraton option

* Fix for Issue #459 Added config option for headerless SysEx voice banks.
pull/469/head
Kevin 2 years ago committed by GitHub
parent 73a80a93cb
commit cfd2a24804
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/config.cpp
  2. 2
      src/config.h
  3. 2
      src/minidexed.cpp
  4. 1
      src/minidexed.ini
  5. 38
      src/sysexfileloader.cpp
  6. 4
      src/sysexfileloader.h

@ -71,6 +71,7 @@ void CConfig::Load (void)
m_bMIDIRXProgramChange = m_Properties.GetNumber ("MIDIRXProgramChange", 1) != 0; m_bMIDIRXProgramChange = m_Properties.GetNumber ("MIDIRXProgramChange", 1) != 0;
m_bIgnoreAllNotesOff = m_Properties.GetNumber ("IgnoreAllNotesOff", 0) != 0; m_bIgnoreAllNotesOff = m_Properties.GetNumber ("IgnoreAllNotesOff", 0) != 0;
m_bMIDIAutoVoiceDumpOnPC = m_Properties.GetNumber ("MIDIAutoVoiceDumpOnPC", 1) != 0; m_bMIDIAutoVoiceDumpOnPC = m_Properties.GetNumber ("MIDIAutoVoiceDumpOnPC", 1) != 0;
m_bHeaderlessSysExVoices = m_Properties.GetNumber ("HeaderlessSysExVoices", 0) != 0;
m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0; m_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0;
m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4); m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4);
@ -179,6 +180,11 @@ bool CConfig::GetMIDIAutoVoiceDumpOnPC (void) const
return m_bMIDIAutoVoiceDumpOnPC; return m_bMIDIAutoVoiceDumpOnPC;
} }
bool CConfig::GetHeaderlessSysExVoices (void) const
{
return m_bHeaderlessSysExVoices;
}
bool CConfig::GetLCDEnabled (void) const bool CConfig::GetLCDEnabled (void) const
{ {
return m_bLCDEnabled; return m_bLCDEnabled;

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

@ -170,7 +170,7 @@ bool CMiniDexed::Initialize (void)
return false; return false;
} }
m_SysExFileLoader.Load (); m_SysExFileLoader.Load (m_pConfig->GetHeaderlessSysExVoices ());
if (m_SerialMIDI.Initialize ()) if (m_SerialMIDI.Initialize ())
{ {

@ -17,6 +17,7 @@ MIDIBaudRate=31250
MIDIRXProgramChange=1 MIDIRXProgramChange=1
IgnoreAllNotesOff=0 IgnoreAllNotesOff=0
MIDIAutoVoiceDumpOnPC=1 MIDIAutoVoiceDumpOnPC=1
HeaderlessSysExVoices=0
# HD44780 LCD # HD44780 LCD
LCDEnabled=1 LCDEnabled=1

@ -81,7 +81,7 @@ CSysExFileLoader::~CSysExFileLoader (void)
} }
} }
void CSysExFileLoader::Load (void) void CSysExFileLoader::Load (bool bHeaderlessSysExVoices)
{ {
m_nNumHighestBank = 0; m_nNumHighestBank = 0;
@ -124,6 +124,7 @@ void CSysExFileLoader::Load (void)
m_pVoiceBank[nBank] = new TVoiceBank; m_pVoiceBank[nBank] = new TVoiceBank;
assert (m_pVoiceBank[nBank]); assert (m_pVoiceBank[nBank]);
assert (sizeof(TVoiceBank) == VoiceSysExHdrSize + VoiceSysExSize);
std::string Filename (m_DirName); std::string Filename (m_DirName);
Filename += "/"; Filename += "/";
@ -132,7 +133,8 @@ void CSysExFileLoader::Load (void)
FILE *pFile = fopen (Filename.c_str (), "rb"); FILE *pFile = fopen (Filename.c_str (), "rb");
if (pFile) if (pFile)
{ {
if ( fread (m_pVoiceBank[nBank], sizeof (TVoiceBank), 1, pFile) == 1 bool bBankLoaded = false;
if ( fread (m_pVoiceBank[nBank], VoiceSysExHdrSize+VoiceSysExSize, 1, pFile) == 1
&& m_pVoiceBank[nBank]->StatusStart == 0xF0 && m_pVoiceBank[nBank]->StatusStart == 0xF0
&& m_pVoiceBank[nBank]->CompanyID == 0x43 && m_pVoiceBank[nBank]->CompanyID == 0x43
&& m_pVoiceBank[nBank]->Format == 0x09 && m_pVoiceBank[nBank]->Format == 0x09
@ -146,8 +148,38 @@ void CSysExFileLoader::Load (void)
// This is the bank ID of the highest loaded bank // This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank; m_nNumHighestBank = nBank;
} }
bBankLoaded = true;
} }
else 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[nBank]->Voice, VoiceSysExSize, 1, pFile) == 1)
{
LOGDBG ("Bank #%u successfully loaded (headerless)", nBank);
// Add in the missing header items.
// Naturally it isn't possible to validate these!
m_pVoiceBank[nBank]->StatusStart = 0xF0;
m_pVoiceBank[nBank]->CompanyID = 0x43;
m_pVoiceBank[nBank]->Format = 0x09;
m_pVoiceBank[nBank]->ByteCountMS = 0x20;
m_pVoiceBank[nBank]->ByteCountLS = 0x00;
m_pVoiceBank[nBank]->Checksum = 0x00;
m_pVoiceBank[nBank]->StatusEnd = 0xF7;
m_BankFileName[nBank] = pEntry->d_name;
if (nBank > m_nNumHighestBank)
{
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank;
}
bBankLoaded = true;
}
}
if (!bBankLoaded)
{ {
LOGWARN ("%s: Invalid size or format", Filename.c_str ()); LOGWARN ("%s: Invalid size or format", Filename.c_str ());

@ -33,6 +33,8 @@ public:
static const unsigned VoicesPerBank = 32; static const unsigned VoicesPerBank = 32;
static const size_t SizePackedVoice = 128; static const size_t SizePackedVoice = 128;
static const size_t SizeSingleVoice = 156; 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
struct TVoiceBank struct TVoiceBank
{ {
@ -54,7 +56,7 @@ public:
CSysExFileLoader (const char *pDirName = "/sysex"); CSysExFileLoader (const char *pDirName = "/sysex");
~CSysExFileLoader (void); ~CSysExFileLoader (void);
void Load (void); void Load (bool bHeaderlessSysExVoices = false);
std::string GetBankName (unsigned nBankID); // 0 .. MaxVoiceBankID std::string GetBankName (unsigned nBankID); // 0 .. MaxVoiceBankID
unsigned GetNumHighestBank (); // 0 .. MaxVoiceBankID unsigned GetNumHighestBank (); // 0 .. MaxVoiceBankID

Loading…
Cancel
Save