How to handle Modulations

I’ve been wondering how to efficiently handle modulations and I think I have a big mess about it. Let’s say you have various LFOs that can be mapped to any parameter of the synth, and the modulation rate occurs every X samples. Since it’s up to the user to chose which parameter can be modulated, in a modulation matrix fashion:

  1. Should all the parameters that can be modulated be checked for value changes every X samples? Is that efficient at all if you have lots of parameters?

  2. If the parameter that is set to be modulated needs to call some other functions, is there any other way to handle that rather than using switch/ifs that check each parameter for its appropiate function calls? i.e: once a filter cuttof sees its value changed, it must call setFilterCoefficients(…)

You’re going to have to benchmark to see if checking for updates is slower than just always updating parameters. It may depend on your voice architecture, the parameter update logic, even the patch itself.

The two ways to look at this is either the modulation sources write to their list of modulation destinations and update their parameter states, or the destinations look at their sources and read them to update their state.

In the latter case, if the list of sources for a given destination is empty no updates will be triggered.

1 Like

Thanks, I see then those are the most common way of handling those and there isn’t much wizardry behind it. I’ve been looking for arrays of function pointers for direct calls as an optimization but I guess the only way to find out is profiling.
My voice architecture is pretty simple and I’d say quite common: oscillator, filter, envelope and not much more. But I’ve abstracted function calls from voices to the audio processor itself so I only call it once there and spread the same value among voices rather than redundantly calling it in every voice.

I’m not sure what you mean by “abstracted function calls from voices to the audio processor” or “redundantly calling it in every voice.”

Also, things like switch statements and virtual base classes are usually compiled as arrays of function pointers (called “jump tables” for switches or “virtual method tables” for base classes) so you don’t always need to roll your own. Though it is fun to write something low level like that.

Glad to hear that, won’t need to dive into that kind of optimization then :stuck_out_tongue_closed_eyes:

Well I mean something like opening a file to read or common data used by all voices (a wavetable for example) I just process/store it once and pass a pointer/result (depending on what I’m doing) to them instead of doing it for each voice, or having a copy of the same data for each voice. Of course filters, envelopes and oscillators must be “individual” to each voice