[LAD] Plugin buffer size restrictions

Jeff McClintock jef at synthedit.com
Wed May 30 18:59:38 UTC 2012

> From: David Robillard <d at drobilla.net>
> I'm a modular head, I remain convinced that control ports are nothing
> but a pain in the ass and CV for everything would be a wonderful
> fantasy land :)

It's called "SynthEdit land" *everything* is CV ;)  (not on Linux sorry).

> As it happens, I am currently porting the blop plugins to LV2, and
> making a new extension in order to drop the many plugin variants (which
> are a nightmare from the user POV).  This simple extension lets you
> switch a port from its default type (e.g. Control) to another type
> (e.g.
> CV).  The pattern looks something like this:
> /* plugin->frequency_is_cv is 1 if a CV buffer, 0 if a single float */
> for (uint32_t i = 0; i < sample_count; ++i) {
>     const float freq = frequency[s * plugin->frequency_is_cv];
>     if (freq != plugin->last_frequency) {
>         recalculate_something(freq);
>         plugin->last_frequency = freq;
>     }
>     /* Do stuff */
> }

That's smart. In a simple example this doesn't seem like much of a win.
Because A 1 port plugin has only two possible variants (frequency as
single-float/ buffer). But..
* A 2-port plugin has 4 varients.
* A 3-port plugin has 8 varients.
* A 10 port plugin has 1024 varients!

So you're avoiding that combinatorial nightmare.

I do something similar. The port is flagged as either 'streaming' (use the
entire buffer) or 'static' use a single float. My point of difference is -
the entire buffer is provided either way. So you have the option of writing
the plugin like..

     const float freq = frequency[s];


     const float freq = frequency[s * plugin->frequency_is_cv];

.. and it works transparently either way. So the extension is backward
compatible with 'dumb' plugins, or 'dumb' plugin standards like VST (I can
interface VST plugins with modular components).

> Doing those comparisons to see if the value actually changed since the
> last sample in order to recalculate is not so great (branching).

I don't know if you can implement what I do. Once I know which ports are
single floats I 'switch' processing functions. i.e. use a function pointer
to select 1 of several optimised functions.  So you write a general purpose
loop like the one above, this is your fallback. Then you write an optimised
one that assumes 'frequency' is a single float - This one has no branching
and no extra multiplication, it's super efficient. You get the best of both
worlds.  Note I don't write loops optimised for every possible combination,
just pick a few key ones. The function pointer is one extra level of
indirection, but it's much faster than branching, esp when there's several
ports involved in the decision.

> personally my interest in a solution here is very real.  More people
> care about normal high level parameters and being able to interpolate
> than low-level modular synth CV stuff, but to me it's telling that (it
> seems...) one solution can solve both problems nicely.

<high five> ;)

Best Regards,

More information about the Linux-audio-dev mailing list