Ways to Connect Env,LFO,Macro to Variables



I would like to make Env or LFO, Macro etc that can connect to variables user want.

In some vst plug-ins, they can drag them to the knob with the mouse and connect them to the knob.
It seems to be called various names such as Macro, Modulation, but it look like no exact technical name. So there is a difficulty in finding a way.

How do I make it possible to connect Env, LFO, etc to variables?


Hello !

It’s not like envelopes or LFOs are really “connected” to any variable under the hood. Most of the time, a modulation matrix is implemented somewhere, and depending on the user actions, some internal variables in the audio processing will use the LFOs and envelopes to modulate themselves.

Your question isn’t that clear, do you have already an audio process where you would like to add modulation functionalities ? Are you talking about the processing side or the user interface side ?


Oh,it was called a modulation matrix. :slight_smile:
Exactly what I asked is both the implementation of the modulation matrix and the implementation of the drag-drop method.


Hi !

I’m also curious about this issue, and I’d be curious to know what is considered the “best practice”.

Should it be as follows ?

  1. Use an AudioProcessorValueTreeState for external parameters
  2. Link those parameters (and maybe other internal variables?) to a “ModMatrix” class, as “modulation destinations”
  3. Link your LFOs, Enveloppes, etc. as “modulation sources”. Create a ModulationSource class to inherit from
  4. Add a ModMatrix.getValues(parameter) function, to get the computed values of your modulated parameter, for the current block
  5. Add a ModMatrix.link(parameter, source, modulationDepth, modulationPolarity) function
  6. Store all computed values in AudioBuffers, for flexible, audio-rate modulations operations

I assume getValues(parameter) should work in a way akin to the following ( I’m very new to C++ and JUCE, so bear with me).

AudioBuffer ModMatrix::getValues (String &parameterID, int samplesPerBlock)
    AudioBuffer values = new AudioBuffer (1, samplesPerBlock); // 1 channel
    for (ModulationSource modSource : modSources)
        AudioBuffer sourceValues = modSource.computeValues(samplesPerBlock);
	    values.addFrom (0, 0, sourceValues, samplesPerBlock, modSource.getModulationDepth());
    return values;

Is that somewhat correct, or is this far fetched ? :sweat_smile: