From 3d4e504bc38955f9cc3c1cba39989811b109c5fa Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Tue, 9 Feb 2021 19:38:02 +0100 Subject: [PATCH] Draw full compressor response plot instead of just the envelope detector step response. Also increase minimum plot width for non realtime enabled case. Signed-off-by: Max Maisel --- src/effects/Compressor2.cpp | 53 ++++++++++++++++++++++++++++--------- src/effects/Compressor2.h | 9 ++++--- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/effects/Compressor2.cpp b/src/effects/Compressor2.cpp index 214dd2346..f458bd0bf 100644 --- a/src/effects/Compressor2.cpp +++ b/src/effects/Compressor2.cpp @@ -131,9 +131,9 @@ float SlidingRmsPreprocessor::ProcessSample(float valueL, float valueR) return DoProcessSample((valueL * valueL + valueR * valueR) / 2.0); } -void SlidingRmsPreprocessor::Reset() +void SlidingRmsPreprocessor::Reset(float level) { - mSum = 0; + mSum = (level / mGain) * (level / mGain) * float(mWindow.size()); mPos = 0; mInsertCount = 0; std::fill(mWindow.begin(), mWindow.end(), 0); @@ -203,11 +203,11 @@ float SlidingMaxPreprocessor::ProcessSample(float valueL, float valueR) return DoProcessSample((fabs(valueL) + fabs(valueR)) / 2.0); } -void SlidingMaxPreprocessor::Reset() +void SlidingMaxPreprocessor::Reset(float value) { mPos = 0; - std::fill(mWindow.begin(), mWindow.end(), 0); - std::fill(mMaxes.begin(), mMaxes.end(), 0); + std::fill(mWindow.begin(), mWindow.end(), value); + std::fill(mMaxes.begin(), mMaxes.end(), value); } void SlidingMaxPreprocessor::SetWindowSize(size_t windowSize) @@ -303,6 +303,13 @@ ExpFitEnvelopeDetector::ExpFitEnvelopeDetector( SetParams(rate, attackTime, releaseTime); } +void ExpFitEnvelopeDetector::Reset(float value) +{ + std::fill(mProcessedBuffer.begin(), mProcessedBuffer.end(), value); + std::fill(mProcessingBuffer.begin(), mProcessingBuffer.end(), value); + std::fill(mLookaheadBuffer.begin(), mLookaheadBuffer.end(), value); +} + void ExpFitEnvelopeDetector::SetParams( float sampleRate, float attackTime, float releaseTime) { @@ -410,6 +417,14 @@ float Pt1EnvelopeDetector::DecayFactor() return mReleaseFactor; } +void Pt1EnvelopeDetector::Reset(float value) +{ + value *= mGainCorrection; + std::fill(mProcessedBuffer.begin(), mProcessedBuffer.end(), value); + std::fill(mProcessingBuffer.begin(), mProcessingBuffer.end(), value); + std::fill(mLookaheadBuffer.begin(), mLookaheadBuffer.end(), value); +} + void Pt1EnvelopeDetector::SetParams( float sampleRate, float attackTime, float releaseTime) { @@ -818,7 +833,7 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S) S.StartVerticalLay(); S.AddVariableText(XO("Envelope dependent gain"), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - mGainPlot = S.MinSize( { 200, 200 } ) + mGainPlot = S.MinSize( { 400, 200 } ) .AddPlot({}, -60, 0, -60, 0, XO("dB"), XO("dB"), Ruler::LinearDBFormat, Ruler::LinearDBFormat); @@ -832,19 +847,19 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S) S.EndVerticalLay(); S.StartVerticalLay(); - S.AddVariableText(XO("Envelope detector step response"), 0, + S.AddVariableText(XO("Compressor step response"), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); - mResponsePlot = S.MinSize( { 200, 200 } ) + mResponsePlot = S.MinSize( { 400, 200 } ) .AddPlot({}, 0, 5, -0.2, 1.2, XO("s"), XO(""), Ruler::IntFormat, Ruler::RealFormat, 2); - mResponsePlot->SetName(XO("Envelope detector step response plot")); + mResponsePlot->SetName(XO("Compressor step response plot")); plot = mResponsePlot->GetPlotData(0); plot->pen = std::unique_ptr( safenew wxPen(AColor::WideEnvelopePen)); plot->xdata = {0, RESPONSE_PLOT_STEP_START, RESPONSE_PLOT_STEP_START, RESPONSE_PLOT_STEP_STOP, RESPONSE_PLOT_STEP_STOP, 5}; - plot->ydata = {0, 0, 1, 1, 0, 0}; + plot->ydata = {0.1, 0.1, 1, 1, 0.1, 0.1}; plot = mResponsePlot->GetPlotData(1); plot->pen = std::unique_ptr( @@ -1655,11 +1670,16 @@ void EffectCompressor2::UpdateResponsePlot() float plot_rate = RESPONSE_PLOT_SAMPLES / RESPONSE_PLOT_TIME; size_t lookahead_size = CalcLookaheadLength(plot_rate); + lookahead_size -= (lookahead_size > 0); ssize_t block_size = float(TAU_FACTOR) * (mAttackTime + 1.0) * plot_rate; + InitGainCalculation(); preproc = InitPreprocessor(plot_rate, true); envelope = InitEnvelope(plot_rate, block_size, true); + preproc->Reset(0.1); + envelope->Reset(0.1); + ssize_t step_start = RESPONSE_PLOT_STEP_START * plot_rate - lookahead_size; ssize_t step_stop = RESPONSE_PLOT_STEP_STOP * plot_rate - lookahead_size; @@ -1667,12 +1687,21 @@ void EffectCompressor2::UpdateResponsePlot() for(ssize_t i = -lookahead_size; i < 2*block_size; ++i) { if(i < step_start || i > step_stop) - envelope->ProcessSample(preproc->ProcessSample(0)); + envelope->ProcessSample(preproc->ProcessSample(0.1)); else envelope->ProcessSample(preproc->ProcessSample(1)); } + for(ssize_t i = 0; i < xsize; ++i) - plot->ydata[i] = envelope->ProcessSample(preproc->ProcessSample(0)); + { + float x = 1; + if(i < RESPONSE_PLOT_STEP_START * plot_rate || + i > RESPONSE_PLOT_STEP_STOP * plot_rate) + x = 0.1; + + plot->ydata[i] = x * CompressorGain( + envelope->ProcessSample(preproc->ProcessSample(0.1))); + } mResponsePlot->Refresh(false); } diff --git a/src/effects/Compressor2.h b/src/effects/Compressor2.h index a813a508e..de09581e8 100644 --- a/src/effects/Compressor2.h +++ b/src/effects/Compressor2.h @@ -29,7 +29,7 @@ class SamplePreprocessor public: virtual float ProcessSample(float value) = 0; virtual float ProcessSample(float valueL, float valueR) = 0; - virtual void Reset() = 0; + virtual void Reset(float value = 0) = 0; virtual void SetWindowSize(size_t windowSize) = 0; }; @@ -40,7 +40,7 @@ class SlidingRmsPreprocessor : public SamplePreprocessor virtual float ProcessSample(float value); virtual float ProcessSample(float valueL, float valueR); - virtual void Reset(); + virtual void Reset(float value = 0); virtual void SetWindowSize(size_t windowSize); static const size_t REFRESH_WINDOW_EVERY = 1048576; // 1 MB @@ -63,7 +63,7 @@ class SlidingMaxPreprocessor : public SamplePreprocessor virtual float ProcessSample(float value); virtual float ProcessSample(float valueL, float valueR); - virtual void Reset(); + virtual void Reset(float value = 0); virtual void SetWindowSize(size_t windowSize); private: @@ -87,6 +87,7 @@ class EnvelopeDetector inline float InitialCondition() const { return mInitialCondition; } inline size_t InitialConditionSize() const { return mInitialBlockSize; } + virtual void Reset(float value = 0) = 0; virtual void SetParams(float sampleRate, float attackTime, float releaseTime) = 0; @@ -110,6 +111,7 @@ class ExpFitEnvelopeDetector : public EnvelopeDetector ExpFitEnvelopeDetector(float rate, float attackTime, float releaseTime, size_t buffer_size); + virtual void Reset(float value); virtual void SetParams(float sampleRate, float attackTime, float releaseTime); @@ -127,6 +129,7 @@ class Pt1EnvelopeDetector : public EnvelopeDetector size_t buffer_size, bool correctGain = true); virtual void CalcInitialCondition(float value); + virtual void Reset(float value); virtual void SetParams(float sampleRate, float attackTime, float releaseTime); virtual float AttackFactor();