Files

81 lines
2.6 KiB
C++

#include "Hyper.h"
namespace serum
{
void HyperUnit::prepare (double sampleRate, int)
{
sr = sampleRate;
lpL.setSampleRate (sr); lpR.setSampleRate (sr);
hpL.setSampleRate (sr); hpR.setSampleRate (sr);
lpL.setLowpass (150.0, 0.7071); lpR.setLowpass (150.0, 0.7071);
hpL.setHighpass (2500.0, 0.7071); hpR.setHighpass (2500.0, 0.7071);
reset();
}
void HyperUnit::reset()
{
lpL.clear(); lpR.clear(); hpL.clear(); hpR.clear();
for (auto& b : bL) { b.env = 0.0f; b.gain = 1.0f; }
for (auto& b : bR) { b.env = 0.0f; b.gain = 1.0f; }
}
float HyperUnit::computeGain (Band& band, float absIn, float intensity) noexcept
{
// Peak envelope follower with fast attack, slower release.
const float attack = (absIn > band.env) ? 0.3f : 0.003f;
band.env += attack * (absIn - band.env);
const float env = band.env + 1e-6f;
const float ratio = 4.0f + 8.0f * intensity;
const float upAmount = intensity * 0.7f;
// Downward compression above the reference level, upward expansion below.
float target;
if (env > 1.0f)
target = 1.0f + (env - 1.0f) / ratio;
else
target = 1.0f - (1.0f - env) * (1.0f - upAmount);
float desired = target / env;
desired = juce::jlimit (0.2f, 4.0f, desired);
band.gain += 0.01f * (desired - band.gain);
return band.gain;
}
void HyperUnit::process (float* l, float* r, int numSamples, const float p[4])
{
const float intensity = p[0];
const float lowAmt = 0.4f + 0.6f * p[1];
const float highAmt = 0.4f + 0.6f * p[2];
const float output = 0.5f + p[3] * 1.0f;
for (int i = 0; i < numSamples; ++i)
{
const float inL = l[i], inR = r[i];
const float loL = lpL.process (inL);
const float restL = inL - loL;
const float hiL = hpL.process (restL);
const float midL = restL - hiL;
const float loR = lpR.process (inR);
const float restR = inR - loR;
const float hiR = hpR.process (restR);
const float midR = restR - hiR;
const float gLL = computeGain (bL[0], std::abs (loL), intensity);
const float gML = computeGain (bL[1], std::abs (midL), intensity);
const float gHL = computeGain (bL[2], std::abs (hiL), intensity);
const float gLR = computeGain (bR[0], std::abs (loR), intensity);
const float gMR = computeGain (bR[1], std::abs (midR), intensity);
const float gHR = computeGain (bR[2], std::abs (hiR), intensity);
l[i] = (loL * gLL * lowAmt + midL * gML + hiL * gHL * highAmt) * output;
r[i] = (loR * gLR * lowAmt + midR * gMR + hiR * gHR * highAmt) * output;
}
}
} // namespace serum