diff --git a/src/ADSR.cpp b/src/ADSR.cpp index d6ddacb..45998c7 100644 --- a/src/ADSR.cpp +++ b/src/ADSR.cpp @@ -120,7 +120,7 @@ struct ADSR : Module { } float_4 gate[4] = {}; - bool push = params[PUSH_PARAM].getValue(); + bool push = (params[PUSH_PARAM].getValue() > 0.f); for (int c = 0; c < channels; c += 4) { // Gate @@ -201,18 +201,33 @@ struct ADSRDisplay : LedDisplay { void drawLayer(const DrawArgs& args, int layer) override { if (layer == 1) { - Rect r = box.zeroPos().shrink(Vec(2, 4)); - Vec s = r.getTopLeft(); - Vec e = r.getBottomRight(); - float decayX = 20.0; - float releaseX = 80.0; - float releaseY = 40.0; + // Module parameters + float attackLambda = module ? module->attackLambda[0][0] : 1.f; + float decayLambda = module ? module->decayLambda[0][0] : 1.f; + float releaseLambda = module ? module->releaseLambda[0][0] : 1.f; + float sustain = module ? module->sustain[0][0] : 0.5f; + + // Scale lambdas + const float power = 0.5f; + float attack = std::pow(attackLambda, -power); + float decay = std::pow(decayLambda, -power); + float release = std::pow(releaseLambda, -power); + float totalLambda = attack + decay + release; + + Rect r = box.zeroPos().shrink(Vec(4, 5)); + Vec p0 = r.getBottomLeft(); + Vec p1 = r.interpolate(Vec(attack / totalLambda, 0)); + Vec p2 = r.interpolate(Vec((attack + decay) / totalLambda, 1 - sustain)); + Vec p3 = r.getBottomRight(); + Vec attackHandle = Vec(p0.x, crossfade(p0.y, p1.y, 0.8f)); + Vec decayHandle = Vec(p1.x, crossfade(p1.y, p2.y, 0.8f)); + Vec releaseHandle = Vec(p2.x, crossfade(p2.y, p3.y, 0.8f)); nvgBeginPath(args.vg); - nvgMoveTo(args.vg, s.x, e.y); - nvgBezierTo(args.vg, s.x, s.y, decayX, s.y, decayX, s.y); - nvgBezierTo(args.vg, decayX, releaseY, releaseX, releaseY, releaseX, releaseY); - nvgBezierTo(args.vg, releaseX, e.y, e.x, e.y, e.x, e.y); + nvgMoveTo(args.vg, p0.x, p0.y); + nvgBezierTo(args.vg, p0.x, p0.y, attackHandle.x, attackHandle.y, p1.x, p1.y); + nvgBezierTo(args.vg, p1.x, p1.y, decayHandle.x, decayHandle.y, p2.x, p2.y); + nvgBezierTo(args.vg, p2.x, p2.y, releaseHandle.x, releaseHandle.y, p3.x, p3.y); nvgLineCap(args.vg, NVG_ROUND); nvgMiterLimit(args.vg, 2.f); nvgStrokeWidth(args.vg, 1.5f);