#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