53 lines
1.9 KiB
C++
53 lines
1.9 KiB
C++
#include "Compressor.h"
|
|
|
|
namespace serum
|
|
{
|
|
|
|
void CompressorUnit::prepare (double sampleRate, int)
|
|
{
|
|
sr = sampleRate;
|
|
reset();
|
|
}
|
|
|
|
void CompressorUnit::reset()
|
|
{
|
|
envL = envR = 0.0f;
|
|
gainL = gainR = 1.0f;
|
|
}
|
|
|
|
void CompressorUnit::process (float* l, float* r, int numSamples, const float p[4])
|
|
{
|
|
const double thresholdDb = -40.0 + p[0] * 40.0; // -40..0 dB
|
|
const double ratio = 2.0 + p[1] * 18.0; // 2..20
|
|
const double attackMs = 2.0 + p[2] * 98.0;
|
|
const double releaseMs = 30.0 + p[3] * 470.0;
|
|
const double attackCoef = std::exp (-1.0 / (attackMs / 1000.0 * sr));
|
|
const double releaseCoef = std::exp (-1.0 / (releaseMs / 1000.0 * sr));
|
|
const double threshold = std::pow (10.0, thresholdDb / 20.0);
|
|
const double makeup = std::pow (10.0, -thresholdDb * 0.5 / 20.0);
|
|
|
|
for (int i = 0; i < numSamples; ++i)
|
|
{
|
|
const float aL = std::abs (l[i]);
|
|
const float aR = std::abs (r[i]);
|
|
|
|
envL = aL > envL ? (float) (attackCoef * envL + (1.0 - attackCoef) * aL)
|
|
: (float) (releaseCoef * envL + (1.0 - releaseCoef) * aL);
|
|
envR = aR > envR ? (float) (attackCoef * envR + (1.0 - attackCoef) * aR)
|
|
: (float) (releaseCoef * envR + (1.0 - releaseCoef) * aR);
|
|
|
|
const double targetL = (envL > threshold) ? threshold * std::pow (envL / threshold, 1.0 / ratio) : envL;
|
|
const double targetR = (envR > threshold) ? threshold * std::pow (envR / threshold, 1.0 / ratio) : envR;
|
|
const float desiredL = (float) juce::jlimit (0.05, 1.0, (envL > 1e-6) ? targetL / envL : 1.0);
|
|
const float desiredR = (float) juce::jlimit (0.05, 1.0, (envR > 1e-6) ? targetR / envR : 1.0);
|
|
|
|
gainL += 0.01f * (desiredL - gainL);
|
|
gainR += 0.01f * (desiredR - gainR);
|
|
|
|
l[i] = (float) (l[i] * gainL * makeup);
|
|
r[i] = (float) (r[i] * gainR * makeup);
|
|
}
|
|
}
|
|
|
|
} // namespace serum
|