SynthLab SDK
EnvelopeGenerator

Next we will create the SynthLab::EnvelopeGenerator object that is also derived from SynthModule.

You will need to add the following files for the EnvelopeGenerator:

Follow the same pattern and start with the class documentation. The AnalogEG:

  • uses a EGParameters structure for control, both GUI and programatically
  • renders values into the ModulationOutput array
  • includes 3 EG cores: AnalogEGCore, DXEGCore, and LinearEGCore

We'll go with the default AnalogEGCore object and jump to its documentation. There we can find the module strings and mod knob assignments. The ModuleStrings are the EG contours.

Module Strings, zero-indexed for your GUI Control:

  • ADSR, AR

We will choose the familiar ADSR contour, which as a zero-indexed string entry is [0]. Next, look at the documentation to find the output data (render) location

From the docs on AnalogEGCore:

  • kEGNormalOutput normal EG output value
  • kEGBiasedOutput biased EG (sustain level subtracted out)

Note that the documentation also shows you how to create the object in standalone mode, as with the LFO:

// --- standalone construction, block size = 64
EnvelopeGenerator(nullptr, nullptr, 64);
//

So, we will do the following:

  1. create the EG and pass nullptr for the MIDI input and parameters arguments
  2. reset it with the sample rate
  3. use getParameters: set the ADSR times in milliseconds
  4. create a MIDI event and call the note-on handler
  5. call the render function repeatedly to render a new output value, get the outout from the ModulationOutput array
  6. call the note-off handler when note event is done
// --- create a EG via shared pointer; here is the definition
std::unique_ptr<SynthLab::EnvelopeGenerator> eg = nullptr;
// --- here is the creation
eg.reset(new SynthLab::EnvelopeGenerator(nullptr, /* MIDI input data */
nullptr, /* LFO parameters */
1)); /* process individual samples (block size = 1)*/
// --- initialize
eg->reset(44100.0); //<- get fs from your framework
// --- get the parameter struct pointer;
// it was synthesized when we passed a nullptr into the constructor
std::shared_ptr<SynthLab::EGParameters> egParameters = eg->getParameters();
if (egParameters) // should never fail
{
// --- set the variables
egParameters->attackTime_mSec = 50.0;
egParameters->decayTime_mSec = 100.0;
egParameters->sustainLevel = 0.707;
egParameters->releaseTime_mSec = 1000.0;
// --- call the update function (only needs to be done once per render cycle)
eg->update();
}
// ---

Now, in response to a MIDI note-on message, we setup a MIDIEvent structure and call the member function:

// --- prepare a MIDI event for note-on
midiEvent.midiNoteNumber = 60; // <- get from your framework
midiEvent.midiNoteVelocity = 127; // <- get from your framework
// --- send note event
eg->doNoteOn(midiEvent);
// ---

At this point, we can start to render values from the EG and grab them from the ModulationOutput array for the normal EG output:

// --- render EG output
eg->render( );
// --- here is the normal output value - do something with it!
double egNormOut = eg->getModulationOutput()->getModValue(SynthLab::kEGNormalOutput);
// ---

From here you can keep rendering until the note-off message arrives:

// --- prepare a MIDI event for note-off
midiEvent.midiNoteNumber = 60; // <- get from your framework
midiEvent.midiNoteVelocity = 0; // <- get from your framework
// --- send note event
eg->doNoteOff(midiEvent);
// ---

Now, experiment with changing the EG parameters (see the EGParameter documentation to see what you can change). Also, try experimenting with the mod knobs (see SynthLFO tutorial above)


synthlab_4.png