From 7f110b284d74614e3d39a5224072fa6a8b63c4ac Mon Sep 17 00:00:00 2001 From: jnonis Date: Mon, 24 Jun 2024 02:40:47 +0000 Subject: [PATCH] Added generic fx paramters handling --- src/effect_base.cpp | 1 - src/effect_base.h | 9 ++- src/effect_chorus.cpp | 38 +++++++++++ src/effect_chorus.h | 12 ++++ src/effect_delay.cpp | 59 ++++++++++++++--- src/effect_delay.h | 17 ++++- src/effect_lpf.h | 128 +++++++++++++++++++++++++++++-------- src/minidexed.cpp | 123 ++++------------------------------- src/minidexed.h | 10 ++- src/uimenu.cpp | 145 +++++++++++++++++++++++++++++++++++++++--- src/uimenu.h | 6 ++ 11 files changed, 382 insertions(+), 166 deletions(-) diff --git a/src/effect_base.cpp b/src/effect_base.cpp index 22bca6f..f74eb29 100644 --- a/src/effect_base.cpp +++ b/src/effect_base.cpp @@ -24,7 +24,6 @@ unsigned AudioEffect::getId() return EFFECT_NONE; } - void AudioEffect::process(const float32_t* inblock, float32_t* outblock, uint16_t len) { // Mono process diff --git a/src/effect_base.h b/src/effect_base.h index 1e720da..2bc30f3 100644 --- a/src/effect_base.h +++ b/src/effect_base.h @@ -19,8 +19,13 @@ public: bool getBypass(); virtual unsigned getId(); - //virtual void setParameter(unsigned param, unsigned value); - //virtual void getParameter(unsigned param); + virtual void setParameter(unsigned param, unsigned value) + { + } + virtual unsigned getParameter(unsigned param) + { + return 0; + } void process(const float32_t* inblockL, float32_t* outblockL, uint16_t len); void process(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len); diff --git a/src/effect_chorus.cpp b/src/effect_chorus.cpp index e08c7aa..57e8f96 100644 --- a/src/effect_chorus.cpp +++ b/src/effect_chorus.cpp @@ -22,6 +22,44 @@ unsigned AudioEffectChorus::getId() return EFFECT_CHORUS; } +void AudioEffectChorus::setParameter(unsigned param, unsigned value) +{ + switch (param) + { + case AudioEffectChorus::Param::CHORUS_I_ENABLE: + this->setChorusI(value); + break; + case AudioEffectChorus::Param::CHORUS_II_ENABLE: + this->setChorusII(value); + break; + case AudioEffectChorus::Param::CHORUS_I_RATE: + this->setChorusIRate(value); + break; + case AudioEffectChorus::Param::CHORUS_II_RATE: + this->setChorusIIRate(value); + break; + default: + break; + } +} + +unsigned AudioEffectChorus::getParameter(unsigned param) +{ + switch (param) + { + case AudioEffectChorus::Param::CHORUS_I_ENABLE: + return this->getChorusI(); + case AudioEffectChorus::Param::CHORUS_II_ENABLE: + return this->getChorusII(); + case AudioEffectChorus::Param::CHORUS_I_RATE: + return this->getChorusIRate(); + case AudioEffectChorus::Param::CHORUS_II_RATE: + return this->getChorusIIRate(); + default: + return 0; + } +} + void AudioEffectChorus::doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) { for (uint16_t i=0; i < len; i++) diff --git a/src/effect_chorus.h b/src/effect_chorus.h index d3ffb61..c1f221f 100644 --- a/src/effect_chorus.h +++ b/src/effect_chorus.h @@ -7,11 +7,23 @@ class AudioEffectChorus : public AudioEffect { public: + enum Param + { + CHORUS_I_ENABLE, + CHORUS_II_ENABLE, + CHORUS_I_RATE, + CHORUS_II_RATE, + UNKNOWN + }; + AudioEffectChorus(float32_t samplerate); virtual ~AudioEffectChorus(); virtual unsigned getId(); + virtual void setParameter(unsigned param, unsigned value); + virtual unsigned getParameter(unsigned param); + unsigned getChorusI(); void setChorusI(unsigned enable); diff --git a/src/effect_delay.cpp b/src/effect_delay.cpp index 228ce62..906ae0b 100644 --- a/src/effect_delay.cpp +++ b/src/effect_delay.cpp @@ -9,13 +9,14 @@ AudioEffectDelay::AudioEffectDelay(float32_t samplerate) : AudioEffect(samplerat this->bufferL = new float32_t[this->bufferSize]; this->bufferR = new float32_t[this->bufferSize]; this->index = 0; + this->lpf = new AudioEffectLPF(samplerate); + this->lpf->setParameter(AudioEffectLPF::Param::CUTOFF, 80); + this->lpf->setParameter(AudioEffectLPF::Param::RESONANCE, 0); - for (size_t i = 0; i < this->bufferSize; i++) - { - this->bufferL[i] = 0.0f; - this->bufferR[i] = 0.0f; - } - + // Clean buffers + memset(this->bufferL, 0, this->bufferSize * sizeof(float32_t)); + memset(this->bufferR, 0, this->bufferSize * sizeof(float32_t)); + this->timeL = 0.36f; this->timeR = 0.36f; this->feedback = 0.3f; @@ -25,6 +26,7 @@ AudioEffectDelay::~AudioEffectDelay() { delete this->bufferL; delete this->bufferR; + delete this->lpf; } unsigned AudioEffectDelay::getId() @@ -32,6 +34,45 @@ unsigned AudioEffectDelay::getId() return EFFECT_DELAY; } +void AudioEffectDelay::setParameter(unsigned param, unsigned value) +{ + switch (param) + { + case AudioEffectDelay::Param::TIME_L: + this->timeL = (float32_t) value / 1000.0f; + break; + case AudioEffectDelay::Param::TIME_R: + this->timeR = (float32_t) value / 1000.0f; + break; + case AudioEffectDelay::Param::FEEDBACK: + this->feedback = (float32_t) value / 100.0f; + break; + case AudioEffectDelay::Param::TONE: + this->lpf->setParameter(AudioEffectLPF::Param::CUTOFF, value); + break; + default: + break; + } +} + +unsigned AudioEffectDelay::getParameter(unsigned param) +{ + switch (param) + { + case AudioEffectDelay::Param::TIME_L: + return roundf(this->timeL * 1000); + case AudioEffectDelay::Param::TIME_R: + return roundf(this->timeR * 1000); + case AudioEffectDelay::Param::FEEDBACK: + return roundf(this->feedback * 100); + case AudioEffectDelay::Param::TONE: + return this->lpf->getParameter(AudioEffectLPF::Param::CUTOFF); + default: + return 0; + } +} + + void AudioEffectDelay::doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) { for (uint16_t i=0; i < len; i++) @@ -50,9 +91,9 @@ void AudioEffectDelay::doProcess(const float32_t* inblockL, const float32_t* inb offsetR = this->bufferSize + offsetR; } - this->bufferL[index] += this->bufferL[offsetL] * this->feedback; - this->bufferR[index] += this->bufferR[offsetR] * this->feedback; - + this->bufferL[index] += this->lpf->processSampleL(this->bufferL[offsetL]) * this->feedback; + this->bufferR[index] += this->lpf->processSampleR(this->bufferR[offsetR]) * this->feedback; + outblockL[i] = this->bufferL[index]; outblockR[i] = this->bufferR[index]; diff --git a/src/effect_delay.h b/src/effect_delay.h index 43a707b..34e9917 100644 --- a/src/effect_delay.h +++ b/src/effect_delay.h @@ -2,16 +2,28 @@ #define _EFFECT_DELAY_H #include "effect_base.h" - -#define MAX_DELAY_TIME 1 +#include "effect_lpf.h" class AudioEffectDelay : public AudioEffect { public: + static const unsigned MAX_DELAY_TIME = 1; + + enum Param + { + TIME_L, + TIME_R, + FEEDBACK, + TONE, + UNKNOWN + }; + AudioEffectDelay(float32_t samplerate); virtual ~AudioEffectDelay(); virtual unsigned getId(); + virtual void setParameter(unsigned param, unsigned value); + virtual unsigned getParameter(unsigned param); protected: virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len); private: @@ -23,6 +35,7 @@ private: float32_t timeL; // Left delay time in seconds (0.0 - 2.0) float32_t timeR; // Right delay time in seconds (0.0 - 2.0) float32_t feedback; // Feedback (0.0 - 1.0) + AudioEffectLPF* lpf; }; #endif // _EFFECT_DELAY_H \ No newline at end of file diff --git a/src/effect_lpf.h b/src/effect_lpf.h index cf4bf63..9ce0e6d 100644 --- a/src/effect_lpf.h +++ b/src/effect_lpf.h @@ -11,14 +11,37 @@ public: static constexpr float32_t MIN_RES = 0.0f; static constexpr float32_t MAX_RES = 1.0f; + struct LPFState + { + float32_t y1; + float32_t y2; + float32_t y3; + float32_t y4; + float32_t oldx; + float32_t oldy1; + float32_t oldy2; + float32_t oldy3; + }; + + enum Param + { + CUTOFF, + RESONANCE, + UNKNOWN + }; + AudioEffectLPF(float32_t samplerate) : AudioEffect(samplerate) { // Setup init values this->setCutoff(2000.0f); this->setResonance(MIN_RES); + this->stateL = new LPFState(); + this->stateR = new LPFState(); } virtual ~AudioEffectLPF() { + delete this->stateL; + delete this->stateR; } virtual unsigned getId() @@ -26,7 +49,61 @@ public: return EFFECT_LPF; } - /** + virtual void setParameter(unsigned param, unsigned value) + { + switch (param) + { + case AudioEffectLPF::Param::CUTOFF: + this->setCutoff(((float32_t) value / 100.0f) * MAX_CUTOFF); + break; + case AudioEffectLPF::Param::RESONANCE: + this->setResonance((float32_t) value / 100.0f); + break; + default: + break; + } + } + + virtual unsigned getParameter(unsigned param) + { + switch (param) + { + case AudioEffectLPF::Param::CUTOFF: + return roundf((this->cutoff / MAX_CUTOFF) * 100); + case AudioEffectLPF::Param::RESONANCE: + return roundf(this->resonance * 100); + default: + return 0; + } + } + + float32_t processSampleL(float32_t input) + { + return processSample(input, this->stateL); + } + + float32_t processSampleR(float32_t input) + { + return processSample(input, this->stateR); + } + +protected: + virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) + { + for (int i = 0; i < len; i++) { + outblockL[i] = processSampleL(inblockL[i]); + outblockR[i] = processSampleR(inblockR[i]); + } + } + +private: + float32_t cutoff; + float32_t resonance; + float32_t r, p, k; + LPFState* stateL; + LPFState* stateR; + + /** * Set the static cutoff frequency of the filter. * Cutoff frequency must be between MIN_CUTOFF and MAX_CUTOFF. * Envelope signal varies the cutoff frequency from this static value. @@ -56,23 +133,6 @@ public: recalculate(); } -protected: - virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) - { - for (int i = 0; i < len; i++) { - // Get a sample to process - float32_t s = inblockL[i]; - - // Return processed sample from filter - outblockL[i] = processSample(s); - } - } - -private: - float32_t cutoff; - float32_t resonance; - float32_t x, r, p, k, y1, y2, y3, y4, oldx, oldy1, oldy2, oldy3; - /** * Recalculate filter parameters on changes to cutoff or resonance */ @@ -87,14 +147,22 @@ private: r = resonance * (t2 + 6.0 * t) / (t2 - 6.0 * t); } - /** + /** * Process a single sample through the filter */ - float32_t processSample(float32_t input) + float32_t processSample(float32_t input, LPFState* state) { + float32_t y1 = state->y1; + float32_t y2 = state->y2; + float32_t y3 = state->y3; + float32_t y4 = state->y4; + float32_t oldx = state->oldx; + float32_t oldy1 = state->oldy1; + float32_t oldy2 = state->oldy2; + float32_t oldy3 = state->oldy3; + // Process input - //x = ((float32_t) input/ F32_MAX) - r * y4; - x = input - r * y4; + float32_t x = input - r * y4; // Four cascaded one pole filters (bilinear transform) y1 = x * p + oldx * p - k * y1; @@ -105,12 +173,16 @@ private: // Clipper band limited sigmoid y4 -= (y4 * y4 * y4) / 6.0; - oldx = x; - oldy1 = y1; - oldy2 = y2; - oldy3 = y3; - //return (float32_t) (y4 * F32_MAX); - return y4; + state->y1 = y1; + state->y2 = y2; + state->y3 = y3; + state->y4 = y4; + state->oldx = x; + state->oldy1 = y1; + state->oldy2 = y2; + state->oldy3 = y3; + + return y4; } }; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 73e4048..7ac073f 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -946,11 +946,6 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; case TGParameterInsertFXType: setInsertFXType(nValue, nTG); break; - case TGParameterFXChorusI: setChorusIEnable(nTG, nValue); break; - case TGParameterFXChorusII: setChorusIIEnable(nTG, nValue); break; - case TGParameterFXChorusIRate: setChorusIRate(nTG, nValue); break; - case TGParameterFXChorusIIRate: setChorusIIRate(nTG, nValue); break; - default: assert (0); break; @@ -1002,17 +997,26 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) case TGParameterATAmplitude: return getModController(3, 2, nTG); case TGParameterATEGBias: return getModController(3, 3, nTG); - case TGParameterFXChorusI: return getChorusIEnable(nTG); - case TGParameterFXChorusII: return getChorusIIEnable(nTG); - case TGParameterFXChorusIRate: return getChorusIRate(nTG); - case TGParameterFXChorusIIRate: return getChorusIIRate(nTG); - default: assert (0); return 0; } } +void CMiniDexed::SetTGFXParameter (unsigned Parameter, int nValue, unsigned nTG, unsigned nFXType) { + assert (nTG < CConfig::ToneGenerators); + assert (m_InsertFX[nTG]->getId() == nFXType); + + m_InsertFX[nTG]->setParameter(Parameter, nValue); +} + +int CMiniDexed::GetTGFXParameter (unsigned Parameter, unsigned nTG, unsigned nFXType) { + assert (nTG < CConfig::ToneGenerators); + assert (m_InsertFX[nTG]->getId() == nFXType); + + return m_InsertFX[nTG]->getParameter(Parameter);; +} + void CMiniDexed::SetVoiceParameter (uint8_t uchOffset, uint8_t uchValue, unsigned nOP, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); @@ -1982,102 +1986,3 @@ unsigned CMiniDexed::getModController (unsigned controller, unsigned parameter, } -unsigned CMiniDexed::getChorusIEnable (uint8_t nTG) -{ - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - return 0; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - return chorus->getChorusI(); -} - -void CMiniDexed::setChorusIEnable (uint8_t nTG, unsigned enable) -{ - m_InsertFXSpinLock[nTG]->Acquire(); - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - m_InsertFXSpinLock[nTG]->Release(); - return; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - chorus->setChorusI(enable); - m_InsertFXSpinLock[nTG]->Release(); -} - -unsigned CMiniDexed::getChorusIIEnable (uint8_t nTG) -{ - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - return 0; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - return chorus->getChorusII(); -} - -void CMiniDexed::setChorusIIEnable (uint8_t nTG, unsigned enable) -{ - m_InsertFXSpinLock[nTG]->Acquire(); - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - m_InsertFXSpinLock[nTG]->Release(); - return; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - chorus->setChorusII(enable); - m_InsertFXSpinLock[nTG]->Release(); -} - -unsigned CMiniDexed::getChorusIRate (uint8_t nTG) -{ - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - return 0; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - return chorus->getChorusIRate(); -} - -void CMiniDexed::setChorusIRate (uint8_t nTG, unsigned int rate) -{ - m_InsertFXSpinLock[nTG]->Acquire(); - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - m_InsertFXSpinLock[nTG]->Release(); - return; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - chorus->setChorusIRate(rate); - m_InsertFXSpinLock[nTG]->Release(); -} - -unsigned CMiniDexed::getChorusIIRate (uint8_t nTG) -{ - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - return 0; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - return chorus->getChorusIIRate(); -} - -void CMiniDexed::setChorusIIRate (uint8_t nTG, unsigned int rate) -{ - m_InsertFXSpinLock[nTG]->Acquire(); - AudioEffect* effect = m_InsertFX[nTG]; - if (effect->getId() != EFFECT_CHORUS) { - m_InsertFXSpinLock[nTG]->Release(); - return; - } - - AudioEffectChorus* chorus = (AudioEffectChorus*) effect; - chorus->setChorusIIRate(rate); - m_InsertFXSpinLock[nTG]->Release(); -} diff --git a/src/minidexed.h b/src/minidexed.h index e23aa07..0772af8 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -213,18 +213,16 @@ public: TGParameterATPitch, TGParameterATAmplitude, TGParameterATEGBias, - - TGParameterFXChorusI, - TGParameterFXChorusIRate, - TGParameterFXChorusII, - TGParameterFXChorusIIRate, - + TGParameterUnknown }; void SetTGParameter (TTGParameter Parameter, int nValue, unsigned nTG); int GetTGParameter (TTGParameter Parameter, unsigned nTG); + void SetTGFXParameter (unsigned Parameter, int nValue, unsigned nTG, unsigned nFXType); + int GetTGFXParameter (unsigned Parameter, unsigned nTG, unsigned nFXType); + // access (global or OP-related) parameter of the active voice of a TG static const unsigned NoOP = 6; // for global parameters void SetVoiceParameter (uint8_t uchOffset, uint8_t uchValue, unsigned nOP, unsigned nTG); diff --git a/src/uimenu.cpp b/src/uimenu.cpp index 55c0978..f39d7e8 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -152,10 +152,26 @@ const CUIMenu::TMenuItem CUIMenu::s_FXNone[] = const CUIMenu::TMenuItem CUIMenu::s_FXChorus[] = { - {"Chorus I", EditTGParameter2, 0, CMiniDexed::TGParameterFXChorusI}, - {"Chorus II", EditTGParameter2, 0, CMiniDexed::TGParameterFXChorusII}, - {"Rate I", EditTGParameter2, 0, CMiniDexed::TGParameterFXChorusIRate}, - {"Rate II", EditTGParameter2, 0, CMiniDexed::TGParameterFXChorusIIRate}, + {"Chorus I", EditTGFXParameter, 0, AudioEffectChorus::Param::CHORUS_I_ENABLE}, + {"Chorus II", EditTGFXParameter, 0, AudioEffectChorus::Param::CHORUS_II_ENABLE}, + {"Rate I", EditTGFXParameter, 0, AudioEffectChorus::Param::CHORUS_I_RATE}, + {"Rate II", EditTGFXParameter, 0, AudioEffectChorus::Param::CHORUS_II_RATE}, + {0} +}; + +const CUIMenu::TMenuItem CUIMenu::s_FXDelay[] = +{ + {"Time L", EditTGFXParameter, 0, AudioEffectDelay::Param::TIME_L}, + {"Time R", EditTGFXParameter, 0, AudioEffectDelay::Param::TIME_R}, + {"Feedback", EditTGFXParameter, 0, AudioEffectDelay::Param::FEEDBACK}, + {"Tone", EditTGFXParameter, 0, AudioEffectDelay::Param::TONE}, + {0} +}; + +const CUIMenu::TMenuItem CUIMenu::s_FXLPFilter[] = +{ + {"Cutoff", EditTGFXParameter, 0, AudioEffectLPF::Param::CUTOFF}, + {"Resonance", EditTGFXParameter, 0, AudioEffectLPF::Param::RESONANCE}, {0} }; @@ -277,12 +293,32 @@ const CUIMenu::TParameter CUIMenu::s_TGParameter[CMiniDexed::TGParameterUnknown] {0, 99, 1}, //AT Range {0, 1, 1, ToOnOff}, //AT Pitch {0, 1, 1, ToOnOff}, //AT Amp - {0, 1, 1, ToOnOff}, //AT EGBias + {0, 1, 1, ToOnOff} //AT EGBias +}; - {0, 1, 1, ToOnOff}, // TGParameterFXChorusI - {0, 100, 1}, // TGParameterFXChorusIRate - {0, 1, 1, ToOnOff}, // TGParameterFXChorusII - {0, 100, 1}, // TGParameterFXChorusIIRate +// must match AudioEffectChorus::Param +const CUIMenu::TParameter CUIMenu::s_TGFXChorusParam[AudioEffectChorus::Param::UNKNOWN] = +{ + {0, 1, 1, ToOnOff}, // CHORUS_I_ENABLE + {0, 1, 1, ToOnOff}, // CHORUS_II_ENABLE + {0, 100, 1}, // CHORUS_I_RATE, + {0, 100, 1} // CHORUS_II_RATE +}; + +// must match AudioEffectDelay::Param +const CUIMenu::TParameter CUIMenu::s_TGFXDelayParam[AudioEffectDelay::Param::UNKNOWN] = +{ + {0, AudioEffectDelay::MAX_DELAY_TIME * 1000, 1}, // TIME_L + {0, AudioEffectDelay::MAX_DELAY_TIME * 1000, 1}, // TIME_R + {0, 100, 1}, // FEEDBACK, + {0, 100, 1} // TONE +}; + +// must match AudioEffectLPF::Param +const CUIMenu::TParameter CUIMenu::s_TGFXLPFParam[AudioEffectLPF::Param::UNKNOWN] = +{ + {0, 100, 1}, // CUTOFF + {0, 100, 1} // RESONANCE }; // must match DexedVoiceParameters in Synth_Dexed @@ -792,6 +828,14 @@ void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) pUIMenu->m_pCurrentMenu = s_FXChorus; break; + case EFFECT_DELAY: + pUIMenu->m_pCurrentMenu = s_FXDelay; + break; + + case EFFECT_LPF: + pUIMenu->m_pCurrentMenu = s_FXLPFilter; + break; + default: pUIMenu->m_pCurrentMenu = s_FXNone; break; @@ -857,6 +901,89 @@ void CUIMenu::EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event) } } +void CUIMenu::EditTGFXParameter (CUIMenu *pUIMenu, TMenuEvent Event) +{ + // Get TG + unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; + + // Get FX type + int nFXType = pUIMenu->m_pMiniDexed->GetTGParameter(CMiniDexed::TGParameterInsertFXType, nTG); + + // Get Param + unsigned nParam = pUIMenu->m_nCurrentParameter; + TParameter pParam; + switch (nFXType) + { + case EFFECT_CHORUS: + pParam = s_TGFXChorusParam[nParam]; + break; + case EFFECT_DELAY: + pParam = s_TGFXDelayParam[nParam]; + break; + case EFFECT_LPF: + pParam = s_TGFXLPFParam[nParam]; + break; + default: + return; + } + const TParameter &rParam = pParam; + + int nValue = pUIMenu->m_pMiniDexed->GetTGFXParameter (nParam, nTG, nFXType); + + switch (Event) + { + case MenuEventUpdate: + break; + + case MenuEventStepDown: + nValue -= rParam.Increment; + if (nValue < rParam.Minimum) + { + nValue = rParam.Minimum; + } + pUIMenu->m_pMiniDexed->SetTGFXParameter (nParam, nValue, nTG, nFXType); + break; + + case MenuEventStepUp: + nValue += rParam.Increment; + if (nValue > rParam.Maximum) + { + nValue = rParam.Maximum; + } + pUIMenu->m_pMiniDexed->SetTGFXParameter (nParam, nValue, nTG, nFXType); + break; + + case MenuEventPressAndStepDown: + case MenuEventPressAndStepUp: + pUIMenu->TGShortcutHandler (Event); + return; + + default: + return; + } + + string TG ("TG"); + TG += to_string (nTG+1); + + // Get value again after change + nValue = pUIMenu->m_pMiniDexed->GetTGFXParameter (nParam, nTG, nFXType); + CUIMenu::TToString *pToString = rParam.ToString; + string Value; + if (pToString) + { + Value = (*pToString) (nValue); + } + else + { + Value = to_string (nValue); + } + + pUIMenu->m_pUI->DisplayWrite (TG.c_str (), + pUIMenu->m_pParentMenu[pUIMenu->m_nCurrentMenuItem].Name, + Value.c_str (), + nValue > rParam.Minimum, nValue < rParam.Maximum); +} + void CUIMenu::EditVoiceParameter (CUIMenu *pUIMenu, TMenuEvent Event) { unsigned nTG = pUIMenu->m_nMenuStackParameter[pUIMenu->m_nCurrentMenuDepth-2]; diff --git a/src/uimenu.h b/src/uimenu.h index 0baf3ed..9bf6fd3 100644 --- a/src/uimenu.h +++ b/src/uimenu.h @@ -94,6 +94,7 @@ private: static void EditPerformanceBankNumber (CUIMenu *pUIMenu, TMenuEvent Event); static void EditInsertFX (CUIMenu *pUIMenu, TMenuEvent Event); + static void EditTGFXParameter (CUIMenu *pUIMenu, TMenuEvent Event); static std::string GetGlobalValueString (unsigned nParameter, int nValue); static std::string GetTGValueString (unsigned nTGParameter, int nValue); @@ -153,6 +154,8 @@ private: static const TMenuItem s_InsertFX[]; static const TMenuItem s_FXNone[]; static const TMenuItem s_FXChorus[]; + static const TMenuItem s_FXDelay[]; + static const TMenuItem s_FXLPFilter[]; static const TMenuItem s_EditVoiceMenu[]; static const TMenuItem s_OperatorMenu[]; static const TMenuItem s_SaveMenu[]; @@ -165,6 +168,9 @@ private: static const TParameter s_GlobalParameter[]; static const TParameter s_TGParameter[]; + static const TParameter s_TGFXChorusParam[]; + static const TParameter s_TGFXDelayParam[]; + static const TParameter s_TGFXLPFParam[]; static const TParameter s_VoiceParameter[]; static const TParameter s_OPParameter[];