#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