#include "Compressor.h" namespace pascal { void GlueCompressor::prepare (const juce::dsp::ProcessSpec& spec) { sampleRate = spec.sampleRate > 0.0 ? spec.sampleRate : 44100.0; reset(); } void GlueCompressor::reset() { detectorLevel = 0.0f; } void GlueCompressor::processBlock (juce::AudioBuffer& buffer) { const auto numChannels = buffer.getNumChannels(); const auto numSamples = buffer.getNumSamples(); if (numChannels == 0 || numSamples == 0) return; const float inputGain = juce::Decibels::decibelsToGain (juce::jlimit (-60.0f, 60.0f, inputDb)); const float makeupGain = juce::Decibels::decibelsToGain (juce::jlimit (-60.0f, 60.0f, makeupDb)); const float fs = static_cast (sampleRate); const float attackCoef = std::exp (-1.0f / (juce::jmax (0.2f, attackMs) * 0.001f * fs)); const float releaseCoef = std::exp (-1.0f / (juce::jmax (10.0f, releaseMs) * 0.001f * fs)); const float wet = juce::jlimit (0.0f, 1.0f, dryWet); const float dry = 1.0f - wet; const float knee = 6.0f; const float ratioV = juce::jmax (1.0f, ratio); juce::AudioBuffer input; input.makeCopyOf (buffer, true); const auto* inChannels = input.getArrayOfReadPointers(); auto* outChannels = buffer.getArrayOfWritePointers(); for (int n = 0; n < numSamples; ++n) { float detect = 0.0f; for (int c = 0; c < numChannels; ++c) detect += inChannels[c][n]; detect = std::fabs (detect / static_cast (numChannels)) * inputGain; const float coeff = detect > detectorLevel ? (1.0f - attackCoef) : (1.0f - releaseCoef); detectorLevel += coeff * (detect - detectorLevel); const float overDb = juce::Decibels::gainToDecibels (detectorLevel + 1.0e-9f) - thresholdDb; float grDb; if (overDb <= -knee * 0.5f) { grDb = 0.0f; } else if (overDb >= knee * 0.5f) { grDb = -overDb * (1.0f - 1.0f / ratioV); } else { const float q = overDb + knee * 0.5f; grDb = -(q * q / (2.0f * knee)) * (1.0f - 1.0f / ratioV); } const float gain = juce::Decibels::decibelsToGain (juce::jlimit (-80.0f, 24.0f, grDb)) * makeupGain; for (int c = 0; c < numChannels; ++c) { const float in = inChannels[c][n] * inputGain; const float wetSample = in * gain; outChannels[c][n] = c < 2 ? in * dry + wetSample * wet : wetSample; } } } }