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
40 if (valuesOutput.size() != blockSize)
42 HART_WARNING (
"Make sure to configure your envelope container size before processing audio");
43 valuesOutput.resize (blockSize);
46 for (size_t i = 0; i < blockSize; ++i)
48 advance (m_frameTimeSeconds);
49 valuesOutput[i] = m_currentValue;
53 void prepare (
double sampleRateHz, size_t )
override
58 m_frameTimeSeconds = 1.0 / sampleRateHz;
63 m_currentTimeSeconds = 0.0;
64 m_currentSegmentIndex = 0;
65 m_currentValue = m_resetValue;
73 m_segments.push_back (Segment { durationSeconds, m_endValue,
Shape::linear,
true });
83 m_segments.push_back (Segment { durationSeconds, targetValue, shape,
false });
85 m_endValue = targetValue;
98 double durationSeconds;
104 durationSeconds (d), targetValue (t), shape (s), isHold (h) {}
107 const double m_resetValue;
110 std::vector<Segment> m_segments;
112 double m_currentTimeSeconds = 0.0;
113 size_t m_currentSegmentIndex = 0;
114 double m_currentValue;
116 double m_frameTimeSeconds = 1.0 / 44100.0;
118 void advance (
double timeSeconds)
120 m_currentTimeSeconds += timeSeconds;
123 while (m_currentSegmentIndex < m_segments.size())
125 const Segment& currentSegment = m_segments[m_currentSegmentIndex];
127 if (m_currentTimeSeconds < currentSegment.durationSeconds)
129 const double t = m_currentTimeSeconds / currentSegment.durationSeconds;
131 if (currentSegment.isHold)
133 m_currentValue = currentSegment.targetValue;
137 switch (currentSegment.shape)
141 m_currentValue = m_beginValue + (currentSegment.targetValue - m_beginValue) * t;
147 const double ratio = currentSegment.targetValue / m_beginValue;
149 if (std::abs (ratio - 1.0) < 1e-9)
151 m_currentValue = m_beginValue;
155 const bool isFallingCurve = ratio > 1.0;
159 double k = std::log (ratio) / currentSegment.durationSeconds;
160 m_currentValue = m_beginValue * std::exp (k * m_currentTimeSeconds);
164 double k = std::log (1.0 / ratio) / currentSegment.durationSeconds;
165 m_currentValue = m_beginValue * std::exp (-k * m_currentTimeSeconds);
173 const double smoothstep = t * t * (3.0 - 2.0 * t);
174 m_currentValue = m_beginValue + (currentSegment.targetValue - m_beginValue) * smoothstep;
184 m_currentTimeSeconds -= currentSegment.durationSeconds;
185 m_beginValue = currentSegment.targetValue;
186 ++m_currentSegmentIndex;
190 if (m_currentSegmentIndex >= m_segments.size())
191 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.
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)
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
#define HART_WARNING(message)