81 lines
2.6 KiB
C++
81 lines
2.6 KiB
C++
#include "EnvelopeDisplay.h"
|
|
|
|
namespace serum
|
|
{
|
|
|
|
void EnvelopeDisplay::setParams (float a, float d, float s, float r, float c)
|
|
{
|
|
attack = a; decay = d; sustain = s; release = r; curve = c;
|
|
}
|
|
|
|
void EnvelopeDisplay::paint (juce::Graphics& g)
|
|
{
|
|
const auto b = getLocalBounds().toFloat().reduced (4.0f);
|
|
g.setColour (juce::Colours::black.withAlpha (0.4f));
|
|
g.fillRoundedRectangle (b.expanded (4.0f), 4.0f);
|
|
g.setColour (theme::outline);
|
|
g.drawRoundedRectangle (b.expanded (4.0f).reduced (0.5f), 4.0f, 1.0f);
|
|
|
|
const float atkShape = 0.3f + curve * 2.7f;
|
|
const float decShape = 3.0f - curve * 2.7f;
|
|
|
|
// Normalise durations for display (attack 0..1, decay 0..0.6, release 0..0.6).
|
|
const float aSec = maps::toSeconds (attack);
|
|
const float dSec = maps::toSeconds (decay);
|
|
const float rSec = maps::toSeconds (release);
|
|
const float total = aSec + dSec + rSec + 0.01f;
|
|
const float ax = (aSec / total);
|
|
const float dx = (dSec / total);
|
|
const float rx = (rSec / total);
|
|
|
|
const float left = b.getX();
|
|
const float right = b.getRight();
|
|
const float bottom = b.getBottom();
|
|
const float top = b.getY();
|
|
const float sustainY = bottom - sustain * b.getHeight();
|
|
|
|
juce::Path path;
|
|
path.startNewSubPath (left, bottom);
|
|
path.lineTo (left, top);
|
|
|
|
// Attack (curve-shaped).
|
|
const int steps = 48;
|
|
const float peakX = left + ax * b.getWidth();
|
|
for (int i = 0; i <= steps; ++i)
|
|
{
|
|
const float p = (float) i / steps;
|
|
const float y = top + (bottom - top) * std::pow (p, atkShape);
|
|
path.lineTo (left + p * (peakX - left), y);
|
|
}
|
|
|
|
// Decay to sustain.
|
|
const float decX = peakX + dx * b.getWidth();
|
|
for (int i = 0; i <= steps; ++i)
|
|
{
|
|
const float p = (float) i / steps;
|
|
const float y = sustainY + (bottom - sustainY) * std::pow (1.0f - p, decShape);
|
|
path.lineTo (peakX + p * (decX - peakX), y);
|
|
}
|
|
path.lineTo (decX, sustainY);
|
|
path.lineTo (right - rx * b.getWidth(), sustainY);
|
|
|
|
// Release.
|
|
const float relStartX = right - rx * b.getWidth();
|
|
for (int i = 0; i <= steps; ++i)
|
|
{
|
|
const float p = (float) i / steps;
|
|
const float y = sustainY + (bottom - sustainY) * std::pow (1.0f - p, decShape);
|
|
path.lineTo (relStartX + p * (right - relStartX), y);
|
|
}
|
|
|
|
g.setColour (theme::accent2.withAlpha (0.3f));
|
|
juce::Path fill = path;
|
|
fill.lineTo (right, bottom);
|
|
fill.closeSubPath();
|
|
g.fillPath (fill);
|
|
g.setColour (theme::accent2);
|
|
g.strokePath (path, juce::PathStrokeType (1.5f));
|
|
}
|
|
|
|
} // namespace serum
|