10namespace tracktion {
inline namespace engine
46 setAttackTime (newParameters.
attack);
47 setDecayTime (newParameters.
decay);
48 setSustainLevel (newParameters.
sustain);
49 setReleaseTime (newParameters.
release);
52 inline void setSampleRate (
double d) { sampleRate = d; }
58 currentState = State::idle;
59 calculateReleaseTime();
64 inline void noteOn() { currentState = State::attack; }
70 currentState = State::release;
72 currentState = State::idle;
76 inline bool isActive()
const {
return currentState != State::idle; }
94 envelopeVal = attackOffset + envelopeVal * attackCoeff;
96 if (envelopeVal >= 1.0f || attackTime <= 0.0f)
99 currentState = State::decay;
106 envelopeVal = decayOffset + envelopeVal * decayCoeff;
108 if (envelopeVal <= sustainLevel || decayTime <= 0.0f)
110 envelopeVal = sustainLevel;
111 currentState = State::sustain;
118 envelopeVal = sustainLevel;
123 envelopeVal = releaseOffset + envelopeVal * releaseCoeff;
125 if (envelopeVal <= 0.0f || releaseTime <= 0.0f)
128 currentState = State::idle;
143 template<
typename FloatType>
150 while (--numSamples >= 0)
154 for (
int i = 0; i < numChannels; ++i)
161 void setAnalog (
bool a)
174 attackTCO = decayTCO = releaseTCO =
std::pow (10.0f, -96.0f / 20.0f);
180 double sampleRate = 44100.0;
182 float envelopeVal = 0.0f;
184 float attackTime = 0.1f, decayTime = 0.1f, releaseTime = 0.1f;
185 float sustainLevel = 0.0f;
187 float attackCoeff = 0.0f, attackOffset = 0.0f, attackTCO {
std::exp (-0.5f)};
188 float decayCoeff = 0.0f, decayOffset = 0.0f, decayTCO {
std::exp (-5.0f)};
189 float releaseCoeff = 0.0f, releaseOffset = 0.0f, releaseTCO {
std::exp (-5.0f)};
193 enum class State { idle, attack, decay, sustain, release };
194 State currentState = State::idle;
196 void calculateAttackTime();
197 void calculateDecayTime();
198 void calculateReleaseTime();
200 inline void setAttackTime (
float d)
205 calculateAttackTime();
209 inline void setDecayTime (
float d)
214 calculateDecayTime();
218 inline void setReleaseTime (
float d)
223 calculateReleaseTime();
227 inline void setSustainLevel (
float d)
232 calculateDecayTime();
233 if (currentState != State::release)
234 calculateReleaseTime();
244 enum class State { idle, attack, decay, sustain, release };
270 currentParameters = newParameters;
272 sustainLevel = newParameters.
sustain;
273 calculateRates (newParameters);
276 void setSampleRate (
double sr) { sampleRate = sr; }
278 float getEnvelopeValue() {
return envelopeVal; }
279 State getState() {
return currentState; }
283 if (attackRate > 0.0f)
285 currentState = State::attack;
287 else if (decayRate > 0.0f)
289 currentState = State::decay;
292 else if (sustainLevel > 0.0f)
294 currentState = State::sustain;
295 envelopeVal = sustainLevel;
297 else if (releaseRate > 0.0f)
299 currentState = State::release;
303 currentState = State::idle;
312 currentState = State::release;
316 currentState = State::idle;
323 currentState = State::idle;
333 if (currentState == State::idle)
336 if (currentState == State::attack)
338 if (attackRate > 0.0f)
339 envelopeVal += attackRate;
343 if (envelopeVal >= 1.0f)
347 if (decayRate > 0.0f)
348 currentState = State::decay;
350 currentState = State::sustain;
353 else if (currentState == State::decay)
355 if (decayRate > 0.0f)
356 envelopeVal -= decayRate;
358 envelopeVal = sustainLevel;
360 if (envelopeVal <= sustainLevel)
362 envelopeVal = sustainLevel;
363 currentState = State::sustain;
366 else if (currentState == State::sustain)
368 envelopeVal = sustainLevel;
370 else if (currentState == State::release)
372 if (releaseRate > 0.0f)
373 envelopeVal -= releaseRate;
377 if (envelopeVal <= 0.0f)
388 template<
typename FloatType>
395 while (--numSamples >= 0)
399 for (
int i = 0; i < numChannels; ++i)
407 void calculateRates (
const Parameters& parameters)
412 attackRate = (parameters.attack > 0.0f ?
static_cast<float> (1.0f / (parameters.attack * sampleRate)) : 0.0f);
413 decayRate = (parameters.decay > 0.0f ?
static_cast<float> (1.0f / (parameters.decay * sampleRate)) : 0.0f);
414 releaseRate = (parameters.release > 0.0f ?
static_cast<float> (1.0f / (parameters.release * sampleRate)) : 0.0f);
417 State currentState = State::idle;
418 Parameters currentParameters;
419 double sampleRate = 44100.0;
420 float envelopeVal = 0.0f;
422 float sustainLevel = 0.0f;
423 float attackRate = 0.0f, decayRate = 0.0f, releaseRate = 0.0f;
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
int getNumSamples() const noexcept
void noteOff()
Starts the release phase of the envelope.
void reset()
Resets the envelope to an idle state.
float release
Release time in seconds.
bool isActive() const
Returns true if the envelope is in its attack, decay, sustain or release stage.
float decay
Decay time in seconds.
float sustain
Sustain level.
float getNextSample()
Returns the next sample value for an ADSR object.
void noteOn()
Starts the attack phase of the envelope.
void applyEnvelopeToBuffer(juce::AudioBuffer< FloatType > &buffer, int startSample, int numSamples)
This method will conveniently apply the next numSamples number of envelope values to an AudioBuffer.
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
float attack
Attack time in seconds.
Holds the parameters being used by an ADSR object.
float decay
Decay time in seconds.
float attack
Attack time in seconds.
float release
Release time in seconds.
void applyEnvelopeToBuffer(juce::AudioBuffer< FloatType > &buffer, int startSample, int numSamples)
This method will conveniently apply the next numSamples number of envelope values to an AudioBuffer.
float sustain
Sustain level.
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
float getNextSample()
Returns the next sample value for an ADSR object.
Holds the parameters being used by an ADSR object.
bool almostEqual(FloatingPointType firstValue, FloatingPointType secondValue, FloatingPointType precision=(FloatingPointType) 0.00001)
Checks to see if two values are equal within a given precision.