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

Implement compressor gain calculation and preview.

Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
Max Maisel 2020-02-15 18:42:06 +01:00
parent ac277c61d7
commit 7326edbefe
2 changed files with 72 additions and 6 deletions

View File

@ -18,6 +18,7 @@
#include "Compressor2.h"
#include <math.h>
#include <numeric>
#include <wx/intl.h>
#include <wx/valgen.h>
@ -270,6 +271,9 @@ void EffectCompressor2::PopulateOrExchange(ShuttleGui & S)
plot = mGainPlot->GetPlotData(0);
plot->pen = std::unique_ptr<wxPen>(
safenew wxPen(AColor::WideEnvelopePen));
plot->xdata.resize(61);
plot->ydata.resize(61);
std::iota(plot->xdata.begin(), plot->xdata.end(), -60);
mResponsePlot = S.MinSize( { 200, 200 } )
.AddPlot({}, 0, 5, -0.2, 1.2, XO("s"), XO(""),
@ -465,6 +469,46 @@ bool EffectCompressor2::TransferDataFromWindow()
// EffectCompressor2 implementation
void EffectCompressor2::InitGainCalculation()
{
mMakeupGainDB = mMakeupGainPct / 100.0 *
-(mThresholdDB * (1.0 - 1.0 / mRatio));
mMakeupGain = DB_TO_LINEAR(mMakeupGainDB);
}
double EffectCompressor2::CompressorGain(double env)
{
double kneeCond;
double envDB = LINEAR_TO_DB(env);
// envDB can become NaN is env is exactly zero.
// As solution, use a very low dB value to prevent NaN propagation.
if(isnan(envDB))
envDB = -200;
kneeCond = 2.0 * (envDB - mThresholdDB);
if(kneeCond < -mKneeWidthDB)
{
// Below threshold: only apply make-up gain
return mMakeupGain;
}
else if(kneeCond >= mKneeWidthDB)
{
// Above threshold: apply compression and make-up gain
return DB_TO_LINEAR(mThresholdDB +
(envDB - mThresholdDB) / mRatio + mMakeupGainDB - envDB);
}
else
{
// Within knee: apply interpolated compression and make-up gain
return DB_TO_LINEAR(
(1.0 / mRatio - 1.0)
* pow(envDB - mThresholdDB + mKneeWidthDB / 2.0, 2)
/ (2.0 * mKneeWidthDB) + mMakeupGainDB);
}
}
void EffectCompressor2::OnUpdateUI(wxCommandEvent & WXUNUSED(evt))
{
if(!mIgnoreGuiEvents)
@ -474,14 +518,30 @@ void EffectCompressor2::OnUpdateUI(wxCommandEvent & WXUNUSED(evt))
void EffectCompressor2::UpdateUI()
{
PlotData* plot;
plot = mGainPlot->GetPlotData(0);
plot->xdata = {-60, -40, 0};
plot->ydata = {-60, -40, -20};
mGainPlot->Refresh(false);
UpdateCompressorPlot();
// TODO: update plots
PlotData* plot;
plot = mResponsePlot->GetPlotData(1);
plot->xdata = {0, 2, 2, 3, 3, 5};
plot->ydata = {0, 0.5, 1, 1, 0.5, 0};
mResponsePlot->Refresh(false);
}
void EffectCompressor2::UpdateCompressorPlot()
{
PlotData* plot;
plot = mGainPlot->GetPlotData(0);
wxASSERT(plot->xdata.size() == plot->ydata.size());
InitGainCalculation();
size_t xsize = plot->xdata.size();
for(size_t i = 0; i < xsize; ++i)
plot->ydata[i] = plot->xdata[i] +
LINEAR_TO_DB(CompressorGain(DB_TO_LINEAR(plot->xdata[i])));
// XXX: accessibility but fails with TranslatableString required
// mGainPlot->SetName(wxString::Format(
// "Compressor gain reduction: %.1f dB", plot->ydata[xsize-1]));
mGainPlot->Refresh(false);
}

View File

@ -58,12 +58,14 @@ public:
private:
// EffectCompressor2 implementation
void InitGainCalculation();
double CompressorGain(double env);
bool UpdateProgress();
void OnUpdateUI(wxCommandEvent & evt);
void UpdateUI();
void UpdateCompressorPlot();
private:
int mAlgorithm;
int mCompressBy;
bool mStereoInd;
@ -78,6 +80,10 @@ private:
double mMakeupGainPct;
double mDryWetPct;
// cached intermediate values
double mMakeupGain;
double mMakeupGainDB;
Plot* mGainPlot;
Plot* mResponsePlot;
bool mIgnoreGuiEvents;