mirror of
https://codeberg.org/armin/pascalcompressor.git
synced 2026-10-11 16:51:56 +02:00
80 lines
No EOL
2.5 KiB
C++
80 lines
No EOL
2.5 KiB
C++
#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<float>& 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<float> (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<float> 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<float> (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;
|
|
}
|
|
}
|
|
}
|
|
|
|
} |