diff --git a/src/config.cpp b/src/config.cpp index b5279a8..44ac32f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -71,6 +71,7 @@ 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_bLCDEnabled = m_Properties.GetNumber ("LCDEnabled", 0) != 0; m_nLCDPinEnable = m_Properties.GetNumber ("LCDPinEnable", 4); @@ -179,6 +180,11 @@ bool CConfig::GetMIDIAutoVoiceDumpOnPC (void) const return m_bMIDIAutoVoiceDumpOnPC; } +bool CConfig::GetHeaderlessSysExVoices (void) const +{ + return m_bHeaderlessSysExVoices; +} + bool CConfig::GetLCDEnabled (void) const { return m_bLCDEnabled; diff --git a/src/config.h b/src/config.h index 8a34239..bc5e7c6 100644 --- a/src/config.h +++ b/src/config.h @@ -77,6 +77,7 @@ 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 // HD44780 LCD // GPIO pin numbers are chip numbers, not header positions @@ -157,6 +158,7 @@ private: bool m_bMIDIRXProgramChange; bool m_bIgnoreAllNotesOff; bool m_bMIDIAutoVoiceDumpOnPC; + bool m_bHeaderlessSysExVoices; bool m_bLCDEnabled; unsigned m_nLCDPinEnable; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 66c6151..6acda43 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -170,7 +170,7 @@ bool CMiniDexed::Initialize (void) return false; } - m_SysExFileLoader.Load (); + m_SysExFileLoader.Load (m_pConfig->GetHeaderlessSysExVoices ()); if (m_SerialMIDI.Initialize ()) { diff --git a/src/minidexed.ini b/src/minidexed.ini index bb3edd7..2f5ce5b 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -17,6 +17,7 @@ MIDIBaudRate=31250 MIDIRXProgramChange=1 IgnoreAllNotesOff=0 MIDIAutoVoiceDumpOnPC=1 +HeaderlessSysExVoices=0 # HD44780 LCD LCDEnabled=1 diff --git a/src/sysexfileloader.cpp b/src/sysexfileloader.cpp index d5159eb..4eee065 100644 --- a/src/sysexfileloader.cpp +++ b/src/sysexfileloader.cpp @@ -81,7 +81,7 @@ CSysExFileLoader::~CSysExFileLoader (void) } } -void CSysExFileLoader::Load (void) +void CSysExFileLoader::Load (bool bHeaderlessSysExVoices) { m_nNumHighestBank = 0; @@ -124,6 +124,7 @@ void CSysExFileLoader::Load (void) m_pVoiceBank[nBank] = new TVoiceBank; assert (m_pVoiceBank[nBank]); + assert (sizeof(TVoiceBank) == VoiceSysExHdrSize + VoiceSysExSize); std::string Filename (m_DirName); Filename += "/"; @@ -132,7 +133,8 @@ void CSysExFileLoader::Load (void) FILE *pFile = fopen (Filename.c_str (), "rb"); 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]->CompanyID == 0x43 && m_pVoiceBank[nBank]->Format == 0x09 @@ -146,8 +148,38 @@ void CSysExFileLoader::Load (void) // This is the bank ID of the highest loaded bank 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 ()); diff --git a/src/sysexfileloader.h b/src/sysexfileloader.h index 3c20d0f..d3821da 100644 --- a/src/sysexfileloader.h +++ b/src/sysexfileloader.h @@ -33,6 +33,8 @@ public: 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 struct TVoiceBank { @@ -54,7 +56,7 @@ public: CSysExFileLoader (const char *pDirName = "/sysex"); ~CSysExFileLoader (void); - void Load (void); + void Load (bool bHeaderlessSysExVoices = false); std::string GetBankName (unsigned nBankID); // 0 .. MaxVoiceBankID unsigned GetNumHighestBank (); // 0 .. MaxVoiceBankID