1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-04-29 23:29:41 +02:00

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 <max.maisel@posteo.de>
This commit is contained in:
Max Maisel 2021-02-09 19:38:02 +01:00
parent 90d7c1d226
commit 3d4e504bc3
2 changed files with 47 additions and 15 deletions

View File

@ -131,9 +131,9 @@ float SlidingRmsPreprocessor::ProcessSample(float valueL, float valueR)
return DoProcessSample((valueL * valueL + valueR * valueR) / 2.0); 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; mPos = 0;
mInsertCount = 0; mInsertCount = 0;
std::fill(mWindow.begin(), mWindow.end(), 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); return DoProcessSample((fabs(valueL) + fabs(valueR)) / 2.0);
} }
void SlidingMaxPreprocessor::Reset() void SlidingMaxPreprocessor::Reset(float value)
{ {
mPos = 0; mPos = 0;
std::fill(mWindow.begin(), mWindow.end(), 0); std::fill(mWindow.begin(), mWindow.end(), value);
std::fill(mMaxes.begin(), mMaxes.end(), 0); std::fill(mMaxes.begin(), mMaxes.end(), value);
} }
void SlidingMaxPreprocessor::SetWindowSize(size_t windowSize) void SlidingMaxPreprocessor::SetWindowSize(size_t windowSize)
@ -303,6 +303,13 @@ ExpFitEnvelopeDetector::ExpFitEnvelopeDetector(
SetParams(rate, attackTime, releaseTime); 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( void ExpFitEnvelopeDetector::SetParams(
float sampleRate, float attackTime, float releaseTime) float sampleRate, float attackTime, float releaseTime)
{ {
@ -410,6 +417,14 @@ float Pt1EnvelopeDetector::DecayFactor()
return mReleaseFactor; 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( void Pt1EnvelopeDetector::SetParams(
float sampleRate, float attackTime, float releaseTime) float sampleRate, float attackTime, float releaseTime)
{ {
@ -818,7 +833,7 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
S.StartVerticalLay(); S.StartVerticalLay();
S.AddVariableText(XO("Envelope dependent gain"), 0, S.AddVariableText(XO("Envelope dependent gain"), 0,
wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
mGainPlot = S.MinSize( { 200, 200 } ) mGainPlot = S.MinSize( { 400, 200 } )
.AddPlot({}, -60, 0, -60, 0, XO("dB"), XO("dB"), .AddPlot({}, -60, 0, -60, 0, XO("dB"), XO("dB"),
Ruler::LinearDBFormat, Ruler::LinearDBFormat); Ruler::LinearDBFormat, Ruler::LinearDBFormat);
@ -832,19 +847,19 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
S.EndVerticalLay(); S.EndVerticalLay();
S.StartVerticalLay(); S.StartVerticalLay();
S.AddVariableText(XO("Envelope detector step response"), 0, S.AddVariableText(XO("Compressor step response"), 0,
wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); 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(""), .AddPlot({}, 0, 5, -0.2, 1.2, XO("s"), XO(""),
Ruler::IntFormat, Ruler::RealFormat, 2); 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 = mResponsePlot->GetPlotData(0);
plot->pen = std::unique_ptr<wxPen>( plot->pen = std::unique_ptr<wxPen>(
safenew wxPen(AColor::WideEnvelopePen)); safenew wxPen(AColor::WideEnvelopePen));
plot->xdata = {0, RESPONSE_PLOT_STEP_START, RESPONSE_PLOT_STEP_START, plot->xdata = {0, RESPONSE_PLOT_STEP_START, RESPONSE_PLOT_STEP_START,
RESPONSE_PLOT_STEP_STOP, RESPONSE_PLOT_STEP_STOP, 5}; 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 = mResponsePlot->GetPlotData(1);
plot->pen = std::unique_ptr<wxPen>( plot->pen = std::unique_ptr<wxPen>(
@ -1655,11 +1670,16 @@ void EffectCompressor2::UpdateResponsePlot()
float plot_rate = RESPONSE_PLOT_SAMPLES / RESPONSE_PLOT_TIME; float plot_rate = RESPONSE_PLOT_SAMPLES / RESPONSE_PLOT_TIME;
size_t lookahead_size = CalcLookaheadLength(plot_rate); size_t lookahead_size = CalcLookaheadLength(plot_rate);
lookahead_size -= (lookahead_size > 0);
ssize_t block_size = float(TAU_FACTOR) * (mAttackTime + 1.0) * plot_rate; ssize_t block_size = float(TAU_FACTOR) * (mAttackTime + 1.0) * plot_rate;
InitGainCalculation();
preproc = InitPreprocessor(plot_rate, true); preproc = InitPreprocessor(plot_rate, true);
envelope = InitEnvelope(plot_rate, block_size, 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_start = RESPONSE_PLOT_STEP_START * plot_rate - lookahead_size;
ssize_t step_stop = RESPONSE_PLOT_STEP_STOP * 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) for(ssize_t i = -lookahead_size; i < 2*block_size; ++i)
{ {
if(i < step_start || i > step_stop) if(i < step_start || i > step_stop)
envelope->ProcessSample(preproc->ProcessSample(0)); envelope->ProcessSample(preproc->ProcessSample(0.1));
else else
envelope->ProcessSample(preproc->ProcessSample(1)); envelope->ProcessSample(preproc->ProcessSample(1));
} }
for(ssize_t i = 0; i < xsize; ++i) 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); mResponsePlot->Refresh(false);
} }

View File

@ -29,7 +29,7 @@ class SamplePreprocessor
public: public:
virtual float ProcessSample(float value) = 0; virtual float ProcessSample(float value) = 0;
virtual float ProcessSample(float valueL, float valueR) = 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; virtual void SetWindowSize(size_t windowSize) = 0;
}; };
@ -40,7 +40,7 @@ class SlidingRmsPreprocessor : public SamplePreprocessor
virtual float ProcessSample(float value); virtual float ProcessSample(float value);
virtual float ProcessSample(float valueL, float valueR); virtual float ProcessSample(float valueL, float valueR);
virtual void Reset(); virtual void Reset(float value = 0);
virtual void SetWindowSize(size_t windowSize); virtual void SetWindowSize(size_t windowSize);
static const size_t REFRESH_WINDOW_EVERY = 1048576; // 1 MB 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 value);
virtual float ProcessSample(float valueL, float valueR); virtual float ProcessSample(float valueL, float valueR);
virtual void Reset(); virtual void Reset(float value = 0);
virtual void SetWindowSize(size_t windowSize); virtual void SetWindowSize(size_t windowSize);
private: private:
@ -87,6 +87,7 @@ class EnvelopeDetector
inline float InitialCondition() const { return mInitialCondition; } inline float InitialCondition() const { return mInitialCondition; }
inline size_t InitialConditionSize() const { return mInitialBlockSize; } inline size_t InitialConditionSize() const { return mInitialBlockSize; }
virtual void Reset(float value = 0) = 0;
virtual void SetParams(float sampleRate, float attackTime, virtual void SetParams(float sampleRate, float attackTime,
float releaseTime) = 0; float releaseTime) = 0;
@ -110,6 +111,7 @@ class ExpFitEnvelopeDetector : public EnvelopeDetector
ExpFitEnvelopeDetector(float rate, float attackTime, float releaseTime, ExpFitEnvelopeDetector(float rate, float attackTime, float releaseTime,
size_t buffer_size); size_t buffer_size);
virtual void Reset(float value);
virtual void SetParams(float sampleRate, float attackTime, virtual void SetParams(float sampleRate, float attackTime,
float releaseTime); float releaseTime);
@ -127,6 +129,7 @@ class Pt1EnvelopeDetector : public EnvelopeDetector
size_t buffer_size, bool correctGain = true); size_t buffer_size, bool correctGain = true);
virtual void CalcInitialCondition(float value); virtual void CalcInitialCondition(float value);
virtual void Reset(float value);
virtual void SetParams(float sampleRate, float attackTime, virtual void SetParams(float sampleRate, float attackTime,
float releaseTime); float releaseTime);
virtual float AttackFactor(); virtual float AttackFactor();