From ff69fdc3956b7bef251bb362fa547bfe7929db06 Mon Sep 17 00:00:00 2001 From: Rene Stange Date: Fri, 18 Mar 2022 23:42:22 +0100 Subject: [PATCH] Support TG select in UI * Active TG number is shown on LCD display * Next TG is selected by double click * MIDI receive and PC keyboard are still in omni mode --- src/mididevice.cpp | 47 +++++++++++++++---- src/minidexed.cpp | 106 ++++++++++++++++++------------------------ src/minidexed.h | 20 ++++---- src/pckeyboard.cpp | 11 ++++- src/userinterface.cpp | 70 +++++++++++++++++++--------- src/userinterface.h | 13 +++--- 6 files changed, 156 insertions(+), 111 deletions(-) diff --git a/src/mididevice.cpp b/src/mididevice.cpp index d5559dd..5d2ebc4 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -107,12 +107,18 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign { if (ucVelocity <= 127) { - m_pSynthesizer->keydown (ucKeyNumber, ucVelocity); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->keydown (ucKeyNumber, ucVelocity, nTG); + } } } else { - m_pSynthesizer->keyup (ucKeyNumber); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->keyup (ucKeyNumber, nTG); + } } break; @@ -122,7 +128,10 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign break; } - m_pSynthesizer->keyup (ucKeyNumber); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->keyup (ucKeyNumber, nTG); + } break; case MIDI_CONTROL_CHANGE: @@ -134,26 +143,41 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign switch (pMessage[1]) { case MIDI_CC_MODULATION: - m_pSynthesizer->setModWheel (pMessage[2]); - m_pSynthesizer->ControllersRefresh (); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->setModWheel (pMessage[2], nTG); + m_pSynthesizer->ControllersRefresh (nTG); + } break; case MIDI_CC_VOLUME: - m_pSynthesizer->SetVolume (pMessage[2]); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->SetVolume (pMessage[2], nTG); + } break; case MIDI_CC_BANK_SELECT_LSB: - m_pSynthesizer->BankSelectLSB (pMessage[2]); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->BankSelectLSB (pMessage[2], nTG); + } break; case MIDI_CC_BANK_SUSTAIN: - m_pSynthesizer->setSustain (pMessage[2] >= 64); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->setSustain (pMessage[2] >= 64, nTG); + } break; } break; case MIDI_PROGRAM_CHANGE: - m_pSynthesizer->ProgramChange (pMessage[1]); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->ProgramChange (pMessage[1], nTG); + } break; case MIDI_PITCH_BEND: { @@ -166,7 +190,10 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign nValue |= (s16) pMessage[2] << 7; nValue -= 0x2000; - m_pSynthesizer->setPitchbend (nValue); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_pSynthesizer->setPitchbend (nValue, nTG); + } } break; default: diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 9ab5416..c3e0273 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -115,13 +115,13 @@ bool CMiniDexed::Initialize (void) m_bUseSerial = true; } - SetVolume (100); - ProgramChange (0); - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) { assert (m_pTG[i]); + SetVolume (100, i); + ProgramChange (0, i); + m_pTG[i]->setTranspose (24); m_pTG[i]->setPBController (12, 1); @@ -245,114 +245,98 @@ CSysExFileLoader *CMiniDexed::GetSysExFileLoader (void) return &m_SysExFileLoader; } -void CMiniDexed::BankSelectLSB (unsigned nBankLSB) +void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG) { if (nBankLSB > 127) { return; } - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - m_nVoiceBankID[i] = nBankLSB; - } + assert (nTG < CConfig::ToneGenerators); + m_nVoiceBankID[nTG] = nBankLSB; - m_UI.BankSelected (nBankLSB); + m_UI.BankSelected (nBankLSB, nTG); } -void CMiniDexed::ProgramChange (unsigned nProgram) +void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) { if (nProgram > 31) { return; } - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - uint8_t Buffer[156]; - m_SysExFileLoader.GetVoice (m_nVoiceBankID[i], nProgram, Buffer); + assert (nTG < CConfig::ToneGenerators); + uint8_t Buffer[156]; + m_SysExFileLoader.GetVoice (m_nVoiceBankID[nTG], nProgram, Buffer); - assert (m_pTG[i]); - m_pTG[i]->loadVoiceParameters (Buffer); - } + assert (m_pTG[nTG]); + m_pTG[nTG]->loadVoiceParameters (Buffer); - m_UI.ProgramChanged (nProgram); + m_UI.ProgramChanged (nProgram, nTG); } -void CMiniDexed::SetVolume (unsigned nVolume) +void CMiniDexed::SetVolume (unsigned nVolume, unsigned nTG) { if (nVolume > 127) { return; } - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->setGain (nVolume / 127.0); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setGain (nVolume / 127.0); - m_UI.VolumeChanged (nVolume); + m_UI.VolumeChanged (nVolume, nTG); } -void CMiniDexed::keyup (int16_t pitch) +void CMiniDexed::keyup (int16_t pitch, unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->keyup (pitch); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->keyup (pitch); } -void CMiniDexed::keydown (int16_t pitch, uint8_t velocity) +void CMiniDexed::keydown (int16_t pitch, uint8_t velocity, unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->keydown (pitch, velocity); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->keydown (pitch, velocity); } -void CMiniDexed::setSustain(bool sustain) +void CMiniDexed::setSustain(bool sustain, unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->setSustain (sustain); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setSustain (sustain); } -void CMiniDexed::setModWheel (uint8_t value) +void CMiniDexed::setModWheel (uint8_t value, unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->setModWheel (value); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setModWheel (value); } -void CMiniDexed::setPitchbend (int16_t value) +void CMiniDexed::setPitchbend (int16_t value, unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->setPitchbend (value); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setPitchbend (value); } -void CMiniDexed::ControllersRefresh (void) +void CMiniDexed::ControllersRefresh (unsigned nTG) { - for (unsigned i = 0; i < CConfig::ToneGenerators; i++) - { - assert (m_pTG[i]); - m_pTG[i]->ControllersRefresh (); - } + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->ControllersRefresh (); } std::string CMiniDexed::GetVoiceName (unsigned nTG) { char VoiceName[11]; memset (VoiceName, 0, sizeof VoiceName); + + assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); m_pTG[nTG]->setName (VoiceName); diff --git a/src/minidexed.h b/src/minidexed.h index a008329..c9c4cc8 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -56,19 +56,19 @@ public: CSysExFileLoader *GetSysExFileLoader (void); - void BankSelectLSB (unsigned nBankLSB); - void ProgramChange (unsigned nProgram); - void SetVolume (unsigned nVolume); + void BankSelectLSB (unsigned nBankLSB, unsigned nTG); + void ProgramChange (unsigned nProgram, unsigned nTG); + void SetVolume (unsigned nVolume, unsigned nTG); - void keyup (int16_t pitch); - void keydown (int16_t pitch, uint8_t velocity); + void keyup (int16_t pitch, unsigned nTG); + void keydown (int16_t pitch, uint8_t velocity, unsigned nTG); - void setSustain (bool sustain); - void setModWheel (uint8_t value); - void setPitchbend (int16_t value); - void ControllersRefresh (void); + void setSustain (bool sustain, unsigned nTG); + void setModWheel (uint8_t value, unsigned nTG); + void setPitchbend (int16_t value, unsigned nTG); + void ControllersRefresh (unsigned nTG); - std::string GetVoiceName (unsigned nTG = 0); + std::string GetVoiceName (unsigned nTG); private: void ProcessSound (void); diff --git a/src/pckeyboard.cpp b/src/pckeyboard.cpp index 153cc31..90a7e9d 100644 --- a/src/pckeyboard.cpp +++ b/src/pckeyboard.cpp @@ -19,6 +19,7 @@ // #include "pckeyboard.h" #include "minidexed.h" +#include "config.h" #include #include #include @@ -112,7 +113,10 @@ void CPCKeyboard::KeyStatusHandlerRaw (unsigned char ucModifiers, const unsigned u8 ucKeyNumber = GetKeyNumber (ucKeyCode); if (ucKeyNumber != 0) { - s_pThis->m_pSynthesizer->keyup (ucKeyNumber); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + s_pThis->m_pSynthesizer->keyup (ucKeyNumber, nTG); + } } } } @@ -127,7 +131,10 @@ void CPCKeyboard::KeyStatusHandlerRaw (unsigned char ucModifiers, const unsigned u8 ucKeyNumber = GetKeyNumber (ucKeyCode); if (ucKeyNumber != 0) { - s_pThis->m_pSynthesizer->keydown (ucKeyNumber, 100); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + s_pThis->m_pSynthesizer->keydown (ucKeyNumber, 100, nTG); + } } } } diff --git a/src/userinterface.cpp b/src/userinterface.cpp index f3b79f4..e935768 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -37,10 +37,14 @@ CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManag m_pLCDBuffered (0), m_pRotaryEncoder (0), m_UIMode (UIModeVoiceSelect), - m_nBank (0), - m_nProgram (0), - m_nVolume (0) + m_nTG (0) { + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + m_nBank[nTG] = 0; + m_nProgram[nTG] = 0; + m_nVolume[nTG] = 0; + } } CUserInterface::~CUserInterface (void) @@ -108,10 +112,11 @@ void CUserInterface::Process (void) } } -void CUserInterface::BankSelected (unsigned nBankLSB) +void CUserInterface::BankSelected (unsigned nBankLSB, unsigned nTG) { assert (nBankLSB < 128); - m_nBank = nBankLSB; + assert (nTG < CConfig::ToneGenerators); + m_nBank[nTG] = nBankLSB; assert (m_pMiniDexed); std::string BankName = m_pMiniDexed->GetSysExFileLoader ()->GetBankName (nBankLSB); @@ -119,48 +124,62 @@ void CUserInterface::BankSelected (unsigned nBankLSB) // MIDI numbering starts with 0, user interface with 1 printf ("Select voice bank %u: \"%s\"\n", nBankLSB+1, BankName.c_str ()); - if (m_UIMode == UIModeBankSelect) + if ( m_UIMode == UIModeBankSelect + && m_nTG == nTG) { + CString TG; + TG.Format ("TG%u", nTG+1); + CString String; String.Format ("%u", nBankLSB+1); - DisplayWrite (String, "BANK", BankName.c_str ()); + DisplayWrite (TG, "BANK", String, BankName.c_str ()); } } -void CUserInterface::ProgramChanged (unsigned nProgram) +void CUserInterface::ProgramChanged (unsigned nProgram, unsigned nTG) { assert (nProgram < 128); - m_nProgram = nProgram; + assert (nTG < CConfig::ToneGenerators); + m_nProgram[nTG] = nProgram; nProgram++; // MIDI numbering starts with 0, user interface with 1 assert (m_pMiniDexed); - std::string VoiceName = m_pMiniDexed->GetVoiceName (); + std::string VoiceName = m_pMiniDexed->GetVoiceName (nTG); printf ("Loading voice %u: \"%s\"\n", nProgram, VoiceName.c_str ()); - if (m_UIMode == UIModeVoiceSelect) + if ( m_UIMode == UIModeVoiceSelect + && m_nTG == nTG) { + CString TG; + TG.Format ("TG%u", nTG+1); + CString String; String.Format ("%u", nProgram); - DisplayWrite (String, "VOICE", VoiceName.c_str ()); + DisplayWrite (TG, "VOICE", String, VoiceName.c_str ()); } } -void CUserInterface::VolumeChanged (unsigned nVolume) +void CUserInterface::VolumeChanged (unsigned nVolume, unsigned nTG) { assert (nVolume < 128); - m_nVolume = nVolume; + assert (nTG < CConfig::ToneGenerators); + m_nVolume[nTG] = nVolume; - if (m_UIMode == UIModeVolume) + if ( m_UIMode == UIModeVolume + && m_nTG == nTG) { + CString TG; + TG.Format ("TG%u", nTG+1); + char VolumeBar[CConfig::LCDColumns+1]; memset (VolumeBar, 0xFF, sizeof VolumeBar); // 0xFF is the block character VolumeBar[nVolume * CConfig::LCDColumns / 127] = '\0'; - DisplayWrite ("", "VOLUME", VolumeBar); + DisplayWrite (TG, "VOLUME", VolumeBar); } } @@ -235,6 +254,13 @@ void CUserInterface::EncoderEventHandler (CKY040::TEvent Event) } break; + case CKY040::EventSwitchDoubleClick: + if (++m_nTG == CConfig::ToneGenerators) + { + m_nTG = 0; + } + break; + case CKY040::EventSwitchHold: if (m_pRotaryEncoder->GetHoldSeconds () >= 3) { @@ -251,23 +277,23 @@ void CUserInterface::EncoderEventHandler (CKY040::TEvent Event) switch (m_UIMode) { case UIModeBankSelect: - if (m_nBank + nStep < 128) + if (m_nBank[m_nTG] + nStep < 128) { - m_pMiniDexed->BankSelectLSB (m_nBank + nStep); + m_pMiniDexed->BankSelectLSB (m_nBank[m_nTG] + nStep, m_nTG); } break; case UIModeVoiceSelect: - if (m_nProgram + nStep < 32) + if (m_nProgram[m_nTG] + nStep < 32) { - m_pMiniDexed->ProgramChange (m_nProgram + nStep); + m_pMiniDexed->ProgramChange (m_nProgram[m_nTG] + nStep, m_nTG); } break; case UIModeVolume: { const int Increment = 128 / CConfig::LCDColumns; - int nVolume = m_nVolume + nStep*Increment; + int nVolume = m_nVolume[m_nTG] + nStep*Increment; if (nVolume < 0) { nVolume = 0; @@ -277,7 +303,7 @@ void CUserInterface::EncoderEventHandler (CKY040::TEvent Event) nVolume = 127; } - m_pMiniDexed->SetVolume (nVolume); + m_pMiniDexed->SetVolume (nVolume, m_nTG); } break; default: diff --git a/src/userinterface.h b/src/userinterface.h index 6e34d99..972d2ec 100644 --- a/src/userinterface.h +++ b/src/userinterface.h @@ -38,9 +38,9 @@ public: void Process (void); - void BankSelected (unsigned nBankLSB); // 0 .. 127 - void ProgramChanged (unsigned nProgram); // 0 .. 127 - void VolumeChanged (unsigned nVolume); // 0 .. 127 + void BankSelected (unsigned nBankLSB, unsigned nTG); // 0 .. 127 + void ProgramChanged (unsigned nProgram, unsigned nTG); // 0 .. 127 + void VolumeChanged (unsigned nVolume, unsigned nTG); // 0 .. 127 private: // Print to display in this format: @@ -78,9 +78,10 @@ private: TUIMode m_UIMode; - unsigned m_nBank; - unsigned m_nProgram; - unsigned m_nVolume; + unsigned m_nTG; + unsigned m_nBank[CConfig::ToneGenerators]; + unsigned m_nProgram[CConfig::ToneGenerators]; + unsigned m_nVolume[CConfig::ToneGenerators]; }; #endif