OpenFrameworks I
May 16 2017
OpenFrameworks: Audio envelopes and visualization.
Looking through the various libraries and add-ons for OpenFrameworks (oF) in relation to audio, there are a lot of useful audio programming add-ons . However it is also one of the points of interest in relation to oF that it allows the construction of low level audio components and generators. So making use of a simple additive synth (taken from a series of tutorial videos on the net: OpenFrameworksAudio) a conceived task was to create a simple envelope. An additional short-term goal was to integrate various graphics components into the process. Other more complex targets would be a series of sound "generators" or "modules". This could include filters and more interesting waveform generators etc.
The first task was an envelope. It is of course trivial to construct an envelope that is triggered from the "keypressed" function in oF. The task is done for you in the "Sound" section of the OF book - contained on their website. A key press triggers a Lerp function that scales the volume according to the parameters that it takes (and the user sets).
Moving on from that the next idea is to create a kind of waveform envelope. This will be familiar to most audio programmers, one simply offsets a sine wave (or another type of wave) by adding 1 to it and scaling it by 0.5. Actually this didn't work so well for me on the first attempt - I found that the wave did not go all the way down to zero. A better solution was to just put an oF fabs method to work on the wave. This produces a floating point absolute number which can then be multiplied with the buffer output array to form an instant envelope. Problem: the envelope continues over and over - thus the next task is to work out a trigger. The trigger must somehow allow for only one half of the duty cycle of the wave to get through and then reset.
A further development was to create a simple AR envelope. This would be an "Attack and Release" series of floats. The first entry point for this is to create a counter that gives (say) 2 seconds of audio as individual samples. The very short buffers of 512 samples each are not really ideal for the longer structures needed for the envelopes. This could be done in many ways: at this point the rudimentary form of an incrementing integer variable was used. The first iteration of this type of envelope involved hard coding a sequence of numbers into "start" and "end" points for the envelope. A simple C++ class was created out of the first iteration. This class allowed the construction of multiple envelopes - for creating a more dense soundscape. The code for the envelope is shown below.
#ifndef Envelopes_h
#define Envelopes_h
#include "ofMain.h"
class envelope{
public:
void envSetup(int start, int aset, int rset);
double envProcess();
bool trigger1=false;
//private:
int AttackStart;
int Aduration;
int ReleaseStart;
int Rduration;
int DurationA;
int counter, counter2, counter3;
double envelope;
};
#endif /* Envelopes_h */
And the implementation file follows below.
#include "Envelopes.h"
#include <cstdio>
void envelope::envSetup(int start, int aset, int rset) {
AttackStart=start;
Rduration=rset;
Aduration=aset;
ReleaseStart=AttackStart+Aduration;
DurationA =AttackStart+Aduration+Rduration;
}
double envelope::envProcess(){
if(counter>=AttackStart&&counter<=ReleaseStart){
counter2++;
envelope=(double)counter2/Aduration;
if(counter2==Aduration){
counter3=Rduration;
//cout<<counter3<<endl;
}
}
else if(counter>=ReleaseStart&&counter<=(ReleaseStart+Rduration))
{
counter3--;
envelope=(double)counter3/Rduration;
//cout<<counter3<<endl;
}
else{
envelope=0.0;
}
counter++;
if(counter>=DurationA){
trigger1=true;
}
if(counter>=(88199)){
trigger1=false;
counter=0;
counter2=0;
counter3=0;
}
//printf("%f \n", envelope);
return envelope;
}
The envelope is obviously very rudimentary. If other programmers are interested in enveloping audio there are many more sophisticated implementations around the web. However this one has the advantage of being structured without any external influence and can be connected to visualization process easily. It suits the role as a starting point.
The duration of the sounds was used in the draw method to attach to the visualization component. The "flows" class, not shown here, is a development of the functions provided in the "Creative Coding Demystified" text (Denis Prevalov). Making those functions into a class with some changes allows for a vector of the objects to be formed. In another piece the coded "flowers" are manipulated via an FFT that changes attributes and coloring of individual objects (flowers) according to the bin they have been assigned. In this experiment a more basic implementation is shown - it will develop alongside the piece. At the moment it is simply a place holder for the graphic component (see video below).
The basic envelope has some shortcomings (for example, it is not optimized and only provides a basic linear ramp), however it is surprisingly useable and in a few short experiments it showed itself able to provide some basic functionality in relation to granulation. The audio example at the bottom of the page is a brief example of a texture built from 300-400 grains triggered per second.
Find below a quick video of the process so far.