6#include "envelopes/hart_envelope.hpp"
31 m_resetValue (startValue),
32 m_beginValue (startValue),
33 m_endValue (startValue),
34 m_currentValue (startValue)
38 void renderNextBlock (size_t blockSize, std::vector<
double>& valuesOutput)
override
41 if (valuesOutput.size() < blockSize)
43 HART_WARNING (
"Make sure to configure your envelope container size before processing audio");
44 valuesOutput.resize (blockSize);
47 for (size_t i = 0; i < blockSize; ++i)
49 advance (m_frameTimeSeconds);
50 valuesOutput[i] = m_currentValue;
54 void prepare (
double sampleRateHz, size_t )
override
59 m_frameTimeSeconds = 1.0 / sampleRateHz;
64 m_currentTimeSeconds = 0.0;
65 m_currentSegmentIndex = 0;
66 m_currentValue = m_resetValue;
74 m_segments.push_back (Segment { durationSeconds, m_endValue,
Shape::linear,
true });
84 m_segments.push_back (Segment { durationSeconds, targetValue, shape,
false });
86 m_endValue = targetValue;
99 double durationSeconds;
105 durationSeconds (d), targetValue (t), shape (s), isHold (h) {}
108 const double m_resetValue;
111 std::vector<Segment> m_segments;
113 double m_currentTimeSeconds = 0.0;
114 size_t m_currentSegmentIndex = 0;
115 double m_currentValue;
117 double m_frameTimeSeconds = 1.0 / 44100.0;
119 void advance (
double timeSeconds)
121 m_currentTimeSeconds += timeSeconds;
124 while (m_currentSegmentIndex < m_segments.size())
126 const Segment& currentSegment = m_segments[m_currentSegmentIndex];
128 if (m_currentTimeSeconds < currentSegment.durationSeconds)
130 const double t = m_currentTimeSeconds / currentSegment.durationSeconds;
132 if (currentSegment.isHold)
134 m_currentValue = currentSegment.targetValue;
138 switch (currentSegment.shape)
142 m_currentValue = m_beginValue + (currentSegment.targetValue - m_beginValue) * t;
148 const double ratio = currentSegment.targetValue / m_beginValue;
150 if (std::abs (ratio - 1.0) < 1e-9)
152 m_currentValue = m_beginValue;
156 const bool isFallingCurve = ratio > 1.0;
160 double k = std::log (ratio) / currentSegment.durationSeconds;
161 m_currentValue = m_beginValue * std::exp (k * m_currentTimeSeconds);
165 double k = std::log (1.0 / ratio) / currentSegment.durationSeconds;
166 m_currentValue = m_beginValue * std::exp (-k * m_currentTimeSeconds);
174 const double smoothstep = t * t * (3.0 - 2.0 * t);
175 m_currentValue = m_beginValue + (currentSegment.targetValue - m_beginValue) * smoothstep;
185 m_currentTimeSeconds -= currentSegment.durationSeconds;
186 m_beginValue = currentSegment.targetValue;
187 ++m_currentSegmentIndex;
191 if (m_currentSegmentIndex >= m_segments.size())
192 m_currentValue = m_segments.back().targetValue;
Represents an Envelope curve for DSP parameters.
A simple envelope constructed from semgents.
void renderNextBlock(size_t blockSize, std::vector< double > &valuesOutput) override
Shape
Determines a shape of ramp curve.
@ exponential
Exponential curve.
std::unique_ptr< Envelope > copy() const override
Created a copy of the envelope wrapped in a smart pointer.
void prepare(double sampleRateHz, size_t) override
SegmentedEnvelope & rampTo(double targetValue, double durationSeconds, Shape shape=Shape::linear)
Adds a transitional section to the envelope.
SegmentedEnvelope(double startValue)
Creates a segmented envelope instance.
SegmentedEnvelope & hold(double durationSeconds)
Adds a flat horizontal section to the envelope.
Thrown when an inappropriate value is encountered.
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns otherwise.
#define HART_WARNING(message)
Prints a warning message.
std::unique_ptr< ObjectType > make_unique(Args &&... args)
std::make_unique() replacement for C++11
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
#define HART_ENVELOPE_DECLARE_ALIASES_FOR(ClassName)