ADSR envelope generator
This sketch demonstrates how to make a simple oscillator with different waveforms and how to use the ADSR library to apply an envelope to an audio signal.
The ADSR gate is controlled by a button connected to digital pin 0. When the button is pressed the gate is turned ON and when it is released the gate is turned OFF.
The oscillator has 4 different waveforms available: sinewave, square wave, triangle wave and sawtooth. A button connected to digital pin 1. When the button is pressed the waveform of the oscillator changes. Continuous presses of the button will cycle over the different waveforms.
The frequency of the oscillator and the parameters of the ADSR are fixed to some predefined values in global variables. You can explore how to change these at runtime.
To learn more about ADSRs and how to use the ADSR library, make sure to check Nigel Redmon's fantastic blog: https://www.earlevel.com/main/category/envelope-generators/
#include <cmath>
#include <libraries/ADSR/ADSR.h>
float gAttack = 0.1;
float gDecay = 0.25;
float gRelease = 0.5;
float gSustain = 1.0;
float gFrequency = 320.0;
float gPhase;
float gInverseSampleRate;
enum osc_type
{
sine,
triangle,
square,
sawtooth,
numOscTypes
};
unsigned int gOscType = 0;
float gAmplitude = 0.3f;
int gTriggerButtonPin = 0;
int gTriggerButtonLastStatus = 0;
int gModeButtonPin = 1;
int gModeButtonLastStatus = 0;
{
gPhase = 0.0;
envelope.
setSustainLevel(gSustain);
pinMode(context, 0, gTriggerButtonPin, INPUT);
pinMode(context, 0, gModeButtonPin, INPUT);
return true;
}
{
for(
unsigned int n = 0; n < context->
audioFrames; n++) {
int triggerButtonStatus =
digitalRead(context, n, gTriggerButtonPin);
if(triggerButtonStatus && !gTriggerButtonLastStatus) {
rt_printf("Gate on\n");
} else if (!triggerButtonStatus && gTriggerButtonLastStatus) {
envelope.gate(false);
rt_printf("Gate off\n");
}
gTriggerButtonLastStatus = triggerButtonStatus;
int modeButtonStatus =
digitalRead(context, 0, gModeButtonPin);
if(modeButtonStatus && !gModeButtonLastStatus) {
gOscType += 1;
if(gOscType >= numOscTypes)
gOscType = 0;
rt_printf("Oscillator type: %d\n", gOscType);
}
gModeButtonLastStatus = modeButtonStatus;
float amp = gAmplitude * envelope.
process();
float out;
switch(gOscType) {
default:
case sine:
out = sinf(gPhase);
break;
case triangle:
if (gPhase > 0) {
out = -1 + (2 * gPhase / (float)M_PI);
} else {
out = -1 - (2 * gPhase/ (float)M_PI);
}
break;
case square:
if (gPhase > 0) {
out = 1;
} else {
out = -1;
}
break;
case sawtooth:
out = 1 - (1 / (float)M_PI * gPhase);
break;
}
out = amp * out;
gPhase += 2.0f * (float)M_PI * gFrequency * gInverseSampleRate;
if(gPhase > M_PI)
gPhase -= 2.0f * (float)M_PI;
}
}
}
{
}