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 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.
#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) {
envelope.gate(true);
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;
}
}
}
{
}
static int digitalRead(BelaContext *context, int frame, int channel)
Read a digital input, specifying the frame number (when to read) and the pin.
Definition Bela.h:1518
static void audioWrite(BelaContext *context, int frame, int channel, float value)
Write an audio output, specifying the frame number (when to write) and the channel.
Definition Bela.h:1469
static void pinMode(BelaContext *context, int frame, int channel, int mode)
Set the direction of a digital pin to input or output.
Definition Bela.h:1548
void render(BelaContext *context, void *userData)
User-defined callback function to process audio and sensor data.
Definition render.cpp:68
bool setup(BelaContext *context, void *userData)
User-defined initialisation function which runs before audio rendering begins.
Definition render.cpp:51
void cleanup(BelaContext *context, void *userData)
User-defined cleanup function which runs when the program finishes.
Definition render.cpp:96
Structure holding audio and sensor settings and pointers to I/O data buffers.
Definition Bela.h:231
const uint32_t audioOutChannels
The number of audio output channels.
Definition Bela.h:326
const uint32_t audioFrames
The number of audio frames per block.
Definition Bela.h:322
const float audioSampleRate
The audio sample rate in Hz (currently always 44100.0).
Definition Bela.h:328