Table of Contents:
Envelope is a curve that controls part of a signal. The most common type of envelope is an Amplitude Envelope, which we will explore in the next section. However any part of a signal can be modulated by an envelope—including frequency, phase, amplitude, and pan.
Envelopes are time based so we have to calculate the current time.
//Envelope Processing
Vst::Sample32* in = data.inputs[0].channelBuffers32[0];
Vst::Sample32* out = data.outputs[0].channelBuffers32[0];
float currentTime = 0.f;
float totalTime = 0.5; //seconds
for (int i = 0; i < data.numSamples; i++) {
float CurrentPos = currentTime / totalTime;
// Attack phase
if (CurrentPos <= mAttackLen) {
envelopeValue = CurrentPos / mAttackLen; // Linear rise from 0 to 1
}
// Decay phase
else if (CurrentPos <= mAttackLen + mDecayLen) {
float decayPos = (CurrentPos - mAttackLen) / mDecayLen;
envelopeValue = 1.0f - decayPos * (1.0f - mSustainLevel); // Decay from 1 to sustain level
}
// Sustain phase
else if (CurrentPos <= mAttackLen + mDecayLen + mSustainLen) {
envelopeValue = mSustainLevel; // Sustain stays constant
}
// Release phase
else if (CurrentPos <= mAttackLen + mDecayLen + mSustainLen + mReleaseLen) {
float releasePos = (CurrentPos - mAttackLen - mDecayLen - mSustainLen) / mReleaseLen;
envelopeValue = mSustainLevel * (1.0f - releasePos); // Release from sustain level to 0
}
// Apply the envelope to the input sample (in[i]) and write it to the output (out[i])
out[i] = in[i] * envelopeValue;
currentTime += 1/data.numSamples;
if (currentTime >= 1.f) {
currentTime = 1.f;
}
}
As you can see, the function defines a curve that will modulate the amplitude based on time. In the attack phase, decay phase, and the release phase. Feel free to use any style of curve instead of the linear style I used here.