> From: David Robillard <d...@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]; ..OR... 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, Jeff _______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/listinfo/linux-audio-dev