diff --git a/src/config.cpp b/src/config.cpp index 3c237fa..b38991f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -110,6 +110,7 @@ void CConfig::Load (void) m_bMIDIDumpEnabled = m_Properties.GetNumber ("MIDIDumpEnabled", 0) != 0; m_bProfileEnabled = m_Properties.GetNumber ("ProfileEnabled", 0) != 0; + m_bPerformanceSelectToLoad = m_Properties.GetNumber ("PerformanceSelectToLoad", 1) != 0; } const char *CConfig::GetSoundDevice (void) const @@ -316,3 +317,8 @@ bool CConfig::GetProfileEnabled (void) const { return m_bProfileEnabled; } + +bool CConfig::GetPerformanceSelectToLoad (void) const +{ + return m_bPerformanceSelectToLoad; +} diff --git a/src/config.h b/src/config.h index 76382b1..dc5e7a3 100644 --- a/src/config.h +++ b/src/config.h @@ -126,6 +126,9 @@ public: // Debug bool GetMIDIDumpEnabled (void) const; bool GetProfileEnabled (void) const; + + // Load performance mode. 0 for load just rotating encoder, 1 load just when Select is pushed + bool GetPerformanceSelectToLoad (void) const; private: CPropertiesFatFsFile m_Properties; @@ -180,6 +183,7 @@ private: bool m_bMIDIDumpEnabled; bool m_bProfileEnabled; + bool m_bPerformanceSelectToLoad; }; #endif diff --git a/src/mididevice.cpp b/src/mididevice.cpp index ec89fe8..7b3683f 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -33,9 +33,12 @@ LOGMODULE ("mididevice"); #define MIDI_NOTE_OFF 0b1000 #define MIDI_NOTE_ON 0b1001 #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_MODULATION 1 + #define MIDI_CC_BREATH_CONTROLLER 2 + #define MIDI_CC_FOOT_PEDAL 4 #define MIDI_CC_VOLUME 7 #define MIDI_CC_PAN_POSITION 10 #define MIDI_CC_BANK_SELECT_LSB 32 @@ -226,6 +229,12 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign m_pSynthesizer->keyup (pMessage[1], nTG); break; + case MIDI_CHANNEL_AFTERTOUCH: + + m_pSynthesizer->setAftertouch (pMessage[1], nTG); + m_pSynthesizer->ControllersRefresh (nTG); + break; + case MIDI_CONTROL_CHANGE: if (nLength < 3) { @@ -238,7 +247,17 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign m_pSynthesizer->setModWheel (pMessage[2], nTG); m_pSynthesizer->ControllersRefresh (nTG); break; - + + case MIDI_CC_FOOT_PEDAL: + m_pSynthesizer->setFootController (pMessage[2], nTG); + m_pSynthesizer->ControllersRefresh (nTG); + break; + + case MIDI_CC_BREATH_CONTROLLER: + m_pSynthesizer->setBreathController (pMessage[2], nTG); + m_pSynthesizer->ControllersRefresh (nTG); + break; + case MIDI_CC_VOLUME: m_pSynthesizer->SetVolume (pMessage[2], nTG); break; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index c09eb42..2cbbfb9 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -52,7 +52,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_bProfileEnabled (m_pConfig->GetProfileEnabled ()), m_bSavePerformance (false), m_bSavePerformanceNewFile (false), - m_bSetNewPerformance (false) + m_bSetNewPerformance (false), + m_bDeletePerformance (false), + m_bLoadPerformanceBusy(false) { assert (m_pConfig); @@ -71,11 +73,20 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_nPortamentoMode[i] = 0; m_nPortamentoGlissando[i] = 0; m_nPortamentoTime[i] = 0; - + m_bMonoMode[i]=0; m_nNoteLimitLow[i] = 0; m_nNoteLimitHigh[i] = 127; m_nNoteShift[i] = 0; - + + m_nModulationWheelRange[i]=99; + m_nModulationWheelTarget[i]=7; + m_nFootControlRange[i]=99; + m_nFootControlTarget[i]=0; + m_nBreathControlRange[i]=99; + m_nBreathControlTarget[i]=0; + m_nAftertouchRange[i]=99; + m_nAftertouchTarget[i]=0; + m_nReverbSend[i] = 0; m_uchOPMask[i] = 0b111111; // All operators on @@ -177,8 +188,12 @@ bool CMiniDexed::Initialize (void) m_pTG[i]->setTranspose (24); m_pTG[i]->setPBController (2, 0); - m_pTG[i]->setMWController (99, 7, 0); + m_pTG[i]->setMWController (99, 1, 0); + m_pTG[i]->setFCController (99, 1, 0); + m_pTG[i]->setBCController (99, 1, 0); + m_pTG[i]->setATController (99, 1, 0); + tg_mixer->pan(i,mapfloat(m_nPan[i],0,127,0.0f,1.0f)); tg_mixer->gain(i,1.0f); reverb_send_mixer->pan(i,mapfloat(m_nPan[i],0,127,0.0f,1.0f)); @@ -225,7 +240,7 @@ bool CMiniDexed::Initialize (void) return false; } #endif - + return true; } @@ -263,12 +278,22 @@ void CMiniDexed::Process (bool bPlugAndPlayUpdated) m_bSavePerformanceNewFile = false; } - if (m_bSetNewPerformance) + if (m_bSetNewPerformance && !m_bLoadPerformanceBusy) { DoSetNewPerformance (); - m_bSetNewPerformance = false; + if (m_nSetNewPerformanceID == GetActualPerformanceID()) + { + m_bSetNewPerformance = false; + } + } + if(m_bDeletePerformance) + { + DoDeletePerformance (); + m_bDeletePerformance = false; + } + if (m_bProfileEnabled) { m_GetChunkTimer.Dump (); @@ -559,6 +584,28 @@ void CMiniDexed::setModWheel (uint8_t value, unsigned nTG) m_pTG[nTG]->setModWheel (value); } + +void CMiniDexed::setFootController (uint8_t value, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setFootController (value); +} + +void CMiniDexed::setBreathController (uint8_t value, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setBreathController (value); +} + +void CMiniDexed::setAftertouch (uint8_t value, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + m_pTG[nTG]->setAftertouch (value); +} + void CMiniDexed::setPitchbend (int16_t value, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); @@ -669,7 +716,28 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT case TGParameterPortamentoMode: setPortamentoMode (nValue, nTG); break; case TGParameterPortamentoGlissando: setPortamentoGlissando (nValue, nTG); break; case TGParameterPortamentoTime: setPortamentoTime (nValue, nTG); break; - + case TGParameterMonoMode: setMonoMode (nValue , nTG); break; + + case TGParameterMWRange: setModController(0, 0, nValue, nTG); break; + case TGParameterMWPitch: setModController(0, 1, nValue, nTG); break; + case TGParameterMWAmplitude: setModController(0, 2, nValue, nTG); break; + case TGParameterMWEGBias: setModController(0, 3, nValue, nTG); break; + + case TGParameterFCRange: setModController(1, 0, nValue, nTG); break; + case TGParameterFCPitch: setModController(1, 1, nValue, nTG); break; + case TGParameterFCAmplitude: setModController(1, 2, nValue, nTG); break; + case TGParameterFCEGBias: setModController(1, 3, nValue, nTG); break; + + case TGParameterBCRange: setModController(2, 0, nValue, nTG); break; + case TGParameterBCPitch: setModController(2, 1, nValue, nTG); break; + case TGParameterBCAmplitude: setModController(2, 2, nValue, nTG); break; + case TGParameterBCEGBias: setModController(2, 3, nValue, nTG); break; + + case TGParameterATRange: setModController(3, 0, nValue, nTG); break; + case TGParameterATPitch: setModController(3, 1, nValue, nTG); break; + case TGParameterATAmplitude: setModController(3, 2, nValue, nTG); break; + case TGParameterATEGBias: setModController(3, 3, nValue, nTG); break; + case TGParameterMIDIChannel: assert (0 <= nValue && nValue <= 255); SetMIDIChannel ((uint8_t) nValue, nTG); @@ -703,7 +771,29 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) case TGParameterPortamentoMode: return m_nPortamentoMode[nTG]; case TGParameterPortamentoGlissando: return m_nPortamentoGlissando[nTG]; case TGParameterPortamentoTime: return m_nPortamentoTime[nTG]; - + case TGParameterMonoMode: return m_bMonoMode[nTG] ? 1 : 0; + + case TGParameterMWRange: return getModController(0, 0, nTG); + case TGParameterMWPitch: return getModController(0, 1, nTG); + case TGParameterMWAmplitude: return getModController(0, 2, nTG); + case TGParameterMWEGBias: return getModController(0, 3, nTG); + + case TGParameterFCRange: return getModController(1, 0, nTG); + case TGParameterFCPitch: return getModController(1, 1, nTG); + case TGParameterFCAmplitude: return getModController(1, 2, nTG); + case TGParameterFCEGBias: return getModController(1, 3, nTG); + + case TGParameterBCRange: return getModController(2, 0, nTG); + case TGParameterBCPitch: return getModController(2, 1, nTG); + case TGParameterBCAmplitude: return getModController(2, 2, nTG); + case TGParameterBCEGBias: return getModController(2, 3, nTG); + + case TGParameterATRange: return getModController(3, 0, nTG); + case TGParameterATPitch: return getModController(3, 1, nTG); + case TGParameterATAmplitude: return getModController(3, 2, nTG); + case TGParameterATEGBias: return getModController(3, 3, nTG); + + default: assert (0); return 0; @@ -946,9 +1036,10 @@ void CMiniDexed::ProcessSound (void) #endif -bool CMiniDexed::SavePerformance (void) +bool CMiniDexed::SavePerformance (bool bSaveAsDeault) { m_bSavePerformance = true; + m_bSaveAsDeault=bSaveAsDeault; return true; } @@ -976,6 +1067,16 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG); m_pTG[nTG]->getVoiceData(m_nRawVoiceData); m_PerformanceConfig.SetVoiceDataToTxt (m_nRawVoiceData, nTG); + m_PerformanceConfig.SetMonoMode (m_bMonoMode[nTG], nTG); + + m_PerformanceConfig.SetModulationWheelRange (m_nModulationWheelRange[nTG], nTG); + m_PerformanceConfig.SetModulationWheelTarget (m_nModulationWheelTarget[nTG], nTG); + m_PerformanceConfig.SetFootControlRange (m_nFootControlRange[nTG], nTG); + m_PerformanceConfig.SetFootControlTarget (m_nFootControlTarget[nTG], nTG); + m_PerformanceConfig.SetBreathControlRange (m_nBreathControlRange[nTG], nTG); + m_PerformanceConfig.SetBreathControlTarget (m_nBreathControlTarget[nTG], nTG); + m_PerformanceConfig.SetAftertouchRange (m_nAftertouchRange[nTG], nTG); + m_PerformanceConfig.SetAftertouchTarget (m_nAftertouchTarget[nTG], nTG); m_PerformanceConfig.SetReverbSend (m_nReverbSend[nTG], nTG); } @@ -989,6 +1090,11 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetReverbDiffusion (m_nParameter[ParameterReverbDiffusion]); m_PerformanceConfig.SetReverbLevel (m_nParameter[ParameterReverbLevel]); + if(m_bSaveAsDeault) + { + m_PerformanceConfig.SetNewPerformance(0); + + } return m_PerformanceConfig.Save (); } @@ -996,7 +1102,7 @@ void CMiniDexed::setMonoMode(uint8_t mono, uint8_t nTG) { assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); - + m_bMonoMode[nTG]= mono != 0; m_pTG[nTG]->setMonoMode(constrain(mono, 0, 1)); m_pTG[nTG]->doRefreshVoice(); m_UI.ParameterChanged (); @@ -1068,7 +1174,10 @@ void CMiniDexed::setModWheelRange(uint8_t range, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); - m_pTG[nTG]->setModWheelRange(constrain(range, 0, 99)); + m_nModulationWheelRange[nTG] = range; + m_pTG[nTG]->setMWController(range, m_pTG[nTG]->getModWheelTarget(), 0); +// m_pTG[nTG]->setModWheelRange(constrain(range, 0, 99)); replaces with the above due to wrong constrain on dexed_synth module. + m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); } @@ -1078,6 +1187,8 @@ void CMiniDexed::setModWheelTarget(uint8_t target, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); + m_nModulationWheelTarget[nTG] = target; + m_pTG[nTG]->setModWheelTarget(constrain(target, 0, 7)); m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); @@ -1088,7 +1199,10 @@ void CMiniDexed::setFootControllerRange(uint8_t range, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); - m_pTG[nTG]->setFootControllerRange(constrain(range, 0, 99)); + m_nFootControlRange[nTG]=range; + m_pTG[nTG]->setFCController(range, m_pTG[nTG]->getFootControllerTarget(), 0); +// m_pTG[nTG]->setFootControllerRange(constrain(range, 0, 99)); replaces with the above due to wrong constrain on dexed_synth module. + m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); } @@ -1098,6 +1212,8 @@ void CMiniDexed::setFootControllerTarget(uint8_t target, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); + m_nFootControlTarget[nTG] = target; + m_pTG[nTG]->setFootControllerTarget(constrain(target, 0, 7)); m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); @@ -1108,7 +1224,10 @@ void CMiniDexed::setBreathControllerRange(uint8_t range, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); - m_pTG[nTG]->setBreathControllerRange(constrain(range, 0, 99)); + m_nBreathControlRange[nTG]=range; + m_pTG[nTG]->setBCController(range, m_pTG[nTG]->getBreathControllerTarget(), 0); + //m_pTG[nTG]->setBreathControllerRange(constrain(range, 0, 99)); + m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); } @@ -1118,6 +1237,8 @@ void CMiniDexed::setBreathControllerTarget(uint8_t target, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); + m_nBreathControlTarget[nTG]=target; + m_pTG[nTG]->setBreathControllerTarget(constrain(target, 0, 7)); m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); @@ -1128,7 +1249,10 @@ void CMiniDexed::setAftertouchRange(uint8_t range, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); - m_pTG[nTG]->setAftertouchRange(constrain(range, 0, 99)); + m_nAftertouchRange[nTG]=range; + m_pTG[nTG]->setATController(range, m_pTG[nTG]->getAftertouchTarget(), 0); +// m_pTG[nTG]->setAftertouchRange(constrain(range, 0, 99)); + m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); } @@ -1138,6 +1262,8 @@ void CMiniDexed::setAftertouchTarget(uint8_t target, uint8_t nTG) assert (nTG < CConfig::ToneGenerators); assert (m_pTG[nTG]); + m_nAftertouchTarget[nTG]=target; + m_pTG[nTG]->setAftertouchTarget(constrain(target, 0, 7)); m_pTG[nTG]->ControllersRefresh(); m_UI.ParameterChanged (); @@ -1244,17 +1370,6 @@ void CMiniDexed::SetActualPerformanceID(unsigned nID) m_PerformanceConfig.SetActualPerformanceID(nID); } -unsigned CMiniDexed::GetMenuSelectedPerformanceID() -{ - return m_PerformanceConfig.GetMenuSelectedPerformanceID(); -} - -void CMiniDexed::SetMenuSelectedPerformanceID(unsigned nID) -{ - m_PerformanceConfig.SetMenuSelectedPerformanceID(nID); -} - - bool CMiniDexed::SetNewPerformance(unsigned nID) { m_bSetNewPerformance = true; @@ -1265,17 +1380,21 @@ bool CMiniDexed::SetNewPerformance(unsigned nID) bool CMiniDexed::DoSetNewPerformance (void) { + m_bLoadPerformanceBusy = true; + unsigned nID = m_nSetNewPerformanceID; m_PerformanceConfig.SetNewPerformance(nID); if (m_PerformanceConfig.Load ()) { LoadPerformanceParameters(); + m_bLoadPerformanceBusy = false; return true; } else { SetMIDIChannel (CMIDIDevice::OmniMode, 0); + m_bLoadPerformanceBusy = false; return false; } } @@ -1288,10 +1407,9 @@ bool CMiniDexed::SavePerformanceNewFile () bool CMiniDexed::DoSavePerformanceNewFile (void) { - std::string nPerformanceName=""; // for future enhacements: capability to write performance name - if (m_PerformanceConfig.CreateNewPerformanceFile(nPerformanceName)) + if (m_PerformanceConfig.CreateNewPerformanceFile()) { - if(SavePerformance()) + if(SavePerformance(false)) { return true; } @@ -1336,8 +1454,18 @@ void CMiniDexed::LoadPerformanceParameters(void) uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG); m_pTG[nTG]->loadVoiceParameters(tVoiceData); } - + setMonoMode(m_PerformanceConfig.GetMonoMode(nTG) ? 1 : 0, nTG); SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); + + setModWheelRange (m_PerformanceConfig.GetModulationWheelRange (nTG), nTG); + setModWheelTarget (m_PerformanceConfig.GetModulationWheelTarget (nTG), nTG); + setFootControllerRange (m_PerformanceConfig.GetFootControlRange (nTG), nTG); + setFootControllerTarget (m_PerformanceConfig.GetFootControlTarget (nTG), nTG); + setBreathControllerRange (m_PerformanceConfig.GetBreathControlRange (nTG), nTG); + setBreathControllerTarget (m_PerformanceConfig.GetBreathControlTarget (nTG), nTG); + setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG); + setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG); + } @@ -1352,3 +1480,184 @@ void CMiniDexed::LoadPerformanceParameters(void) SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); } +std::string CMiniDexed::GetNewPerformanceDefaultName(void) +{ + return m_PerformanceConfig.GetNewPerformanceDefaultName(); +} + +void CMiniDexed::SetNewPerformanceName(std::string nName) +{ + m_PerformanceConfig.SetNewPerformanceName(nName); +} + +void CMiniDexed::SetVoiceName (std::string VoiceName, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + assert (m_pTG[nTG]); + char Name[10]; + strncpy(Name, VoiceName.c_str(),10); + m_pTG[nTG]->getName (Name); +} + +bool CMiniDexed::DeletePerformance(unsigned nID) +{ + m_bDeletePerformance = true; + m_nDeletePerformanceID = nID; + + return true; +} + +bool CMiniDexed::DoDeletePerformance(void) +{ + unsigned nID = m_nDeletePerformanceID; + if(m_PerformanceConfig.DeletePerformance(nID)) + { + if (m_PerformanceConfig.Load ()) + { + LoadPerformanceParameters(); + return true; + } + else + { + SetMIDIChannel (CMIDIDevice::OmniMode, 0); + } + } + + return false; +} + +bool CMiniDexed::GetPerformanceSelectToLoad(void) +{ + return m_pConfig->GetPerformanceSelectToLoad(); +} + +void CMiniDexed::setModController (unsigned controller, unsigned parameter, uint8_t value, uint8_t nTG) +{ + uint8_t nBits; + + switch (controller) + { + case 0: + if (parameter == 0) + { + setModWheelRange(value, nTG); + } + else + { + value=constrain(value, 0, 1); + nBits=m_nModulationWheelTarget[nTG]; + value == 1 ? nBits |= 1 << (parameter-1) : nBits &= ~(1 << (parameter-1)); + setModWheelTarget(nBits , nTG); + } + break; + + case 1: + if (parameter == 0) + { + setFootControllerRange(value, nTG); + } + else + { + value=constrain(value, 0, 1); + nBits=m_nFootControlTarget[nTG]; + value == 1 ? nBits |= 1 << (parameter-1) : nBits &= ~(1 << (parameter-1)); + setFootControllerTarget(nBits , nTG); + } + break; + + case 2: + if (parameter == 0) + { + setBreathControllerRange(value, nTG); + } + else + { + value=constrain(value, 0, 1); + nBits=m_nBreathControlTarget[nTG]; + value == 1 ? nBits |= 1 << (parameter-1) : nBits &= ~(1 << (parameter-1)); + setBreathControllerTarget(nBits , nTG); + } + break; + + case 3: + if (parameter == 0) + { + setAftertouchRange(value, nTG); + } + else + { + value=constrain(value, 0, 1); + nBits=m_nAftertouchTarget[nTG]; + value == 1 ? nBits |= 1 << (parameter-1) : nBits &= ~(1 << (parameter-1)); + setAftertouchTarget(nBits , nTG); + } + break; + default: + break; + } +} + +unsigned CMiniDexed::getModController (unsigned controller, unsigned parameter, uint8_t nTG) +{ + unsigned nBits; + switch (controller) + { + case 0: + if (parameter == 0) + { + return m_nModulationWheelRange[nTG]; + } + else + { + + nBits=m_nModulationWheelTarget[nTG]; + nBits &= 1 << (parameter-1); + return (nBits != 0 ? 1 : 0) ; + } + break; + + case 1: + if (parameter == 0) + { + return m_nFootControlRange[nTG]; + } + else + { + nBits=m_nFootControlTarget[nTG]; + nBits &= 1 << (parameter-1) ; + return (nBits != 0 ? 1 : 0) ; + } + break; + + case 2: + if (parameter == 0) + { + return m_nBreathControlRange[nTG]; + } + else + { + nBits=m_nBreathControlTarget[nTG]; + nBits &= 1 << (parameter-1) ; + return (nBits != 0 ? 1 : 0) ; + } + break; + + case 3: + if (parameter == 0) + { + return m_nAftertouchRange[nTG]; + } + else + { + nBits=m_nAftertouchTarget[nTG]; + nBits &= 1 << (parameter-1) ; + return (nBits != 0 ? 1 : 0) ; + } + break; + + default: + return 0; + break; + } + +} diff --git a/src/minidexed.h b/src/minidexed.h index 6945845..0e6fcb4 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -82,6 +82,10 @@ public: void setPitchbend (int16_t value, unsigned nTG); void ControllersRefresh (unsigned nTG); + void setFootController (uint8_t value, unsigned nTG); + void setBreathController (uint8_t value, unsigned nTG); + void setAftertouch (uint8_t value, unsigned nTG); + void SetReverbSend (unsigned nReverbSend, unsigned nTG); // 0 .. 127 void setMonoMode(uint8_t mono, uint8_t nTG); @@ -102,6 +106,9 @@ public: void setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG); void getSysExVoiceDump(uint8_t* dest, uint8_t nTG); + void setModController (unsigned controller, unsigned parameter, uint8_t value, uint8_t nTG); + unsigned getModController (unsigned controller, unsigned parameter, uint8_t nTG); + int16_t checkSystemExclusive(const uint8_t* pMessage, const uint16_t nLength, uint8_t nTG); std::string GetPerformanceFileName(unsigned nID); @@ -111,11 +118,11 @@ public: void SetActualPerformanceID(unsigned nID); bool SetNewPerformance(unsigned nID); bool SavePerformanceNewFile (); - unsigned GetMenuSelectedPerformanceID(); - void SetMenuSelectedPerformanceID(unsigned nID); bool DoSavePerformanceNewFile (void); bool DoSetNewPerformance (void); + bool GetPerformanceSelectToLoad(void); + bool SavePerformance (bool bSaveAsDeault); enum TParameter { @@ -133,6 +140,12 @@ public: void SetParameter (TParameter Parameter, int nValue); int GetParameter (TParameter Parameter); + std::string GetNewPerformanceDefaultName(void); + void SetNewPerformanceName(std::string nName); + void SetVoiceName (std::string VoiceName, unsigned nTG); + bool DeletePerformance(unsigned nID); + bool DoDeletePerformance(void); + enum TTGParameter { TGParameterVoiceBank, @@ -149,6 +162,28 @@ public: TGParameterPortamentoMode, TGParameterPortamentoGlissando, TGParameterPortamentoTime, + TGParameterMonoMode, + + TGParameterMWRange, + TGParameterMWPitch, + TGParameterMWAmplitude, + TGParameterMWEGBias, + + TGParameterFCRange, + TGParameterFCPitch, + TGParameterFCAmplitude, + TGParameterFCEGBias, + + TGParameterBCRange, + TGParameterBCPitch, + TGParameterBCAmplitude, + TGParameterBCEGBias, + + TGParameterATRange, + TGParameterATPitch, + TGParameterATAmplitude, + TGParameterATEGBias, + TGParameterUnknown }; @@ -204,7 +239,17 @@ private: unsigned m_nPortamentoMode[CConfig::ToneGenerators]; unsigned m_nPortamentoGlissando[CConfig::ToneGenerators]; unsigned m_nPortamentoTime[CConfig::ToneGenerators]; - + bool m_bMonoMode[CConfig::ToneGenerators]; + + unsigned m_nModulationWheelRange[CConfig::ToneGenerators]; + unsigned m_nModulationWheelTarget[CConfig::ToneGenerators]; + unsigned m_nFootControlRange[CConfig::ToneGenerators]; + unsigned m_nFootControlTarget[CConfig::ToneGenerators]; + unsigned m_nBreathControlRange[CConfig::ToneGenerators]; + unsigned m_nBreathControlTarget[CConfig::ToneGenerators]; + unsigned m_nAftertouchRange[CConfig::ToneGenerators]; + unsigned m_nAftertouchTarget[CConfig::ToneGenerators]; + unsigned m_nNoteLimitLow[CConfig::ToneGenerators]; unsigned m_nNoteLimitHigh[CConfig::ToneGenerators]; int m_nNoteShift[CConfig::ToneGenerators]; @@ -220,7 +265,8 @@ private: float32_t nMasterVolume; - + bool m_bDeletePerformance; + unsigned m_nDeletePerformanceID; CUserInterface m_UI; CSysExFileLoader m_SysExFileLoader; @@ -252,6 +298,8 @@ private: CSpinLock m_ReverbSpinLock; bool m_bSavePerformance; + bool m_bLoadPerformanceBusy; + bool m_bSaveAsDeault; }; #endif diff --git a/src/minidexed.ini b/src/minidexed.ini index a2cc2df..d9beec5 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -65,3 +65,6 @@ EncoderPinData=9 # Debug MIDIDumpEnabled=0 ProfileEnabled=0 + +# Performance +PerformanceSelectToLoad=1 diff --git a/src/performance.ini b/src/performance.ini index 1ab54b2..ba7d028 100644 --- a/src/performance.ini +++ b/src/performance.ini @@ -21,6 +21,15 @@ #PortamentoGlissando#=0 # 0 .. 1 #PortamentoTime#=0 # 0 .. 99 #VoiceData#= # space separated hex numbers of 156 voice parameters. Example: 5F 1D 14 32 63 [....] 20 55 +#MonoMode#=0 # 0-off .. 1-On +#ModulationWheelRange#=99 # 0..99 +#ModulationWheelTarget#=1 # 0..7 +#FootControlRange#=99 # 0..99 +#FootControlTarget#=0 # 0..7 +#BreathControlRange#=99 # 0..99 +#BreathControlTarget#=0 # 0..7 +#AftertouchRange#=99 # 0..99 +#AftertouchTarget#=0 # 0..7 # TG1 BankNumber1=0 @@ -41,6 +50,15 @@ PortamentoMode1=0 PortamentoGlissando1=0 PortamentoTime1=0 VoiceData1= +MonoMode1=0 +ModulationWheelRange1=99 +ModulationWheelTarget1=1 +FootControlRange1=99 +FootControlTarget1=0 +BreathControlRange1=99 +BreathControlTarget1=0 +AftertouchRange1=99 +AftertouchTarget1=0 # TG2 BankNumber2=0 @@ -61,6 +79,15 @@ PortamentoMode2=0 PortamentoGlissando2=0 PortamentoTime2=0 VoiceData2= +MonoMode2=0 +ModulationWheelRange2=99 +ModulationWheelTarget2=1 +FootControlRange2=99 +FootControlTarget2=0 +BreathControlRange2=99 +BreathControlTarget2=0 +AftertouchRange2=99 +AftertouchTarget2=0 # TG3 BankNumber3=0 @@ -81,6 +108,15 @@ PortamentoMode3=0 PortamentoGlissando3=0 PortamentoTime3=0 VoiceData3= +MonoMode3=0 +ModulationWheelRange3=99 +ModulationWheelTarget3=1 +FootControlRange3=99 +FootControlTarget3=0 +BreathControlRange3=99 +BreathControlTarget3=0 +AftertouchRange3=99 +AftertouchTarget3=0 # TG4 BankNumber4=0 @@ -101,6 +137,15 @@ PortamentoMode4=0 PortamentoGlissando4=0 PortamentoTime4=0 VoiceData4= +MonoMode4=0 +ModulationWheelRange4=99 +ModulationWheelTarget4=1 +FootControlRange4=99 +FootControlTarget4=0 +BreathControlRange4=99 +BreathControlTarget4=0 +AftertouchRange4=99 +AftertouchTarget4=0 # TG5 BankNumber5=0 @@ -121,6 +166,15 @@ PortamentoMode5=0 PortamentoGlissando5=0 PortamentoTime5=0 VoiceData5= +MonoMode5=0 +ModulationWheelRange5=99 +ModulationWheelTarget5=1 +FootControlRange5=99 +FootControlTarget5=0 +BreathControlRange5=99 +BreathControlTarget5=0 +AftertouchRange5=99 +AftertouchTarget5=0 # TG6 BankNumber6=0 @@ -141,6 +195,15 @@ PortamentoMode6=0 PortamentoGlissando6=0 PortamentoTime6=0 VoiceData6= +MonoMode6=0 +ModulationWheelRange6=99 +ModulationWheelTarget6=1 +FootControlRange6=99 +FootControlTarget6=0 +BreathControlRange6=99 +BreathControlTarget6=0 +AftertouchRange6=99 +AftertouchTarget6=0 # TG7 BankNumber7=0 @@ -161,6 +224,15 @@ PortamentoMode7=0 PortamentoGlissando7=0 PortamentoTime7=0 VoiceData7= +MonoMode7=0 +ModulationWheelRange7=99 +ModulationWheelTarget7=1 +FootControlRange7=99 +FootControlTarget7=0 +BreathControlRange7=99 +BreathControlTarget7=0 +AftertouchRange7=99 +AftertouchTarget7=0 # TG8 BankNumber8=0 @@ -181,6 +253,15 @@ PortamentoMode8=0 PortamentoGlissando8=0 PortamentoTime8=0 VoiceData8= +MonoMode8=0 +ModulationWheelRange8=99 +ModulationWheelTarget8=1 +FootControlRange8=99 +FootControlTarget8=0 +BreathControlRange8=99 +BreathControlTarget8=0 +AftertouchRange8=99 +AftertouchTarget8=0 # Effects #CompressorEnable=1 # 0: off, 1: on diff --git a/src/performanceconfig.cpp b/src/performanceconfig.cpp index c477248..7249003 100644 --- a/src/performanceconfig.cpp +++ b/src/performanceconfig.cpp @@ -119,6 +119,34 @@ bool CPerformanceConfig::Load (void) PropertyName.Format ("VoiceData%u", nTG+1); m_nVoiceDataTxt[nTG] = m_Properties.GetString (PropertyName, ""); + + PropertyName.Format ("MonoMode%u", nTG+1); + m_bMonoMode[nTG] = m_Properties.GetNumber (PropertyName, 0) != 0; + + PropertyName.Format ("ModulationWheelRange%u", nTG+1); + m_nModulationWheelRange[nTG] = m_Properties.GetNumber (PropertyName, 99); + + PropertyName.Format ("ModulationWheelTarget%u", nTG+1); + m_nModulationWheelTarget[nTG] = m_Properties.GetNumber (PropertyName, 1); + + PropertyName.Format ("FootControlRange%u", nTG+1); + m_nFootControlRange[nTG] = m_Properties.GetNumber (PropertyName, 99); + + PropertyName.Format ("FootControlTarget%u", nTG+1); + m_nFootControlTarget[nTG] = m_Properties.GetNumber (PropertyName, 0); + + PropertyName.Format ("BreathControlRange%u", nTG+1); + m_nBreathControlRange[nTG] = m_Properties.GetNumber (PropertyName, 99); + + PropertyName.Format ("BreathControlTarget%u", nTG+1); + m_nBreathControlTarget[nTG] = m_Properties.GetNumber (PropertyName, 0); + + PropertyName.Format ("AftertouchRange%u", nTG+1); + m_nAftertouchRange[nTG] = m_Properties.GetNumber (PropertyName, 99); + + PropertyName.Format ("AftertouchTarget%u", nTG+1); + m_nAftertouchTarget[nTG] = m_Properties.GetNumber (PropertyName, 0); + } m_bCompressorEnable = m_Properties.GetNumber ("CompressorEnable", 1) != 0; @@ -209,6 +237,34 @@ bool CPerformanceConfig::Save (void) PropertyName.Format ("VoiceData%u", nTG+1); char *cstr = &m_nVoiceDataTxt[nTG][0]; m_Properties.SetString (PropertyName, cstr); + + PropertyName.Format ("MonoMode%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_bMonoMode[nTG] ? 1 : 0); + + PropertyName.Format ("ModulationWheelRange%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nModulationWheelRange[nTG]); + + PropertyName.Format ("ModulationWheelTarget%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nModulationWheelTarget[nTG]); + + PropertyName.Format ("FootControlRange%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nFootControlRange[nTG]); + + PropertyName.Format ("FootControlTarget%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nFootControlTarget[nTG]); + + PropertyName.Format ("BreathControlRange%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nBreathControlRange[nTG]); + + PropertyName.Format ("BreathControlTarget%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nBreathControlTarget[nTG]); + + PropertyName.Format ("AftertouchRange%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nAftertouchRange[nTG]); + + PropertyName.Format ("AftertouchTarget%u", nTG+1); + m_Properties.SetNumber (PropertyName, m_nAftertouchTarget[nTG]); + } m_Properties.SetNumber ("CompressorEnable", m_bCompressorEnable ? 1 : 0); @@ -512,6 +568,113 @@ unsigned CPerformanceConfig::GetPortamentoTime (unsigned nTG) const return m_nPortamentoTime[nTG]; } +void CPerformanceConfig::SetMonoMode (bool bValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_bMonoMode[nTG] = bValue; +} + +bool CPerformanceConfig::GetMonoMode (unsigned nTG) const +{ + return m_bMonoMode[nTG]; +} + +void CPerformanceConfig::SetModulationWheelRange (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nModulationWheelRange[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetModulationWheelRange (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nModulationWheelRange[nTG]; +} + +void CPerformanceConfig::SetModulationWheelTarget (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nModulationWheelTarget[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetModulationWheelTarget (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nModulationWheelTarget[nTG]; +} + +void CPerformanceConfig::SetFootControlRange (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nFootControlRange[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetFootControlRange (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nFootControlRange[nTG]; +} + +void CPerformanceConfig::SetFootControlTarget (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nFootControlTarget[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetFootControlTarget (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nFootControlTarget[nTG]; +} + +void CPerformanceConfig::SetBreathControlRange (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nBreathControlRange[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetBreathControlRange (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nBreathControlRange[nTG]; +} + +void CPerformanceConfig::SetBreathControlTarget (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nBreathControlTarget[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetBreathControlTarget (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nBreathControlTarget[nTG]; +} + +void CPerformanceConfig::SetAftertouchRange (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nAftertouchRange[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetAftertouchRange (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nAftertouchRange[nTG]; +} + +void CPerformanceConfig::SetAftertouchTarget (unsigned nValue, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + m_nAftertouchTarget[nTG] = nValue; +} + +unsigned CPerformanceConfig::GetAftertouchTarget (unsigned nTG) const +{ + assert (nTG < CConfig::ToneGenerators); + return m_nAftertouchTarget[nTG]; +} + void CPerformanceConfig::SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); @@ -579,25 +742,15 @@ void CPerformanceConfig::SetActualPerformanceID(unsigned nID) nActualPerformance = nID; } -unsigned CPerformanceConfig::GetMenuSelectedPerformanceID() -{ - return nMenuSelectedPerformance; -} - -void CPerformanceConfig::SetMenuSelectedPerformanceID(unsigned nID) -{ - nMenuSelectedPerformance = nID; -} - bool CPerformanceConfig::GetInternalFolderOk() { return nInternalFolderOk; } -bool CPerformanceConfig::CreateNewPerformanceFile(std::string sPerformanceName) +bool CPerformanceConfig::CreateNewPerformanceFile(void) { - // sPerformanceName for future improvements when user can enter a name via UI - + std::string sPerformanceName = NewPerformanceName; + NewPerformanceName=""; nActualPerformance=nLastPerformance; std::string nFileName; std::string nPath; @@ -697,7 +850,7 @@ bool CPerformanceConfig::ListPerformances() // sort by performance number-name if (nLastPerformance > 2) { - sort (m_nPerformanceFileName+1, m_nPerformanceFileName + nLastPerformance - 1); // default is always on first place. + sort (m_nPerformanceFileName+1, m_nPerformanceFileName + nLastPerformance); // default is always on first place. %%%%%%%%%%%%%%%% } } @@ -718,3 +871,55 @@ void CPerformanceConfig::SetNewPerformance (unsigned nID) new (&m_Properties) CPropertiesFatFsFile(FileN.c_str(), m_pFileSystem); } + +std::string CPerformanceConfig::GetNewPerformanceDefaultName(void) +{ + std::string nIndex = "000000"; + nIndex += std::to_string(nLastFileIndex+1); + nIndex = nIndex.substr(nIndex.length()-6,6); + return "Perf" + nIndex; +} + +void CPerformanceConfig::SetNewPerformanceName(std::string nName) +{ + int i = nName.length(); + do + { + --i; + } + while (i>=0 && nName[i] == 32); + nName=nName.substr(0,i+1) ; + + NewPerformanceName = nName; +} + +bool CPerformanceConfig::DeletePerformance(unsigned nID) +{ + bool bOK = false; + if(nID == 0){return bOK;} // default (performance.ini at root directory) can't be deleted + DIR Directory; + FILINFO FileInfo; + std::string FileN = "SD:/"; + FileN += PERFORMANCE_DIR; + + + FRESULT Result = f_findfirst (&Directory, &FileInfo, FileN.c_str(), m_nPerformanceFileName[nID].c_str()); + if (Result == FR_OK && FileInfo.fname[0]) + { + FileN += "/"; + FileN += m_nPerformanceFileName[nID]; + Result=f_unlink (FileN.c_str()); + if (Result == FR_OK) + { + SetNewPerformance(0); + nActualPerformance =0; + //nMenuSelectedPerformance=0; + m_nPerformanceFileName[nID]="ZZZZZZ"; + sort (m_nPerformanceFileName+1, m_nPerformanceFileName + nLastPerformance); // test si va con -1 o no + --nLastPerformance; + m_nPerformanceFileName[nLastPerformance]=nullptr; + bOK=true; + } + } + return bOK; +} diff --git a/src/performanceconfig.h b/src/performanceconfig.h index 2110e34..145cb5f 100644 --- a/src/performanceconfig.h +++ b/src/performanceconfig.h @@ -57,7 +57,17 @@ public: unsigned GetPortamentoMode (unsigned nTG) const; // 0 .. 1 unsigned GetPortamentoGlissando (unsigned nTG) const; // 0 .. 1 unsigned GetPortamentoTime (unsigned nTG) const; // 0 .. 99 + bool GetMonoMode (unsigned nTG) const; // 0 .. 1 + unsigned GetModulationWheelRange (unsigned nTG) const; // 0 .. 99 + unsigned GetModulationWheelTarget (unsigned nTG) const; // 0 .. 7 + unsigned GetFootControlRange (unsigned nTG) const; // 0 .. 99 + unsigned GetFootControlTarget (unsigned nTG) const; // 0 .. 7 + unsigned GetBreathControlRange (unsigned nTG) const; // 0 .. 99 + unsigned GetBreathControlTarget (unsigned nTG) const; // 0 .. 7 + unsigned GetAftertouchRange (unsigned nTG) const; // 0 .. 99 + unsigned GetAftertouchTarget (unsigned nTG) const; // 0 .. 7 + void SetBankNumber (unsigned nValue, unsigned nTG); void SetVoiceNumber (unsigned nValue, unsigned nTG); void SetMIDIChannel (unsigned nValue, unsigned nTG); @@ -77,7 +87,17 @@ public: void SetPortamentoTime (unsigned nValue, unsigned nTG); void SetVoiceDataToTxt (const uint8_t *pData, unsigned nTG); uint8_t *GetVoiceDataFromTxt (unsigned nTG); - + void SetMonoMode (bool bOKValue, unsigned nTG); + + void SetModulationWheelRange (unsigned nValue, unsigned nTG); + void SetModulationWheelTarget (unsigned nValue, unsigned nTG); + void SetFootControlRange (unsigned nValue, unsigned nTG); + void SetFootControlTarget (unsigned nValue, unsigned nTG); + void SetBreathControlRange (unsigned nValue, unsigned nTG); + void SetBreathControlTarget (unsigned nValue, unsigned nTG); + void SetAftertouchRange (unsigned nValue, unsigned nTG); + void SetAftertouchTarget (unsigned nValue, unsigned nTG); + // Effects bool GetCompressorEnable (void) const; bool GetReverbEnable (void) const; @@ -106,10 +126,11 @@ public: unsigned GetLastPerformance(); void SetActualPerformanceID(unsigned nID); unsigned GetActualPerformanceID(); - void SetMenuSelectedPerformanceID(unsigned nID); - unsigned GetMenuSelectedPerformanceID(); - bool CreateNewPerformanceFile(std::string sPerformanceName); + bool CreateNewPerformanceFile(void); bool GetInternalFolderOk(); + std::string GetNewPerformanceDefaultName(void); + void SetNewPerformanceName(std::string nName); + bool DeletePerformance(unsigned nID); private: CPropertiesFatFsFile m_Properties; @@ -132,17 +153,28 @@ private: unsigned m_nPortamentoGlissando[CConfig::ToneGenerators]; unsigned m_nPortamentoTime[CConfig::ToneGenerators]; std::string m_nVoiceDataTxt[CConfig::ToneGenerators]; - + bool m_bMonoMode[CConfig::ToneGenerators]; + + unsigned m_nModulationWheelRange[CConfig::ToneGenerators]; + unsigned m_nModulationWheelTarget[CConfig::ToneGenerators]; + unsigned m_nFootControlRange[CConfig::ToneGenerators]; + unsigned m_nFootControlTarget[CConfig::ToneGenerators]; + unsigned m_nBreathControlRange[CConfig::ToneGenerators]; + unsigned m_nBreathControlTarget[CConfig::ToneGenerators]; + unsigned m_nAftertouchRange[CConfig::ToneGenerators]; + unsigned m_nAftertouchTarget[CConfig::ToneGenerators]; + unsigned nLastPerformance; unsigned nLastFileIndex; unsigned nActualPerformance = 0; - unsigned nMenuSelectedPerformance = 0; + //unsigned nMenuSelectedPerformance = 0; std::string m_nPerformanceFileName[40]; FATFS *m_pFileSystem; bool nInternalFolderOk=false; bool nExternalFolderOk=false; // for future USB implementation - + std::string NewPerformanceName=""; + bool m_bCompressorEnable; bool m_bReverbEnable; unsigned m_nReverbSize; diff --git a/src/serialmididevice.cpp b/src/serialmididevice.cpp index aed64a6..cdb5153 100644 --- a/src/serialmididevice.cpp +++ b/src/serialmididevice.cpp @@ -130,7 +130,8 @@ void CSerialMIDIDevice::Process (void) m_SerialMessage[m_nSerialState++] = uchData; if ( (m_SerialMessage[0] & 0xE0) == 0xC0 - || m_nSerialState == 3) // message is complete + || m_nSerialState == 3 // message is complete + || (m_SerialMessage[0] & 0xF0) == 0xD0) // channel aftertouch { MIDIMessageHandler (m_SerialMessage, m_nSerialState); diff --git a/src/uimenu.cpp b/src/uimenu.cpp index 6191add..6013029 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -52,8 +52,7 @@ const CUIMenu::TMenuItem CUIMenu::s_MainMenu[] = {"TG8", MenuHandler, s_TGMenu, 7}, #endif {"Effects", MenuHandler, s_EffectsMenu}, - {"Performance", PerformanceMenu}, - {"Save", MenuHandler, s_SaveMenu}, + {"Performance", MenuHandler, s_PerformanceMenu}, {0} }; @@ -71,6 +70,8 @@ const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] = {"Resonance", EditTGParameter, 0, CMiniDexed::TGParameterResonance}, {"Pitch Bend", MenuHandler, s_EditPitchBendMenu}, {"Portamento", MenuHandler, s_EditPortamentoMenu}, + {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, + {"Modulation", MenuHandler, s_ModulationMenu}, {"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, {"Edit Voice", MenuHandler, s_EditVoiceMenu}, {0} @@ -100,6 +101,24 @@ const CUIMenu::TMenuItem CUIMenu::s_EditPortamentoMenu[] = {0} }; +const CUIMenu::TMenuItem CUIMenu::s_ModulationMenu[] = +{ + {"Mod. Wheel", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterMWRange}, + {"Foot Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterFCRange}, + {"Breath Control", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterBCRange}, + {"Aftertouch", MenuHandler, s_ModulationMenuParameters, CMiniDexed::TGParameterATRange}, + {0} +}; + +const CUIMenu::TMenuItem CUIMenu::s_ModulationMenuParameters[] = +{ + {"Range", EditTGParameterModulation, 0, 0}, + {"Pitch", EditTGParameterModulation, 0, 1}, + {"Amplitude", EditTGParameterModulation, 0, 2}, + {"EG Bias", EditTGParameterModulation, 0, 3}, + {0} +}; + #ifdef ARM_ALLOW_MULTI_CORE const CUIMenu::TMenuItem CUIMenu::s_ReverbMenu[] = @@ -144,6 +163,7 @@ const CUIMenu::TMenuItem CUIMenu::s_EditVoiceMenu[] = {"LFO Wave", EditVoiceParameter, 0, DEXED_LFO_WAVE}, {"P Mod Sens.", EditVoiceParameter, 0, DEXED_LFO_PITCH_MOD_SENS}, {"Transpose", EditVoiceParameter, 0, DEXED_TRANSPOSE}, + {"Name", InputTxt,0 , 3}, {0} }; @@ -176,8 +196,9 @@ const CUIMenu::TMenuItem CUIMenu::s_OperatorMenu[] = const CUIMenu::TMenuItem CUIMenu::s_SaveMenu[] = { - {"Overwrite", SavePerformance}, - {"New", SavePerformanceNewFile}, + {"Overwrite", SavePerformance, 0, 0}, + {"New", InputTxt,0 , 1}, + {"Save as default", SavePerformance, 0, 1}, {0} }; @@ -208,9 +229,27 @@ const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown] {0, 99, 1}, // TGParameterReverbSend {0, 12, 1}, // TGParameterPitchBendRange {0, 12, 1}, // TGParameterPitchBendStep - {0, 1, 1, ToPortaMode}, // TGParameterPortamentoMode - {0, 1, 1, ToPortaGlissando}, // TGParameterPortamentoGlissando - {0, 99, 1} // TGParameterPortamentoTime + {0, 1, 1, ToPortaMode}, // TGParameterPortamentoMode + {0, 1, 1, ToPortaGlissando}, // TGParameterPortamentoGlissando + {0, 99, 1}, // TGParameterPortamentoTime + {0, 1, 1, ToPolyMono}, // TGParameterMonoMode + {0, 99, 1}, //MW Range + {0, 1, 1, ToOnOff}, //MW Pitch + {0, 1, 1, ToOnOff}, //MW Amp + {0, 1, 1, ToOnOff}, //MW EGBias + {0, 99, 1}, //FC Range + {0, 1, 1, ToOnOff}, //FC Pitch + {0, 1, 1, ToOnOff}, //FC Amp + {0, 1, 1, ToOnOff}, //FC EGBias + {0, 99, 1}, //BC Range + {0, 1, 1, ToOnOff}, //BC Pitch + {0, 1, 1, ToOnOff}, //BC Amp + {0, 1, 1, ToOnOff}, //BC EGBias + {0, 99, 1}, //AT Range + {0, 1, 1, ToOnOff}, //AT Pitch + {0, 1, 1, ToOnOff}, //AT Amp + {0, 1, 1, ToOnOff} //AT EGBias + }; // must match DexedVoiceParameters in Synth_Dexed @@ -234,7 +273,8 @@ const CUIMenu::TParameter CUIMenu::s_VoiceParameter[] = {0, 1, 1, ToOnOff}, // DEXED_LFO_SYNC {0, 5, 1, ToLFOWaveform}, // DEXED_LFO_WAVE {0, 7, 1}, // DEXED_LFO_PITCH_MOD_SENS - {0, 48, 1, ToTransposeNote} // DEXED_TRANSPOSE + {0, 48, 1, ToTransposeNote}, // DEXED_TRANSPOSE + {0, 1, 1} // Voice Name - Dummy parameters for in case new item would be added in future }; // must match DexedVoiceOPParameters in Synth_Dexed @@ -278,6 +318,15 @@ const char CUIMenu::s_NoteName[100][4] = }; static const unsigned NoteC3 = 27; +const CUIMenu::TMenuItem CUIMenu::s_PerformanceMenu[] = +{ + {"Load", PerformanceMenu, 0, 0}, + {"Save", MenuHandler, s_SaveMenu}, + {"Delete", PerformanceMenu, 0, 1}, + {0} +}; + + CUIMenu::CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed) : m_pUI (pUI), m_pMiniDexed (pMiniDexed), @@ -799,7 +848,7 @@ void CUIMenu::SavePerformance (CUIMenu *pUIMenu, TMenuEvent Event) return; } - bool bOK = pUIMenu->m_pMiniDexed->SavePerformance (); + bool bOK = pUIMenu->m_pMiniDexed->SavePerformance (pUIMenu->m_nCurrentParameter == 1); const char *pMenuName = pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1] @@ -1020,6 +1069,16 @@ string CUIMenu::ToPortaGlissando (int nValue) } }; +string CUIMenu::ToPolyMono (int nValue) +{ + switch (nValue) + { + case 0: return "Poly"; + case 1: return "Mono"; + default: return to_string (nValue); + } +} + void CUIMenu::TGShortcutHandler (TMenuEvent Event) { assert (m_nCurrentMenuDepth >= 2); @@ -1088,79 +1147,364 @@ void CUIMenu::TimerHandler (TKernelTimerHandle hTimer, void *pParam, void *pCont pThis->EventHandler (MenuEventBack); } +void CUIMenu::TimerHandlerNoBack (TKernelTimerHandle hTimer, void *pParam, void *pContext) +{ + CUIMenu *pThis = static_cast (pContext); + assert (pThis); + + pThis->m_bSplashShow = false; + + pThis->EventHandler (MenuEventUpdate); +} + void CUIMenu::PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event) { + bool bPerformanceSelectToLoad = pUIMenu->m_pMiniDexed->GetPerformanceSelectToLoad(); + unsigned nValue = pUIMenu->m_nSelectedPerformanceID; + std::string Value; + + if (Event == MenuEventUpdate) + { + pUIMenu->m_bPerformanceDeleteMode=false; + } + + if (pUIMenu->m_bSplashShow) + { + return; + } - unsigned nValue = pUIMenu->m_pMiniDexed->GetMenuSelectedPerformanceID(); + if(!pUIMenu->m_bPerformanceDeleteMode) + { + switch (Event) + { + case MenuEventUpdate: + break; + + case MenuEventStepDown: + if (nValue > 0) + { + --nValue; + } + pUIMenu->m_nSelectedPerformanceID = nValue; + if (!bPerformanceSelectToLoad && pUIMenu->m_nCurrentParameter==0) + { + pUIMenu->m_pMiniDexed->SetNewPerformance(nValue); + } + break; + + case MenuEventStepUp: + if (++nValue > (unsigned) pUIMenu->m_pMiniDexed->GetLastPerformance()-1) + { + nValue = pUIMenu->m_pMiniDexed->GetLastPerformance()-1; + } + pUIMenu->m_nSelectedPerformanceID = nValue; + if (!bPerformanceSelectToLoad && pUIMenu->m_nCurrentParameter==0) + { + pUIMenu->m_pMiniDexed->SetNewPerformance(nValue); + } + break; + + case MenuEventSelect: + switch (pUIMenu->m_nCurrentParameter) + { + case 0: + if (bPerformanceSelectToLoad) + { + pUIMenu->m_pMiniDexed->SetNewPerformance(nValue); + } + + break; + case 1: + if (pUIMenu->m_nSelectedPerformanceID != 0) + { + pUIMenu->m_bPerformanceDeleteMode=true; + pUIMenu->m_bConfirmDeletePerformance=false; + } + break; + default: + break; + } + break; + default: + return; + } + } + else + { + switch (Event) + { + case MenuEventUpdate: + break; + + case MenuEventStepDown: + pUIMenu->m_bConfirmDeletePerformance=false; + break; + + case MenuEventStepUp: + pUIMenu->m_bConfirmDeletePerformance=true; + break; + + case MenuEventSelect: + pUIMenu->m_bPerformanceDeleteMode=false; + if (pUIMenu->m_bConfirmDeletePerformance) + { + pUIMenu->m_nSelectedPerformanceID = 0; + pUIMenu->m_bConfirmDeletePerformance=false; + pUIMenu->m_pUI->DisplayWrite ("", "Delete", pUIMenu->m_pMiniDexed->DeletePerformance(nValue) ? "Completed" : "Error", false, false); + pUIMenu->m_bSplashShow=true; + CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandlerNoBack, 0, pUIMenu); + return; + } + else + { + break; + } + + default: + return; + } + } + + if(!pUIMenu->m_bPerformanceDeleteMode) + { + Value = pUIMenu->m_pMiniDexed->GetPerformanceName(nValue); + + + std::string nPSelected = ""; + if(nValue == pUIMenu->m_pMiniDexed->GetActualPerformanceID()) + { + nPSelected= "[L]"; + } + + pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(), + Value.c_str (), + (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance()-1); + } + else + { + pUIMenu->m_pUI->DisplayWrite ("", "Delete?", pUIMenu->m_bConfirmDeletePerformance ? "Yes" : "No", false, false); + } +} + +void CUIMenu::InputTxt (CUIMenu *pUIMenu, TMenuEvent Event) +{ + unsigned nTG=0; + string TG ("TG"); + + std::string MsgOk; + std::string NoValidChars; + unsigned MaxChars; + std::string MenuTitleR; + std::string MenuTitleL; + std::string OkTitleL; + std::string OkTitleR; + + switch(pUIMenu->m_nCurrentParameter) + { + case 1: // save new performance + NoValidChars = {92, 47, 58, 42, 63, 34, 60,62, 124}; + MaxChars=14; + MenuTitleL="Performance Name"; + MenuTitleR=""; + OkTitleL="New Performance"; // \E[?25l + OkTitleR=""; + break; + + case 2: // Rename performance - NOT Implemented yet + NoValidChars = {92, 47, 58, 42, 63, 34, 60,62, 124}; + MaxChars=14; + MenuTitleL="Performance Name"; + MenuTitleR=""; + OkTitleL="Rename Perf."; // \E[?25l + OkTitleR=""; + break; + case 3: // Voice name + nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; + NoValidChars = {127}; + MaxChars=10; + MenuTitleL="Name"; + TG += to_string (nTG+1); + MenuTitleR=TG; + OkTitleL=""; + OkTitleR=""; + break; + + default: + return; + } + + bool bOK; + unsigned nPosition = pUIMenu->m_InputTextPosition; + unsigned nChar = pUIMenu->m_InputText[nPosition]; + + switch (Event) { case MenuEventUpdate: + if(pUIMenu->m_nCurrentParameter == 1 || pUIMenu->m_nCurrentParameter == 2) + { + pUIMenu->m_InputText = pUIMenu->m_pMiniDexed->GetNewPerformanceDefaultName(); + pUIMenu->m_InputText += " "; + pUIMenu->m_InputText = pUIMenu->m_InputText.substr(0,14); + pUIMenu->m_InputTextPosition=0; + nPosition=pUIMenu->m_InputTextPosition; + nChar = pUIMenu->m_InputText[nPosition]; + } + else + { + + pUIMenu->m_InputText = pUIMenu->m_pMiniDexed->GetVoiceName(nTG); + pUIMenu->m_InputText += " "; + pUIMenu->m_InputText = pUIMenu->m_InputText.substr(0,10); + pUIMenu->m_InputTextPosition=0; + nPosition=pUIMenu->m_InputTextPosition; + nChar = pUIMenu->m_InputText[nPosition]; + } break; case MenuEventStepDown: - if (nValue > 0) + if (nChar > 32) { - --nValue; + do { + --nChar; + } + while (NoValidChars.find(nChar) != std::string::npos); } - pUIMenu->m_pMiniDexed->SetMenuSelectedPerformanceID (nValue); + pUIMenu->m_InputTextChar = nChar; break; case MenuEventStepUp: - if (++nValue > (unsigned) pUIMenu->m_pMiniDexed->GetLastPerformance()-1) + if (nChar < 126) { - nValue = pUIMenu->m_pMiniDexed->GetLastPerformance()-1; + do { + ++nChar; + } + while (NoValidChars.find(nChar) != std::string::npos); } - pUIMenu->m_pMiniDexed->SetMenuSelectedPerformanceID (nValue); - break; - + pUIMenu->m_InputTextChar = nChar; + break; + + + case MenuEventSelect: - pUIMenu->m_pMiniDexed->SetNewPerformance(nValue); + if(pUIMenu->m_nCurrentParameter == 1) + { + pUIMenu->m_pMiniDexed->SetNewPerformanceName(pUIMenu->m_InputText); + bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile (); + MsgOk=bOK ? "Completed" : "Error"; + pUIMenu->m_pUI->DisplayWrite (OkTitleR.c_str(), OkTitleL.c_str(), MsgOk.c_str(), false, false); + CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandler, 0, pUIMenu); + return; + } + else + { + break; // Voice Name Edit + } + case MenuEventPressAndStepDown: + if (nPosition > 0) + { + --nPosition; + } + pUIMenu->m_InputTextPosition = nPosition; + nChar = pUIMenu->m_InputText[nPosition]; break; - - case MenuEventPressAndStepDown: case MenuEventPressAndStepUp: - pUIMenu->TGShortcutHandler (Event); - return; + if (nPosition < MaxChars-1) + { + ++nPosition; + } + pUIMenu->m_InputTextPosition = nPosition; + nChar = pUIMenu->m_InputText[nPosition]; + break; default: return; } - string Value = pUIMenu->m_pMiniDexed->GetPerformanceName(nValue); + + // \E[2;%dH Cursor move to row %1 and column %2 (starting at 1) + // \E[?25h Normal cursor visible + // \E[?25l Cursor invisible + + std::string escCursor="\E[?25h\E[2;"; // this is to locate cursor + escCursor += to_string(nPosition + 2); + escCursor += "H"; - std::string nPSelected = ""; - if(nValue == pUIMenu->m_pMiniDexed->GetActualPerformanceID()) - { - nPSelected="[Ld]"; - } - - pUIMenu->m_pUI->DisplayWrite (pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, nPSelected.c_str(), - Value.c_str (), - (int) nValue > 0, (int) nValue < (int) pUIMenu->m_pMiniDexed->GetLastPerformance()-1); + std::string Value = pUIMenu->m_InputText; + Value[nPosition]=nChar; + pUIMenu->m_InputText = Value; + + if(pUIMenu->m_nCurrentParameter == 3) + { + pUIMenu->m_pMiniDexed->SetVoiceName(pUIMenu->m_InputText, nTG); + } + + Value = Value + " " + escCursor ; + pUIMenu->m_pUI->DisplayWrite (MenuTitleR.c_str(),MenuTitleL.c_str(), Value.c_str(), false, false); + } -void CUIMenu::SavePerformanceNewFile (CUIMenu *pUIMenu, TMenuEvent Event) +void CUIMenu::EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event) { - if (Event != MenuEventUpdate) + + unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-3]; + 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]; + + int nValue = pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG); + + switch (Event) { + case MenuEventUpdate: + break; + + case MenuEventStepDown: + nValue -= rParam.Increment; + if (nValue < rParam.Minimum) + { + nValue = rParam.Minimum; + } + pUIMenu->m_pMiniDexed->SetTGParameter (Param, nValue, nTG); + break; + + case MenuEventStepUp: + nValue += rParam.Increment; + if (nValue > rParam.Maximum) + { + nValue = rParam.Maximum; + } + pUIMenu->m_pMiniDexed->SetTGParameter (Param, nValue, nTG); + break; + + case MenuEventPressAndStepDown: + case MenuEventPressAndStepUp: + pUIMenu->TGShortcutHandler (Event); + return; + + default: return; } - bool bOK = pUIMenu->m_pMiniDexed->SavePerformanceNewFile (); + string TG ("TG"); + TG += to_string (nTG+1); - const char *pMenuName = - pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth-1] - [pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth-1]].Name; + string Value = GetTGValueString (Param, pUIMenu->m_pMiniDexed->GetTGParameter (Param, nTG)); - pUIMenu->m_pUI->DisplayWrite (pMenuName, + pUIMenu->m_pUI->DisplayWrite (TG.c_str (), pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, - bOK ? "Completed" : "Error", - false, false); - - CTimer::Get ()->StartKernelTimer (MSEC2HZ (1500), TimerHandler, 0, pUIMenu); + Value.c_str (), + nValue > rParam.Minimum, nValue < rParam.Maximum); + } + + diff --git a/src/uimenu.h b/src/uimenu.h index d5935af..78384be 100644 --- a/src/uimenu.h +++ b/src/uimenu.h @@ -52,7 +52,7 @@ public: CUIMenu (CUserInterface *pUI, CMiniDexed *pMiniDexed); void EventHandler (TMenuEvent Event); - + private: typedef void TMenuHandler (CUIMenu *pUIMenu, TMenuEvent Event); @@ -84,7 +84,7 @@ private: static void EditOPParameter (CUIMenu *pUIMenu, TMenuEvent Event); static void SavePerformance (CUIMenu *pUIMenu, TMenuEvent Event); static void EditTGParameter2 (CUIMenu *pUIMenu, TMenuEvent Event); - + static void EditTGParameterModulation (CUIMenu *pUIMenu, TMenuEvent Event); static void PerformanceMenu (CUIMenu *pUIMenu, TMenuEvent Event); static void SavePerformanceNewFile (CUIMenu *pUIMenu, TMenuEvent Event); @@ -107,12 +107,16 @@ private: static std::string ToOscillatorDetune (int nValue); static std::string ToPortaMode (int nValue); static std::string ToPortaGlissando (int nValue); + static std::string ToPolyMono (int nValue); void TGShortcutHandler (TMenuEvent Event); void OPShortcutHandler (TMenuEvent Event); static void TimerHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext); + static void InputTxt (CUIMenu *pUIMenu, TMenuEvent Event); + static void TimerHandlerNoBack (TKernelTimerHandle hTimer, void *pParam, void *pContext); + private: CUserInterface *m_pUI; CMiniDexed *m_pMiniDexed; @@ -140,13 +144,26 @@ private: static const TMenuItem s_SaveMenu[]; static const TMenuItem s_EditPitchBendMenu[]; static const TMenuItem s_EditPortamentoMenu[]; - + static const TMenuItem s_PerformanceMenu[]; + + static const TMenuItem s_ModulationMenu[]; + static const TMenuItem s_ModulationMenuParameters[]; + static const TParameter s_GlobalParameter[]; static const TParameter s_TGParameter[]; static const TParameter s_VoiceParameter[]; static const TParameter s_OPParameter[]; static const char s_NoteName[100][4]; + + std::string m_InputText="1234567890ABCD"; + unsigned m_InputTextPosition=0; + unsigned m_InputTextChar=32; + bool m_bPerformanceDeleteMode=false; + bool m_bConfirmDeletePerformance=false; + unsigned m_nSelectedPerformanceID =0; + bool m_bSplashShow=false; + }; #endif diff --git a/src/userinterface.cpp b/src/userinterface.cpp index e013779..17083bd 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -173,7 +173,7 @@ void CUserInterface::DisplayWrite (const char *pMenu, const char *pParam, const assert (pParam); assert (pValue); - CString Msg ("\x1B[H"); // cursor home + CString Msg ("\x1B[H\E[?25l"); // cursor home and off // first line Msg.Append (pParam);