34template<
typename T,
int NC = 1>
38 void SetThreshold(
double thresholdDB)
40 mThreshold =
DBToAmp(thresholdDB);
43 void SetSampleRate(
double sampleRate)
45 mSampleRate = sampleRate;
48 void SetAttackTime(
double attackTime)
50 mAttackTime = std::max(attackTime, (1.0 / mSampleRate));
51 mMinRate = std::min(mAttackTime, mReleaseTime);
54 void SetHoldTime(
double holdTime)
56 mHoldTime = std::max(holdTime, (1.0 / mSampleRate));
59 void SetReleaseTime(
double releaseTime)
61 mReleaseTime = std::max(releaseTime, (1.0 / mSampleRate));
62 mMinRate = std::min(mAttackTime, mReleaseTime);
65 void ProcessBlock(T** inputs, T** outputs, T* sidechain,
int nChans,
int nFrames)
69 for (
auto s=0; s <nFrames; s++)
71 auto trigger = sidechain[s];
72 auto gain = processSample(trigger);
73 for (
auto c=0; c<nChans; c++)
75 outputs[c][s] = inputs[c][s] * gain;
81 inline T processSample(T sample)
83 auto ampFollower = [](T x, T& y,
double att,
double rel,
double sr) {
84 auto tau2pole = [](
double tau,
double sr) {
85 return std::exp(-1.0 / (tau * sr));
87 const auto absX = std::abs(x);
88 const auto coeff = (absX > y) ? T(tau2pole(att, sr)) : T(tau2pole(rel, sr));
89 y = (T(1) - coeff) * absX + coeff * y;
93 auto rawGate = ampFollower(sample, mHistory2, mMinRate, mMinRate, mSampleRate) > mThreshold;
95 if (rawGate < mPrevGate)
97 mHoldCounter = int(mHoldTime * mSampleRate);
101 if (mHoldCounter > 0)
107 const auto heldGate = std::max(rawGate, mHoldCounter > 0);
108 const auto smoothed = ampFollower(T(heldGate), mHistory1, mAttackTime, mReleaseTime, mSampleRate);
115 double mThreshold = 0.5;
116 double mSampleRate = 48000.0;
117 double mAttackTime = 0.01f;
118 double mHoldTime = 0.01f;
119 double mReleaseTime = 0.01f;
120 double mMinRate = mAttackTime;
121 T mHistory1, mHistory2 = 0.0f;
122 bool mPrevGate =
false;
123 int mHoldCounter = 0;
Utility functions and macros.
static double DBToAmp(double dB)
Calculates gain from a given dB value.