/* * Author: Harry van Haaren 2013 * harryhaaren@gmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dsp_sidechain_gain.hxx" // for pow() #include SidechainGain::SidechainGain(int rate) : /// initial control values controlThreshold(0.2), controlReduction(1), controlReleaseTime(0.5), /// filter state init w(10.0f / (rate * 0.02)), a(0.07f), b(1.0f / (1.0f - a)), g1(0.0f), g2(0.0f), peakFrameCounter(0), peakCountDuration( rate / 4 ), currentTarget(0) { } void SidechainGain::process(unsigned int n_samples, float** inputs, float** outputs) { /// audio inputs float* inL = inputs[0]; float* inR = inputs[1]; float* side = inputs[2]; float* outL = outputs[0]; float* outR = outputs[1]; /// control inputs float threshold = controlThreshold; float reduction = controlReduction; float releaseTime = controlReleaseTime; /// analyse sidechain input for peak float sum = 0.f; for( unsigned int i = 0; i < n_samples; i++ ) { if ( *side > 0.000001 ) sum += *side++; else sum += -*side++; } currentTarget = 0.f; /// check for peak level (offset to avoid "always on" peak) if ( sum / n_samples > threshold + 0.05 ) { peakFrameCounter = peakCountDuration * releaseTime; currentTarget = 1.f - reduction; } else if ( peakFrameCounter < 0 ) { currentTarget = 1.f; } else { currentTarget = 1.f - reduction; } if ( currentTarget < 0.f ) currentTarget = 0.f; peakFrameCounter -= n_samples; for( unsigned int i = 0; i < n_samples; i++ ) { /// smoothing algo is a lowpass, to de-zip the fades /// x^^4 approximates linear volume increase for human ears g1 += w * ( pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f); g2 += w * (b * g1 - g2 + 1e-20f); float gain = g2; *outL++ = *inL++ * gain; *outR++ = *inR++ * gain; } /// update output value controlSidechainAmp = currentTarget; }