From a02515360d28df8605333c6a8f05f7051ac8e399 Mon Sep 17 00:00:00 2001 From: Kevin <68612569+diyelectromusic@users.noreply.github.com> Date: Sat, 9 Dec 2023 11:03:03 -0800 Subject: [PATCH] Start of subdirectory implementation for performance banks. --- src/mididevice.cpp | 24 +++++++- src/minidexed.cpp | 34 +++++++++++ src/minidexed.h | 5 ++ src/performanceconfig.cpp | 121 ++++++++++++++++++++++++++++++++++++++ src/performanceconfig.h | 9 +++ 5 files changed, 192 insertions(+), 1 deletion(-) diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 5f231d63..b5959bff 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -184,9 +184,31 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign else { // Perform any MiniDexed level MIDI handling before specific Tone Generators + unsigned nPerfCh = m_pSynthesizer->GetPerformanceSelectChannel(); switch (ucType) { case MIDI_CONTROL_CHANGE: + // Check for performance PC messages + if (nPerfCh != Disabled) + { + if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode)) + { + if (pMessage[1] == MIDI_CC_BANK_SELECT_MSB) + { + m_pSynthesizer->BankSelectMSBPerformance (pMessage[2]); + } + else if (pMessage[1] == MIDI_CC_BANK_SELECT_LSB) + { + m_pSynthesizer->BankSelectLSBPerformance (pMessage[2]); + } + else + { + // Ignore any other CC messages at this time + } + } + } + break; + case MIDI_NOTE_OFF: case MIDI_NOTE_ON: if (nLength < 3) @@ -195,11 +217,11 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign } m_pUI->UIMIDICmdHandler (ucChannel, ucStatus & 0xF0, pMessage[1], pMessage[2]); break; + case MIDI_PROGRAM_CHANGE: // Check for performance PC messages if( m_pConfig->GetMIDIRXProgramChange() ) { - unsigned nPerfCh = m_pSynthesizer->GetPerformanceSelectChannel(); if( nPerfCh != Disabled) { if ((ucChannel == nPerfCh) || (nPerfCh == OmniMode)) diff --git a/src/minidexed.cpp b/src/minidexed.cpp index b11f8b44..e9c4dbc9 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -407,6 +407,22 @@ void CMiniDexed::BankSelect (unsigned nBank, unsigned nTG) } } +void CMiniDexed::BankSelectPerformance (unsigned nBank) +{ + nBank=constrain((int)nBank,0,16383); + + if (m_nParameter[ParameterPerformanceSelectChannel] != CMIDIDevice::Disabled) + { + // if (GetSysExFileLoader ()->IsValidBank(nBank)) + { + // Only change if we have the bank loaded + m_nVoiceBankIDPerformance = nBank; + + m_UI.ParameterChanged (); + } + } +} + void CMiniDexed::BankSelectMSB (unsigned nBankMSB, unsigned nTG) { nBankMSB=constrain((int)nBankMSB,0,127); @@ -422,6 +438,12 @@ void CMiniDexed::BankSelectMSB (unsigned nBankMSB, unsigned nTG) m_nVoiceBankIDMSB[nTG] = nBankMSB; } +void CMiniDexed::BankSelectMSBPerformance (unsigned nBankMSB) +{ + nBankMSB=constrain((int)nBankMSB,0,127); + m_nVoiceBankIDMSBPerformance = nBankMSB; +} + void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG) { nBankLSB=constrain((int)nBankLSB,0,127); @@ -435,6 +457,18 @@ void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG) BankSelect(nBank, nTG); } +void CMiniDexed::BankSelectLSBPerformance (unsigned nBankLSB) +{ + nBankLSB=constrain((int)nBankLSB,0,127); + + unsigned nBank = m_nVoiceBankIDPerformance; + unsigned nBankMSB = m_nVoiceBankIDMSBPerformance; + nBank = (nBankMSB << 7) + nBankLSB; + + // Now should have both MSB and LSB so enable the BankSelect + BankSelectPerformance(nBank); +} + void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) { assert (m_pConfig); diff --git a/src/minidexed.h b/src/minidexed.h index d56c228d..c2852632 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -64,8 +64,11 @@ class CMiniDexed CSysExFileLoader *GetSysExFileLoader (void); void BankSelect (unsigned nBank, unsigned nTG); + void BankSelectPerformance (unsigned nBank); void BankSelectMSB (unsigned nBankMSB, unsigned nTG); + void BankSelectMSBPerformance (unsigned nBankMSB); void BankSelectLSB (unsigned nBankLSB, unsigned nTG); + void BankSelectLSBPerformance (unsigned nBankLSB); void ProgramChange (unsigned nProgram, unsigned nTG); void ProgramChangePerformance (unsigned nProgram); void SetVolume (unsigned nVolume, unsigned nTG); @@ -239,6 +242,8 @@ class CMiniDexed unsigned m_nVoiceBankID[CConfig::ToneGenerators]; unsigned m_nVoiceBankIDMSB[CConfig::ToneGenerators]; + unsigned m_nVoiceBankIDPerformance; + unsigned m_nVoiceBankIDMSBPerformance; unsigned m_nProgram[CConfig::ToneGenerators]; unsigned m_nVolume[CConfig::ToneGenerators]; unsigned m_nPan[CConfig::ToneGenerators]; diff --git a/src/performanceconfig.cpp b/src/performanceconfig.cpp index 1382f34f..2f36b096 100644 --- a/src/performanceconfig.cpp +++ b/src/performanceconfig.cpp @@ -949,6 +949,8 @@ bool CPerformanceConfig::ListPerformances() LOGNOTE ("Last Performance: %d", nLastPerformance + 1); // Show "user facing" index + ListPerformanceBanks(); + return nInternalFolderOk; } @@ -1013,3 +1015,122 @@ bool CPerformanceConfig::DeletePerformance(unsigned nID) } return bOK; } + +bool CPerformanceConfig::ListPerformanceBanks() +{ + // Open performance directory + DIR Directory; + FILINFO FileInfo; + FRESULT Result; + Result = f_opendir (&Directory, "SD:/" PERFORMANCE_DIR); + if (Result != FR_OK) + { + // No performance directory, so no performance banks. + // So nothing else to do here + return false; + } + + LOGNOTE ("Performance Directory Found"); + + unsigned nNumBanks = 0; + unsigned nHighestBank = 0; + + // List directories with names in format 01_Perf Bank Name + Result = f_findfirst (&Directory, &FileInfo, "SD:/" PERFORMANCE_DIR, "*"); + for (unsigned i = 0; Result == FR_OK && FileInfo.fname[0]; i++) + { + // Check to see if it is a directory + if ((FileInfo.fattrib & AM_DIR) != 0) + { + // Looking for Performance banks of the form: 01_Perf Bank Name + // So positions 0,1 = decimal digit + // position 2 = "_" + // positions 3.. = actual name + // + std::string OriFileName = FileInfo.fname; + size_t nLen = OriFileName.length(); + if ( nLen > 3 && nLen <26 && strcmp(OriFileName.substr(2,1).c_str(), "_")==0) + { + unsigned nBankIndex = stoi(OriFileName.substr(0,2)); + // Recall user index numbered 01..NUM_PERFORMANCE_BANKS + if ((nBankIndex > 0) && (nBankIndex <= NUM_PERFORMANCE_BANKS)) + { + // Convert from "user facing" 1..indexed number to internal 0..indexed + nBankIndex = nBankIndex-1; + if (m_nPerformanceBankName[nBankIndex].empty()) + { + std::string BankName = OriFileName.substr(3,nLen); + + m_nPerformanceBankName[nBankIndex] = BankName; + //LOGNOTE ("Found performance bank %s (%d, %s)", OriFileName.c_str(), nBankIndex, BankName.c_str()); + nNumBanks++; + if (nBankIndex > nHighestBank) + { + nHighestBank = nBankIndex; + } + } + else + { + LOGNOTE ("Duplicate Performance Bank: %s", FileInfo.fname); + } + } + else + { + LOGNOTE ("Performance Bank number out of range: %s", FileInfo.fname); + } + } + else + { + //LOGNOTE ("Skipping: %s", FileInfo.fname); + } + } + + Result = f_findnext (&Directory, &FileInfo); + } + + if (nNumBanks > 0) + { + LOGNOTE ("Number of Performance Banks: %d (last = %d)", nNumBanks, nHighestBank+1); + } + return true; +} + +void CPerformanceConfig::SetPerformanceBank(unsigned nBankID) +{ + assert (nBankID < NUM_PERFORMANCE_BANKS); + if (IsValidPerformanceBank(nBankID)) + { + // Construct performance bank directory name + // Change directory + // Reload performances from that directory + nPerformanceBank = nBankID; + } +} + +unsigned CPerformanceConfig::GetPerformanceBank(void) +{ + return nPerformanceBank; +} + +std::string CPerformanceConfig::GetPerformanceBankName(unsigned nBankID) +{ + assert (nBankID < NUM_PERFORMANCE_BANKS); + if (IsValidPerformanceBank(nBankID)) + { + return m_nPerformanceBankName[nBankID]; + } + else + { + return "Default"; + } +} + +bool CPerformanceConfig::IsValidPerformanceBank(unsigned nBankID) +{ + assert (nBankID < NUM_PERFORMANCE_BANKS); + if (m_nPerformanceBankName[nBankID].empty()) + { + return false; + } + return true; +} diff --git a/src/performanceconfig.h b/src/performanceconfig.h index 1815e7c4..77e508e1 100644 --- a/src/performanceconfig.h +++ b/src/performanceconfig.h @@ -29,6 +29,7 @@ #define NUM_VOICE_PARAM 156 #define PERFORMANCE_DIR "performance" #define NUM_PERFORMANCES 256 +#define NUM_PERFORMANCE_BANKS 8 class CPerformanceConfig // Performance configuration { @@ -136,6 +137,12 @@ class CPerformanceConfig // Performance configuration bool CheckFreePerformanceSlot(void); bool IsValidPerformance(unsigned nID); + bool ListPerformanceBanks(void); + void SetPerformanceBank(unsigned nBankID); + unsigned GetPerformanceBank(void); + std::string GetPerformanceBankName(unsigned nBankID); + bool IsValidPerformanceBank(unsigned nBankID); + private: CPropertiesFatFsFile m_Properties; @@ -170,8 +177,10 @@ class CPerformanceConfig // Performance configuration unsigned nLastPerformance; unsigned nActualPerformance = 0; + unsigned nPerformanceBank; //unsigned nMenuSelectedPerformance = 0; std::string m_nPerformanceFileName[NUM_PERFORMANCES]; + std::string m_nPerformanceBankName[NUM_PERFORMANCE_BANKS]; FATFS *m_pFileSystem; bool nInternalFolderOk=false;