diff --git a/src/midi_arp.cpp b/src/midi_arp.cpp index ccddb40..f454afc 100644 --- a/src/midi_arp.cpp +++ b/src/midi_arp.cpp @@ -3,13 +3,18 @@ MidiArp::MidiArp(float32_t samplerate, CDexedAdapter* synth) : MidiEffect(samplerate, synth) { - this->syncMode = 1; - arpeggiator.transmitHostInfo(0, 4, 1, 1, 120.0); arpeggiator.setSampleRate(samplerate); - arpeggiator.setDivision(7); - + arpeggiator.setBpm(120); + + this->setParameter(MidiArp::Param::LATCH, 0); + this->setParameter(MidiArp::Param::ARP_MODE, 0); + this->setParameter(MidiArp::Param::DIVISION, 9); + this->setParameter(MidiArp::Param::NOTE_LENGTH, 70); + this->setParameter(MidiArp::Param::VELOCITY, 110); + this->setParameter(MidiArp::Param::OCTAVE_SPREAD, 1); + this->setParameter(MidiArp::Param::OCTAVE_MODE, 4); } MidiArp::~MidiArp() @@ -41,7 +46,7 @@ void MidiArp::setParameter(unsigned param, unsigned value) this->arpeggiator.setDivision(value); break; case MidiArp::Param::NOTE_LENGTH: - this->arpeggiator.setNoteLength(value); + this->arpeggiator.setNoteLength((float) value / 100.0f); break; case MidiArp::Param::VELOCITY: this->arpeggiator.setVelocity(value); @@ -75,7 +80,7 @@ unsigned MidiArp::getParameter(unsigned param) case MidiArp::Param::DIVISION: return this->arpeggiator.getDivision(); case MidiArp::Param::NOTE_LENGTH: - return this->arpeggiator.getNoteLength(); + return roundf(this->arpeggiator.getNoteLength() * 100); case MidiArp::Param::VELOCITY: return this->arpeggiator.getVelocity(); case MidiArp::Param::OCTAVE_SPREAD: diff --git a/src/midi_arp.h b/src/midi_arp.h index 9f0e7ec..c68820e 100644 --- a/src/midi_arp.h +++ b/src/midi_arp.h @@ -18,7 +18,9 @@ class MidiArp : public MidiEffect { public: - static const unsigned MIDI_EFFECT_ARP = 1; + // ID must be unique for each MidiEffect + static const unsigned ID = 1; + static constexpr const char* NAME = "Arp"; enum Param { @@ -35,20 +37,65 @@ public: UNKNOWN }; + enum Mode + { + UP, + DOWN, + UP_DOWN, + UP_DOWN_ALT, + PLAYED, + RANDOM, + MODE_UNKNOWN + }; + + enum Division + { + D_1_1, + D_1_2, + D_1_3, + D_1_4, + D_1_4D, + D_1_4T, + D_1_8, + D_1_8D, + D_1_8T, + D_1_16, + D_1_16D, + D_1_16T, + D_1_32, + D_UNKNOWN + }; + + enum OctMode + { + OM_UP, + OM_DOWN, + OM_UP_DOWN, + OM_DOWN_UP, + OM_UP_CYCLE, + OM_UNKNOWN + }; + + MidiArp(float32_t samplerate, CDexedAdapter* synth); virtual ~MidiArp(); virtual unsigned getId() { - return MIDI_EFFECT_ARP; + return MidiArp::ID; + } + + virtual std::string getName() + { + return MidiArp::NAME; } virtual void setTempo(unsigned tempo); virtual void setParameter(unsigned param, unsigned value); virtual unsigned getParameter(unsigned param); - void keydown(int16_t pitch, uint8_t velocity); - void keyup(int16_t pitch); + virtual void keydown(int16_t pitch, uint8_t velocity); + virtual void keyup(int16_t pitch); protected: virtual size_t getParametersSize() @@ -63,7 +110,6 @@ private: static const unsigned MIDI_NOTE_ON = 0b1001; Arpeggiator arpeggiator; - int syncMode; std::vector events; }; diff --git a/src/midi_effect_base.h b/src/midi_effect_base.h index 9c9b8b6..accc3dd 100644 --- a/src/midi_effect_base.h +++ b/src/midi_effect_base.h @@ -5,13 +5,16 @@ #ifndef _MIDI_EFFECT_H #define _MIDI_EFFECT_H +#include #include #include "dexedadapter.h" class MidiEffect { public: - static const unsigned MIDI_EFFECT_NONE = 0; + // ID must be unique for each MidiEffect + static const unsigned ID = 0; + static constexpr const char* NAME = "None"; MidiEffect(float32_t samplerate, CDexedAdapter* synth) { @@ -23,19 +26,24 @@ public: { } - void setBypass(bool bypass) + virtual unsigned getId() { - this->bypass = bypass; + return MidiEffect::ID; } - bool getBypass() + virtual std::string getName() { - return bypass; + return MidiEffect::NAME; } - virtual unsigned getId() + void setBypass(bool bypass) { - return MIDI_EFFECT_NONE; + this->bypass = bypass; + } + + bool getBypass() + { + return this->getId() == MidiEffect::ID ? true : this->bypass; } virtual void setTempo(unsigned tempo) @@ -70,9 +78,17 @@ public: return params; } + virtual void keydown(int16_t pitch, uint8_t velocity) + { + } + + virtual void keyup(int16_t pitch) + { + } + void process(uint16_t len) { - if (this->bypass) + if (this->getBypass()) { return; } diff --git a/src/midi_effects.h b/src/midi_effects.h new file mode 100644 index 0000000..a1f2afd --- /dev/null +++ b/src/midi_effects.h @@ -0,0 +1,107 @@ +#ifndef _MIDI_EFFECTS_H +#define _MIDI_EFFECTS_H + +#include "midi_effect_base.h" +#include "midi_arp.h" + +inline MidiEffect* newMidiEffect(unsigned type, float32_t samplerate, CDexedAdapter* synth) +{ + switch (type) + { + case MidiArp::ID: + return new MidiArp(samplerate, synth); + default: + return new MidiEffect(samplerate, synth); + } +} + +inline std::string getMidiFXTypeName(int type) +{ + switch (type) + { + case MidiArp::ID: + return MidiArp::NAME; + case MidiEffect::ID: + default: + return MidiEffect::NAME; + } +} + +inline std::string ToMidiFXType (int value) +{ + return getMidiFXTypeName(value); +} + +inline std::string ToArpDivision (int value) +{ + switch (value) + { + case MidiArp::Division::D_1_1: + return "1/1"; + case MidiArp::Division::D_1_2: + return "1/2"; + case MidiArp::Division::D_1_3: + return "1/3"; + case MidiArp::Division::D_1_4: + return "1/4"; + case MidiArp::Division::D_1_4D: + return "1/4."; + case MidiArp::Division::D_1_4T: + return "1/4T"; + case MidiArp::Division::D_1_8: + return "1/8"; + case MidiArp::Division::D_1_8D: + return "1/8."; + case MidiArp::Division::D_1_8T: + return "1/8T"; + case MidiArp::Division::D_1_16: + return "1/16"; + case MidiArp::Division::D_1_16D: + return "1/16."; + case MidiArp::Division::D_1_16T: + return "1/16T"; + case MidiArp::Division::D_1_32: + default: + return "1/32"; + } +} + +inline std::string ToArpMode (int value) +{ + switch (value) + { + case MidiArp::Mode::UP: + return "Up"; + case MidiArp::Mode::DOWN: + return "Down"; + case MidiArp::Mode::UP_DOWN: + return "Up-Down"; + case MidiArp::Mode::UP_DOWN_ALT: + return "Up-Down Alt"; + case MidiArp::Mode::PLAYED: + return "Played"; + case MidiArp::Mode::RANDOM: + default: + return "Random"; + } +} + +inline std::string ToArpOctMode (int value) +{ + switch (value) + { + case MidiArp::OctMode::OM_UP: + return "Up"; + case MidiArp::OctMode::OM_DOWN: + return "Down"; + case MidiArp::OctMode::OM_UP_DOWN: + return "Up-Down"; + case MidiArp::OctMode::OM_DOWN_UP: + return "Down-Up"; + case MidiArp::OctMode::OM_UP_CYCLE: + default: + return "Up-Cycle"; + } +} + +#endif // _MIDI_EFFECTS_H \ No newline at end of file diff --git a/src/minidexed.cpp b/src/minidexed.cpp index d9fa8c6..6e2f4c9 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -109,7 +109,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()); assert (m_pTG[i]); m_MidiArpSpinLock[i] = new CSpinLock(); - m_MidiArp[i] = new MidiArp(pConfig->GetSampleRate(), m_pTG[i]); + m_MidiArp[i] = new MidiEffect(pConfig->GetSampleRate(), m_pTG[i]); m_pTG[i]->setEngineType(pConfig->GetEngineType ()); m_pTG[i]->activate (); @@ -626,6 +626,24 @@ void CMiniDexed::setInsertFXType (unsigned nType, unsigned nTG) m_UI.ParameterChanged (); } +void CMiniDexed::setMidiFXType (unsigned nType, unsigned nTG) +{ + assert (nTG < CConfig::ToneGenerators); + + // If the effect type is already set just return + if (m_MidiArp[nTG]->getId() == nType) { + return; + } + + m_MidiArpSpinLock[nTG]->Acquire(); + delete m_MidiArp[nTG]; + m_MidiArp[nTG] = newMidiEffect(nType, m_pConfig->GetSampleRate(), m_pTG[nTG]); + m_MidiArp[nTG]->setTempo(m_nTempo); + m_MidiArpSpinLock[nTG]->Release(); + + m_UI.ParameterChanged (); +} + void CMiniDexed::setSendFXType (unsigned nType) { m_SendFXSpinLock.Acquire(); @@ -1073,9 +1091,7 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; case TGParameterInsertFXType: setInsertFXType(nValue, nTG); break; - case TGParameterMidiFXType: - // TODO - break; + case TGParameterMidiFXType: setMidiFXType(nValue, nTG); break; default: assert (0); diff --git a/src/minidexed.h b/src/minidexed.h index 15b786f..160c608 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -41,11 +41,11 @@ #include #include #include "common.h" -#include "midi_arp.h" #include "effect_mixer.hpp" #include "effect_platervbstereo.h" #include "effect_compressor.h" #include "effects.h" +#include "midi_effects.h" class CMiniDexed #ifdef ARM_ALLOW_MULTI_CORE @@ -101,6 +101,7 @@ public: void setAftertouch (uint8_t value, unsigned nTG); void setInsertFXType (unsigned nType, unsigned nTG); + void setMidiFXType (unsigned nType, unsigned nTG); void setSendFXType (unsigned nType); void setSendFXLevel (unsigned nValue); @@ -307,7 +308,7 @@ private: unsigned m_nNoteLimitHigh[CConfig::ToneGenerators]; int m_nNoteShift[CConfig::ToneGenerators]; - MidiArp* m_MidiArp[CConfig::ToneGenerators]; + MidiEffect* m_MidiArp[CConfig::ToneGenerators]; AudioEffect* m_InsertFX[CConfig::ToneGenerators]; unsigned m_nReverbSend[CConfig::ToneGenerators]; diff --git a/src/uimenu.cpp b/src/uimenu.cpp index 50b3916..6a409a8 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -75,7 +75,7 @@ const CUIMenu::TMenuItem CUIMenu::s_TGMenu[] = {"Portamento", MenuHandler, s_EditPortamentoMenu}, {"Poly/Mono", EditTGParameter, 0, CMiniDexed::TGParameterMonoMode}, {"Modulation", MenuHandler, s_ModulationMenu}, - {"Arp", MenuHandler, s_Arp}, + {"Midi FX", MenuHandlerMidiFX}, {"Channel", EditTGParameter, 0, CMiniDexed::TGParameterMIDIChannel}, {"Edit Voice", MenuHandler, s_EditVoiceMenu}, {0} @@ -237,18 +237,31 @@ CUIMenu::TMenuItem CUIMenu::s_FXReverb[] = {0} }; -CUIMenu::TMenuItem CUIMenu::s_Arp[] = -{ - {"Bypass", EditTGArpParameter, 0, MidiArp::Param::BYPASS}, - {"Latch", EditTGArpParameter, 0, MidiArp::Param::LATCH}, - {"Sync", EditTGArpParameter, 0, MidiArp::Param::SYNC}, - {"Arp Mode", EditTGArpParameter, 0, MidiArp::Param::ARP_MODE}, - {"Division", EditTGArpParameter, 0, MidiArp::Param::DIVISION}, - {"Note Length", EditTGArpParameter, 0, MidiArp::Param::NOTE_LENGTH}, - {"Velocity", EditTGArpParameter, 0, MidiArp::Param::VELOCITY}, - {"Oct Spread", EditTGArpParameter, 0, MidiArp::Param::OCTAVE_SPREAD}, - {"Oct Mode", EditTGArpParameter, 0, MidiArp::Param::OCTAVE_MODE}, - {"Panic", EditTGArpParameter, 0, MidiArp::Param::PANIC}, +const CUIMenu::TMenuItem CUIMenu::s_MidiFX[] = +{ + {"Type:", EditTGParameter2, 0, CMiniDexed::TGParameterMidiFXType}, + {"Edit:", EditMidiFX}, + {0} +}; + +CUIMenu::TMenuItem CUIMenu::s_MidiFXNone[] = +{ + {"None"}, + {0} +}; + +CUIMenu::TMenuItem CUIMenu::s_MidiFXArp[] = +{ + {"Bypass", EditTGMidiFXParameter, 0, MidiArp::Param::BYPASS}, + {"Latch", EditTGMidiFXParameter, 0, MidiArp::Param::LATCH}, + {"Sync", EditTGMidiFXParameter, 0, MidiArp::Param::SYNC}, + {"Arp Mode", EditTGMidiFXParameter, 0, MidiArp::Param::ARP_MODE}, + {"Division", EditTGMidiFXParameter, 0, MidiArp::Param::DIVISION}, + {"Note Length", EditTGMidiFXParameter, 0, MidiArp::Param::NOTE_LENGTH}, + {"Velocity", EditTGMidiFXParameter, 0, MidiArp::Param::VELOCITY}, + {"Oct Spread", EditTGMidiFXParameter, 0, MidiArp::Param::OCTAVE_SPREAD}, + {"Oct Mode", EditTGMidiFXParameter, 0, MidiArp::Param::OCTAVE_MODE}, + {"Panic", EditTGMidiFXParameter, 0, MidiArp::Param::PANIC}, {0} }; @@ -347,7 +360,7 @@ const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown] {0, 127, 8, ToVolume}, // TGParameterVolume {0, 127, 8, ToPan}, // TGParameterPan {0, 7, 1, ToFXType}, // TGParameterInsertFXType - {0, 1, 1}, // TGParameterMidiFXType + {0, 1, 1, ToMidiFXType}, // TGParameterMidiFXType {-99, 99, 1}, // TGParameterMasterTune {0, 99, 1}, // TGParameterCutoff {0, 99, 1}, // TGParameterResonance @@ -454,18 +467,18 @@ const CUIMenu::TParameter CUIMenu::s_TGFXReverbParam[AudioEffectPlateReverb::Par }; // must match MidiArp::Param -const CUIMenu::TParameter CUIMenu::s_ArpParam[MidiArp::Param::UNKNOWN] = +const CUIMenu::TParameter CUIMenu::s_TGMidiFXArpParam[MidiArp::Param::UNKNOWN] = { {0, 1, 1, ToOnOff}, // BYPASS - {0, 1, 1}, // LATCH + {0, 1, 1, ToOnOff}, // LATCH {0, 2, 1}, // SYNC - {0, 5, 1}, // ARP_MODE - {0, 12, 1}, // DIVISION + {0, 5, 1, ToArpMode}, // ARP_MODE + {0, 12, 1, ToArpDivision}, // DIVISION {0, 100, 1}, // NOTE_LENGTH {0, 127, 1}, // VELOCITY {1, 4, 1}, // OCTAVE_SPREAD - {0, 4, 1}, // OCTAVE_MODE - {0, 1, 1} // PANIC + {0, 4, 1, ToArpOctMode}, // OCTAVE_MODE + {0, 1, 1, ToOnOff} // PANIC }; // must match DexedVoiceParameters in Synth_Dexed @@ -698,6 +711,93 @@ void CUIMenu::MenuHandler (CUIMenu *pUIMenu, TMenuEvent Event) } } +void CUIMenu::MenuHandlerMidiFX (CUIMenu *pUIMenu, TMenuEvent Event) +{ + // Setup menu when it's open + if (!pUIMenu->m_pCurrentMenu) + { + pUIMenu->m_pCurrentMenu = s_MidiFX; + } + + switch (Event) + { + case MenuEventUpdate: + break; + + case MenuEventSelect: // push menu + assert (pUIMenu->m_nCurrentMenuDepth < MaxMenuDepth); + pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth] = pUIMenu->m_pParentMenu; + pUIMenu->m_MenuStackMenu[pUIMenu->m_nCurrentMenuDepth] = pUIMenu->m_pCurrentMenu; + pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentMenuItem; + pUIMenu->m_nMenuStackSelection[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentSelection; + pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentParameter; + pUIMenu->m_nCurrentMenuDepth++; + + pUIMenu->m_pParentMenu = pUIMenu->m_pCurrentMenu; + pUIMenu->m_nCurrentParameter = + pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter; + pUIMenu->m_pCurrentMenu = + pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].MenuItem; + pUIMenu->m_nCurrentMenuItem = pUIMenu->m_nCurrentSelection; + pUIMenu->m_nCurrentSelection = 0; + break; + + case MenuEventStepDown: + if (pUIMenu->m_nCurrentSelection > 0) + { + pUIMenu->m_nCurrentSelection--; + } + break; + + case MenuEventStepUp: + ++pUIMenu->m_nCurrentSelection; + if (!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name) // more entries? + { + pUIMenu->m_nCurrentSelection--; + } + break; + + case MenuEventPressAndStepDown: + case MenuEventPressAndStepUp: + pUIMenu->TGShortcutHandler (Event); + return; + + default: + return; + } + + if (pUIMenu->m_pCurrentMenu) // if this is another menu? + { + // Identify TG + unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-1]; + // Create TG label + string TG ("TG"); + TG += to_string (nTG+1); + + // Get current FX type + int nFxType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterMidiFXType, nTG); + + // Create Paramter with type label + std::string value; + value.append(pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name); + value.append(getMidiFXTypeName(nFxType)); + + pUIMenu->m_pUI->DisplayWrite ( + TG.c_str (), + pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, + value.c_str(), + pUIMenu->m_nCurrentSelection > 0, + !!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection+1].Name); + } + else + { + pUIMenu->EventHandler (MenuEventUpdate); // no, update parameter display + } +} + void CUIMenu::MenuHandlerInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) { // Setup menu when it's open @@ -1135,12 +1235,12 @@ void CUIMenu::EditTGParameter2 (CUIMenu *pUIMenu, TMenuEvent Event) // second me nValue > rParam.Minimum, nValue < rParam.Maximum); } -void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) +void CUIMenu::EditMidiFX (CUIMenu *pUIMenu, TMenuEvent Event) { unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; - int nFXType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterInsertFXType, nTG); - pUIMenu->m_pCurrentMenu = getInsertFXMenuItem(nFXType); + int nFXType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterMidiFXType, nTG); + pUIMenu->m_pCurrentMenu = getMidiFXMenuItem(nFXType); switch (Event) { @@ -1148,7 +1248,7 @@ void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) break; case MenuEventSelect: // push menu - if (nFXType == 0) + if (nFXType == MidiEffect::ID) { break; } @@ -1198,7 +1298,7 @@ void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) pUIMenu->m_pUI->DisplayWrite ( TG.c_str (), - getFXTypeName(nFXType).c_str(), + getMidiFXTypeName(nFXType).c_str(), pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name, pUIMenu->m_nCurrentSelection > 0, !!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection+1].Name); @@ -1209,17 +1309,17 @@ void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) } } -void CUIMenu::EditTGArpParameter (CUIMenu *pUIMenu, TMenuEvent Event) +void CUIMenu::EditTGMidiFXParameter (CUIMenu *pUIMenu, TMenuEvent Event) { // Get TG - unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; + unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-3]; // Get FX type int nFXType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterMidiFXType, nTG); // Get Param unsigned nParam = pUIMenu->m_nCurrentParameter; - TParameter pParam = s_ArpParam[nParam]; + TParameter pParam = getMidiFXParameter(nFXType, nParam); const TParameter &rParam = pParam; int nValue = pUIMenu->m_pMiniDexed->GetMidiFXParameter (nParam, nTG, nFXType); @@ -1277,6 +1377,80 @@ void CUIMenu::EditTGArpParameter (CUIMenu *pUIMenu, TMenuEvent Event) nValue > rParam.Minimum, nValue < rParam.Maximum); } +void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) +{ + unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; + + int nFXType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterInsertFXType, nTG); + pUIMenu->m_pCurrentMenu = getInsertFXMenuItem(nFXType); + + switch (Event) + { + case MenuEventUpdate: + break; + + case MenuEventSelect: // push menu + if (nFXType == 0) + { + break; + } + assert (pUIMenu->m_nCurrentMenuDepth < MaxMenuDepth); + pUIMenu->m_MenuStackParent[pUIMenu->m_nCurrentMenuDepth] = pUIMenu->m_pParentMenu; + pUIMenu->m_MenuStackMenu[pUIMenu->m_nCurrentMenuDepth] = pUIMenu->m_pCurrentMenu; + pUIMenu->m_nMenuStackItem[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentMenuItem; + pUIMenu->m_nMenuStackSelection[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentSelection; + pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth] + = pUIMenu->m_nCurrentParameter; + pUIMenu->m_nCurrentMenuDepth++; + + pUIMenu->m_pParentMenu = pUIMenu->m_pCurrentMenu; + pUIMenu->m_nCurrentParameter = + pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Parameter; + pUIMenu->m_pCurrentMenu = + pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].MenuItem; + pUIMenu->m_nCurrentMenuItem = pUIMenu->m_nCurrentSelection; + pUIMenu->m_nCurrentSelection = 0; + break; + + case MenuEventStepDown: + if (pUIMenu->m_nCurrentSelection > 0) + { + pUIMenu->m_nCurrentSelection--; + } + break; + + case MenuEventStepUp: + ++pUIMenu->m_nCurrentSelection; + if (!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name) // more entries? + { + pUIMenu->m_nCurrentSelection--; + } + break; + + default: + return; + } + + if (pUIMenu->m_pCurrentMenu) // if this is another menu? + { + string TG ("TG"); + TG += to_string (nTG+1); + + pUIMenu->m_pUI->DisplayWrite ( + TG.c_str (), + getFXTypeName(nFXType).c_str(), + pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection].Name, + pUIMenu->m_nCurrentSelection > 0, + !!pUIMenu->m_pCurrentMenu[pUIMenu->m_nCurrentSelection+1].Name); + } + else + { + pUIMenu->EventHandler (MenuEventUpdate); // no, update parameter display + } +} + void CUIMenu::EditTGFXParameter (CUIMenu *pUIMenu, TMenuEvent Event) { // Get TG @@ -2719,3 +2893,32 @@ CUIMenu::TParameter CUIMenu::getFXParameter(unsigned type, unsigned nParam) } return pParam; } + +CUIMenu::TMenuItem* CUIMenu::getMidiFXMenuItem(unsigned type) +{ + CUIMenu::TMenuItem* menu; + switch (type) + { + case MidiArp::ID: + menu = s_MidiFXArp; + break; + case MidiEffect::ID: + default: + menu = s_MidiFXNone; + break; + } + return menu; +} + +CUIMenu::TParameter CUIMenu::getMidiFXParameter(unsigned type, unsigned nParam) +{ + TParameter pParam; + switch (type) + { + case MidiArp::ID: + pParam = s_TGMidiFXArpParam[nParam]; + default: + break; + } + return pParam; +} \ No newline at end of file diff --git a/src/uimenu.h b/src/uimenu.h index 6c164bd..0700502 100644 --- a/src/uimenu.h +++ b/src/uimenu.h @@ -93,13 +93,18 @@ private: static void SavePerformanceNewFile (CUIMenu *pUIMenu, TMenuEvent Event); static void EditPerformanceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event); + static void MenuHandlerMidiFX (CUIMenu *pUIMenu, TMenuEvent Event); + static void EditMidiFX (CUIMenu *pUIMenu, TMenuEvent Event); + static void EditTGMidiFXParameter (CUIMenu *pUIMenu, TMenuEvent Event); + static CUIMenu::TMenuItem* getMidiFXMenuItem(unsigned type); + static CUIMenu::TParameter getMidiFXParameter(unsigned type, unsigned param); + static CUIMenu::TMenuItem* getFXMenuItem(unsigned type); static CUIMenu::TParameter getFXParameter(unsigned type, unsigned param); static void MenuHandlerInsertFX (CUIMenu *pUIMenu, TMenuEvent Event); static void EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event); static void EditTGFXParameter (CUIMenu *pUIMenu, TMenuEvent Event); - static void EditTGArpParameter (CUIMenu *pUIMenu, TMenuEvent Event); static CUIMenu::TMenuItem* getInsertFXMenuItem(unsigned type); static void MenuHandlerSendFX (CUIMenu *pUIMenu, TMenuEvent Event); @@ -130,7 +135,7 @@ private: static std::string ToFXType (int nValue); static std::string ToMix (int nValue); static std::string ToDelayTime (int nValue); - + void TGShortcutHandler (TMenuEvent Event); void OPShortcutHandler (TMenuEvent Event); @@ -166,6 +171,7 @@ private: static const TMenuItem s_SendFXMenu[]; static const TMenuItem s_ReverbMenu[]; static const TMenuItem s_InsertFX[]; + static const TMenuItem s_MidiFX[]; static TMenuItem s_FXNone[]; static TMenuItem s_FXChorus[]; @@ -176,7 +182,8 @@ private: static TMenuItem s_FXTalReverb3[]; static TMenuItem s_FXReverb[]; - static TMenuItem s_Arp[]; + static TMenuItem s_MidiFXNone[]; + static TMenuItem s_MidiFXArp[]; static const TMenuItem s_EditVoiceMenu[]; static const TMenuItem s_OperatorMenu[]; @@ -197,7 +204,7 @@ private: static const TParameter s_TGFXBigMuffParam[]; static const TParameter s_TGFXTalReverb3Param[]; static const TParameter s_TGFXReverbParam[]; - static const TParameter s_ArpParam[]; + static const TParameter s_TGMidiFXArpParam[]; static const TParameter s_VoiceParameter[]; static const TParameter s_OPParameter[];