diff --git a/src/fx_flanger.cpp b/src/fx_flanger.cpp index 7949100..b8325e2 100644 --- a/src/fx_flanger.cpp +++ b/src/fx_flanger.cpp @@ -2,17 +2,22 @@ #include -Flanger::Flanger(float32_t sampling_rate, float32_t delay_time, float32_t frequency, float32_t depth, float32_t feedback) : +Flanger::Flanger(float32_t sampling_rate, float32_t rate, float32_t depth, float32_t feedback) : FXElement(sampling_rate), - MaxDelayLineSize(static_cast(2.0f * MAX_FLANGER_DELAY * sampling_rate / 1000.0f)), - delay_line_index_(0), - lfo_(sampling_rate, LFO::Waveform::Sine, 0.1f, 10.0f) + MaxDelayLineSize(static_cast(MAX_FLANGER_DELAY * sampling_rate)), + write_index_(0) { this->delay_lineL_ = new float32_t[this->MaxDelayLineSize]; this->delay_lineR_ = new float32_t[this->MaxDelayLineSize]; - this->setDelayTime(delay_time); - this->setFrequency(frequency); + memset(this->delay_lineL_, 0, this->MaxDelayLineSize * sizeof(float32_t)); + memset(this->delay_lineR_, 0, this->MaxDelayLineSize * sizeof(float32_t)); + memset(this->feedback_samples_, 0, 2 * sizeof(float32_t)); + + this->lfo_[LFO_Index::LFO_L] = new LFO(sampling_rate, LFO::Waveform::Sine, 0.1f, 5.0f); + this->lfo_[LFO_Index::LFO_R] = new LFO(sampling_rate, LFO::Waveform::Sine, 0.1f, 5.0f, Constants::MPI_2); + + this->setRate(rate); this->setDepth(depth); this->setFeedback(feedback); } @@ -21,52 +26,96 @@ Flanger::~Flanger() { delete[] this->delay_lineL_; delete[] this->delay_lineR_; -} - -void Flanger::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) -{ - // Calculate the delay time based on the depth and rate parameters - float32_t delay = this->getDelayTime() + this->getDepth() * this->lfo_.process(); - - // Convert the delay time to samples - unsigned delay_samples = static_cast(delay * this->getSamplingRate() / 1000.0f); - // mix the input audio with the delayed audio and the feedback signal - outL = inL + this->delay_lineL_[(this->delay_line_index_ + this->delay_line_size_ - delay_samples) % this->delay_line_size_] * (1.0 - this->getFeedback()); - outR = inR + this->delay_lineR_[(this->delay_line_index_ + this->delay_line_size_ - delay_samples) % this->delay_line_size_] * (1.0 - this->getFeedback()); - - // Update the delay buffer with the mixed audio and the feedback signal - this->delay_lineL_[this->delay_line_index_] = inL + outL * this->getFeedback(); - this->delay_lineR_[this->delay_line_index_] = inR + outR * this->getFeedback(); - - this->delay_line_index_ = (this->delay_line_index_ + 1) % this->delay_line_size_; + delete this->lfo_[LFO_Index::LFO_L]; + delete this->lfo_[LFO_Index::LFO_R]; } -void Flanger::setDelayTime(float32_t delayMS) +inline float32_t linearIterpolationnterp(float32_t inX, float32_t inY, float32_t inPhase) { - this->delay_time_ms_ = constrain(delayMS, 1.0f, MAX_FLANGER_DELAY); - this->adjustDelayCofficients(); + return (1.0f - inPhase) * inX + inPhase * inY; } -float32_t Flanger::getDelayTime() const +void Flanger::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) { - return this->delay_time_ms_; + // Write sample and any feedback into delay buffers + this->delay_lineL_[this->write_index_] = inL + this->feedback_samples_[0]; + this->delay_lineR_[this->write_index_] = inR + this->feedback_samples_[1]; + + ++this->write_index_; + if(this->write_index_ >= this->MaxDelayLineSize) + { + this->write_index_ -= this->MaxDelayLineSize; + } + + // Configure LFO for effect processing + float32_t lfo_l = this->lfo_[LFO_L]->process() * this->depth_; + float32_t lfo_r = this->lfo_[LFO_R]->process() * this->depth_; + + // Map LFO range to millisecond range according to Chorus or Flanger effect + float32_t lfoMappedL = mapfloat(lfo_l, -1.0f, 1.0f, 0.001f, 0.005f); + float32_t lfoMappedR = mapfloat(lfo_r, -1.0f, 1.0f, 0.001f, 0.005f); + + // Calculate delay lengths in samples + float32_t delayTimeSamplesL = this->getSamplingRate() * lfoMappedL; + float32_t delayTimeSamplesR = this->getSamplingRate() * lfoMappedR; + + // Calculate read head positions + float32_t delayReadHeadL = this->write_index_ - delayTimeSamplesL; + if(delayReadHeadL < 0.0f) + { + delayReadHeadL += this->MaxDelayLineSize; + } + float32_t delayReadHeadR = this->write_index_ - delayTimeSamplesR; + if(delayReadHeadR < 0.0f) + { + delayReadHeadR += this->MaxDelayLineSize; + } + + // Calculate linear interpolation point for left channel + int currentL = (int)delayReadHeadL; + int nextL = currentL + 1; + float32_t fractionL = delayReadHeadL - currentL; + if(nextL >= static_cast(this->MaxDelayLineSize)) + { + nextL -= this->MaxDelayLineSize; + } + + // Calculate linear interpolation point for right channel + int currentR = (int)delayReadHeadR; + int nextR = currentR + 1; + float32_t fractionR = delayReadHeadR - currentR; + if(nextR >= static_cast(this->MaxDelayLineSize)) + { + nextR -= this->MaxDelayLineSize; + } + + // Interpolate and read from delay buffer + float32_t delay_sample_l = linearIterpolationnterp(this->delay_lineL_[currentL], this->delay_lineL_[nextL], fractionL); + float32_t delay_sample_r = linearIterpolationnterp(this->delay_lineR_[currentR], this->delay_lineR_[nextR], fractionR); + + // Store delayed samples as feedback + this->feedback_samples_[0] = delay_sample_l * this->feedback_; + this->feedback_samples_[1] = delay_sample_r * this->feedback_; + + outL = delay_sample_l; + outR = delay_sample_r; } -void Flanger::setFrequency(float32_t frequency) +void Flanger::setRate(float32_t rate) { - this->lfo_.setNormalizedFrequency(frequency); + this->lfo_[LFO_Index::LFO_L]->setNormalizedFrequency(rate); + this->lfo_[LFO_Index::LFO_R]->setNormalizedFrequency(rate); } -float32_t Flanger::getFrequency() const +float32_t Flanger::getRate() const { - return this->lfo_.getNormalizedFrequency(); + return this->lfo_[LFO_Index::LFO_L]->getNormalizedFrequency(); } void Flanger::setDepth(float32_t depth) { - this->depth_ = constrain(depth, 0.0f, MAX_FLANGER_DELAY); - this->adjustDelayCofficients(); + this->depth_ = constrain(depth, 0.0f, 1.0f); } float32_t Flanger::getDepth() const @@ -76,15 +125,10 @@ float32_t Flanger::getDepth() const void Flanger::setFeedback(float32_t feedback) { - this->feedback_ = constrain(feedback, 0.0f, 1.0f); + this->feedback_ = constrain(feedback, 0.0f, 0.97f); } float32_t Flanger::getFeedback() const { return this->feedback_; } - -void Flanger::adjustDelayCofficients() -{ - this->delay_line_size_ = static_cast(this->getSamplingRate() * (this->getDelayTime() + this->getDepth()) / 1000.0f); -} diff --git a/src/fx_flanger.h b/src/fx_flanger.h index aea9dc9..6e6377c 100644 --- a/src/fx_flanger.h +++ b/src/fx_flanger.h @@ -20,23 +20,26 @@ #include "fx_components.h" -#define MAX_FLANGER_DELAY 20.0f +#define MAX_FLANGER_DELAY 2.0f class Flanger : public FXElement { DISALLOW_COPY_AND_ASSIGN(Flanger); public: - Flanger(float32_t sampling_rate, float32_t delay_time = 5.0f, float32_t frequency = 0.05f, float32_t depth = 1.0f, float32_t feedback = 0.25f); + enum LFO_Index + { + LFO_L = 0, + LFO_R + }; + + Flanger(float32_t sampling_rate, float32_t rate = 0.5f, float32_t depth = 0.5f, float32_t feedback = 0.0f); virtual ~Flanger(); virtual void processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) override; - void setDelayTime(float32_t delayMS); - float32_t getDelayTime() const; - - void setFrequency(float32_t frequency); - float32_t getFrequency() const; + void setRate(float32_t rate); + float32_t getRate() const; void setDepth(float32_t depth); float32_t getDepth() const; @@ -45,16 +48,13 @@ public: float32_t getFeedback() const; private: - inline void adjustDelayCofficients(); - const unsigned MaxDelayLineSize; - unsigned delay_line_index_; - unsigned delay_line_size_; float32_t* delay_lineL_; float32_t* delay_lineR_; + unsigned write_index_; + float32_t feedback_samples_[2]; - float32_t delay_time_ms_; // Delay time in milliseconds (0.0 - 10.0) - LFO lfo_; + LFO* lfo_[2]; float32_t depth_; // Depth of the flanger effect in milliseconds (0.0 - 10.0) float32_t feedback_; // Amount of feedback to apply to the delay line }; \ No newline at end of file diff --git a/src/minidexed.cpp b/src/minidexed.cpp index fc07eec..3c8774c 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -180,10 +180,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, // FXChain > Flanger parameters this->SetParameter(ParameterFXChainFlangerEnable, 1); this->SetParameter(ParameterFXChainFlangerWet, 50); - this->SetParameter(ParameterFXChainFlangerDelayTime, 10); - this->SetParameter(ParameterFXChainFlangerRate, 15); - this->SetParameter(ParameterFXChainFlangerDepth, 10); - this->SetParameter(ParameterFXChainFlangerFeedback, 20); + this->SetParameter(ParameterFXChainFlangerRate, 3); + this->SetParameter(ParameterFXChainFlangerDepth, 75); + this->SetParameter(ParameterFXChainFlangerFeedback, 50); // FXChain > Orbitone parameters this->SetParameter(ParameterFXChainOrbitoneEnable, 1); @@ -195,7 +194,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, this->SetParameter(ParameterFXChainPhaserEnable, 1); this->SetParameter(ParameterFXChainPhaserWet, 50); this->SetParameter(ParameterFXChainPhaserRate, 5); - this->SetParameter(ParameterFXChainPhaserDepth, 45); + this->SetParameter(ParameterFXChainPhaserDepth, 99); + this->SetParameter(ParameterFXChainPhaserFeedback, 50); + this->SetParameter(ParameterFXChainPhaserNbStages, 12); // FXChain > Delay parameters this->SetParameter(ParameterFXChainDelayEnable, 1); @@ -816,28 +817,22 @@ void CMiniDexed::SetParameter (TParameter Parameter, int nValue) this->fx_rack->getFlanger()->setWetLevel(nValue / 99.0f); this->m_FXSpinLock.Release(); break; - case ParameterFXChainFlangerDelayTime: - nValue = constrain((int)nValue, 0, 99); - this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setDelayTime(mapfloat(nValue, 0, 99, 1.0f, MAX_FLANGER_DELAY)); - this->m_FXSpinLock.Release(); - break; case ParameterFXChainFlangerRate: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setFrequency(nValue / 99.0f); + this->fx_rack->getFlanger()->setRate(nValue / 99.0f); this->m_FXSpinLock.Release(); break; case ParameterFXChainFlangerDepth: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setDepth(mapfloat(nValue, 0, 99, 0.0f, MAX_FLANGER_DELAY)); + this->fx_rack->getFlanger()->setDepth(nValue / 99.0f); this->m_FXSpinLock.Release(); break; case ParameterFXChainFlangerFeedback: nValue = constrain((int)nValue, 0, 99); this->m_FXSpinLock.Acquire(); - this->fx_rack->getFlanger()->setFeedback(nValue / 99.0f); + this->fx_rack->getFlanger()->setFeedback(mapfloat(nValue, 0, 99, 0.0f, 0.97f)); this->m_FXSpinLock.Release(); break; @@ -1407,7 +1402,6 @@ bool CMiniDexed::DoSavePerformance (void) this->m_PerformanceConfig.SetFXChainChorusDepth(this->m_nParameter[ParameterFXChainChorusDepth]); this->m_PerformanceConfig.SetFXChainFlangerEnable(!!this->m_nParameter[ParameterFXChainFlangerEnable]); this->m_PerformanceConfig.SetFXChainFlangerWet(this->m_nParameter[ParameterFXChainFlangerWet]); - this->m_PerformanceConfig.SetFXChainFlangerDelayTime(this->m_nParameter[ParameterFXChainFlangerDelayTime]); this->m_PerformanceConfig.SetFXChainFlangerRate(this->m_nParameter[ParameterFXChainFlangerRate]); this->m_PerformanceConfig.SetFXChainFlangerDepth(this->m_nParameter[ParameterFXChainFlangerDepth]); this->m_PerformanceConfig.SetFXChainFlangerFeedback(this->m_nParameter[ParameterFXChainFlangerFeedback]); @@ -1836,7 +1830,6 @@ void CMiniDexed::LoadPerformanceParameters(void) this->SetParameter(ParameterFXChainChorusDepth, this->m_PerformanceConfig.GetFXChainChorusDepth()); this->SetParameter(ParameterFXChainFlangerEnable, this->m_PerformanceConfig.GetFXChainFlangerEnable()); this->SetParameter(ParameterFXChainFlangerWet, this->m_PerformanceConfig.GetFXChainFlangerWet()); - this->SetParameter(ParameterFXChainFlangerDelayTime, this->m_PerformanceConfig.GetFXChainFlangerDelayTime()); this->SetParameter(ParameterFXChainFlangerRate, this->m_PerformanceConfig.GetFXChainFlangerRate()); this->SetParameter(ParameterFXChainFlangerDepth, this->m_PerformanceConfig.GetFXChainFlangerDepth()); this->SetParameter(ParameterFXChainFlangerFeedback, this->m_PerformanceConfig.GetFXChainFlangerFeedback()); diff --git a/src/minidexed.h b/src/minidexed.h index 728d69a..f54d09d 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -160,7 +160,6 @@ public: // FXChain > Flanger parameters ParameterFXChainFlangerEnable, ParameterFXChainFlangerWet, - ParameterFXChainFlangerDelayTime, ParameterFXChainFlangerRate, ParameterFXChainFlangerDepth, ParameterFXChainFlangerFeedback, diff --git a/src/performance.ini b/src/performance.ini index 332874f..7a61480 100644 --- a/src/performance.ini +++ b/src/performance.ini @@ -295,10 +295,9 @@ FXChainChorusRate=40 FXChainChorusDepth=50 FXChainFlangerEnable=0 FXChainFlangerWet=50 -FXChainFlangerDelayTime=10 -FXChainFlangerRate=15 -FXChainFlangerDepth=10 -FXChainFlangerFeedback=20 +FXChainFlangerRate=3 +FXChainFlangerDepth=75 +FXChainFlangerFeedback=50 FXChainOrbitoneEnable=0 FXChainOrbitoneWet=80 FXChainOrbitoneRate=40 diff --git a/src/performanceconfig.cpp b/src/performanceconfig.cpp index dc17b19..419d389 100644 --- a/src/performanceconfig.cpp +++ b/src/performanceconfig.cpp @@ -171,7 +171,6 @@ bool CPerformanceConfig::Load (void) this->m_nFXChainChorusDepth = this->m_Properties.GetNumber("FXChainChorusDepth", 50); this->m_bFXChainFlangerEnable = this->m_Properties.GetNumber("FXChainFlangerEnable", 1); this->m_nFXChainFlangerWet = this->m_Properties.GetNumber("FXChainFlangerWet", 50); - this->m_nFXChainFlangerDelayTime = this->m_Properties.GetNumber("FXChainFlangerDelayTime", 10); this->m_nFXChainFlangerRate = this->m_Properties.GetNumber("FXChainFlangerRate", 15); this->m_nFXChainFlangerDepth = this->m_Properties.GetNumber("FXChainFlangerDepth", 10); this->m_nFXChainFlangerFeedback = this->m_Properties.GetNumber("FXChainFlangerFeedback", 20); @@ -328,7 +327,6 @@ bool CPerformanceConfig::Save (void) this->m_Properties.SetNumber("FXChainChorusDepth", m_nFXChainChorusDepth); this->m_Properties.SetNumber("FXChainFlangerEnable", m_bFXChainFlangerEnable ? 1 : 0); this->m_Properties.SetNumber("FXChainFlangerWet", m_nFXChainFlangerWet); - this->m_Properties.SetNumber("FXChainFlangerDelayTime", m_nFXChainFlangerDelayTime); this->m_Properties.SetNumber("FXChainFlangerRate", m_nFXChainFlangerRate); this->m_Properties.SetNumber("FXChainFlangerDepth", m_nFXChainFlangerDepth); this->m_Properties.SetNumber("FXChainFlangerFeedback", m_nFXChainFlangerFeedback); @@ -1058,11 +1056,6 @@ unsigned CPerformanceConfig::GetFXChainFlangerWet(void) const return this->m_nFXChainFlangerWet; } -unsigned CPerformanceConfig::GetFXChainFlangerDelayTime(void) const -{ - return this->m_nFXChainFlangerDelayTime; -} - unsigned CPerformanceConfig::GetFXChainFlangerRate(void) const { return this->m_nFXChainFlangerRate; @@ -1238,11 +1231,6 @@ void CPerformanceConfig::SetFXChainFlangerWet(unsigned nValue) this->m_nFXChainFlangerWet = nValue; } -void CPerformanceConfig::SetFXChainFlangerDelayTime(unsigned nValue) -{ - this->m_nFXChainFlangerDelayTime = nValue; -} - void CPerformanceConfig::SetFXChainFlangerRate(unsigned nValue) { this->m_nFXChainFlangerRate = nValue; diff --git a/src/performanceconfig.h b/src/performanceconfig.h index 6ec286f..4cd7790 100644 --- a/src/performanceconfig.h +++ b/src/performanceconfig.h @@ -129,7 +129,6 @@ public: unsigned GetFXChainChorusDepth(void) const; bool GetFXChainFlangerEnable(void) const; unsigned GetFXChainFlangerWet(void) const; - unsigned GetFXChainFlangerDelayTime(void) const; unsigned GetFXChainFlangerRate(void) const; unsigned GetFXChainFlangerDepth(void) const; unsigned GetFXChainFlangerFeedback(void) const; @@ -166,7 +165,6 @@ public: void SetFXChainChorusDepth(unsigned nValue); void SetFXChainFlangerEnable(bool bValue); void SetFXChainFlangerWet(unsigned nValue); - void SetFXChainFlangerDelayTime(unsigned nValue); void SetFXChainFlangerRate(unsigned nValue); void SetFXChainFlangerDepth(unsigned nValue); void SetFXChainFlangerFeedback(unsigned nValue); @@ -272,7 +270,6 @@ private: unsigned m_nFXChainChorusDepth; bool m_bFXChainFlangerEnable; unsigned m_nFXChainFlangerWet; - unsigned m_nFXChainFlangerDelayTime; unsigned m_nFXChainFlangerRate; unsigned m_nFXChainFlangerDepth; unsigned m_nFXChainFlangerFeedback; diff --git a/src/test/fxrack_test.cpp b/src/test/fxrack_test.cpp index eb0edb7..9e75e3c 100644 --- a/src/test/fxrack_test.cpp +++ b/src/test/fxrack_test.cpp @@ -142,8 +142,8 @@ void testFXRack(unsigned& step, unsigned fxSwitch) rack->setWetLevel(1.0f); rack->getTube()->setEnable(Active(fxSwitch, FXSitch::Tube)); - rack->getTube()->setWetLevel(1.0f); - rack->getTube()->setOverdrive(1.0f); + rack->getTube()->setWetLevel(0.25f); + rack->getTube()->setOverdrive(0.25f); rack->getChorus()->setEnable(Active(fxSwitch, FXSitch::Chorus)); rack->getChorus()->setWetLevel(0.5f); @@ -154,7 +154,8 @@ void testFXRack(unsigned& step, unsigned fxSwitch) rack->getPhaser()->setWetLevel(1.0f); rack->getPhaser()->setRate(0.1f); rack->getPhaser()->setDepth(1.0f); - rack->getPhaser()->setFeedback(0.75f); + rack->getPhaser()->setFeedback(0.5f); + rack->getPhaser()->setNbStages(12); rack->getOrbitone()->setEnable(Active(fxSwitch, FXSitch::Orbitone)); rack->getOrbitone()->setWetLevel(0.8f); @@ -163,10 +164,9 @@ void testFXRack(unsigned& step, unsigned fxSwitch) rack->getFlanger()->setEnable(Active(fxSwitch, FXSitch::Flanger)); rack->getFlanger()->setWetLevel(0.5f); - rack->getFlanger()->setDelayTime(0.8f); - rack->getFlanger()->setFrequency(0.25f); - rack->getFlanger()->setDepth(0.8f); - rack->getFlanger()->setFeedback(0.75f); + rack->getFlanger()->setRate(0.03f); + rack->getFlanger()->setDepth(0.75f); + rack->getFlanger()->setFeedback(0.5f); rack->getDelay()->setEnable(Active(fxSwitch, FXSitch::Delay)); rack->getDelay()->setWetLevel(0.6f); @@ -175,8 +175,8 @@ void testFXRack(unsigned& step, unsigned fxSwitch) rack->getDelay()->setFeedbak(0.5f); rack->getShimmerReverb()->setEnable(Active(fxSwitch, FXSitch::Shimmer)); - rack->getShimmerReverb()->setWetLevel(0.7f); - rack->getShimmerReverb()->setInputGain(0.45f); + rack->getShimmerReverb()->setWetLevel(0.5f); + rack->getShimmerReverb()->setInputGain(0.35f); rack->getShimmerReverb()->setTime(0.89f); rack->getShimmerReverb()->setDiffusion(0.75f); rack->getShimmerReverb()->setLP(0.8f); @@ -215,12 +215,21 @@ int main() // testFlutter(step); // testSVF(step); // testFXRack(step, FXSitch::Tube); - // testFXRack(step, FXSitch::Flanger); // to be fixed -> feedback deletes FX effect - testFXRack(step, FXSitch::Phaser); + // testFXRack(step, FXSitch::Flanger); + // testFXRack(step, FXSitch::Phaser); // testFXRack(step, FXSitch::Chorus); // testFXRack(step, FXSitch::Orbitone); // testFXRack(step, FXSitch::Delay); // testFXRack(step, FXSitch::Shimmer); + testFXRack( + step, + FXSitch::Tube | + FXSitch::Chorus | + FXSitch::Flanger | + FXSitch::Orbitone | + FXSitch::Phaser | + FXSitch::Delay | + FXSitch::Shimmer); return 0; } diff --git a/src/uimenu.cpp b/src/uimenu.cpp index 6507979..f94f969 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -177,7 +177,6 @@ const CUIMenu::TMenuItem CUIMenu::s_FXChainFlanger[] = { {"Enable", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerEnable}, {"Wet Lvl", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerWet}, - {"Delay", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerDelayTime}, {"Rate", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerRate}, {"Depth", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerDepth}, {"Feedbck", EditGlobalParameter, 0, CMiniDexed::ParameterFXChainFlangerFeedback}, @@ -327,7 +326,6 @@ const CUIMenu::TParameter CUIMenu::s_GlobalParameter[CMiniDexed::ParameterUnknow // FXChain > Flanger parameters {0, 1, 1, ToOnOff}, // ParameterFXChainFlangerEnable {0, 99, 1}, // ParameterFXChainFlangerWet - {0, 99, 1}, // ParameterFXChainFlangerDelayTime {0, 99, 1}, // ParameterFXChainFlangerRate {0, 99, 1}, // ParameterFXChainFlangerDepth {0, 99, 1}, // ParameterFXChainFlangerFeedback