Re: [LAD] Plugin buffer size restrictions

From: Tim E. Real <termtech@email-addr-hidden>
Date: Sun May 27 2012 - 02:47:12 EEST

On May 26, 2012 10:02:32 AM Fons Adriaensen wrote:
> On Fri, May 25, 2012 at 10:43:36PM -0400, David Robillard wrote:
> > I am making an LV2 extension for accessing and/or restricting the buffer
> > size. This is straightforward, but I need to know just what
> > restrictions are actually needed by various sorts of DSP.
> >
> > The sort of thing we're looking for here is "buffer size is always at
> > least 123 frames" or "buffer size is always a power of 2" or "buffer
> > size is always a multiple of 123".
> >
> > I know "multiple of a power of two" is needed for convolution. Not sure
> > what else...
>
> It's not really *needed*, an FFT-based process can be designed to
> work with arbitrary and variable buffer sizes provided
>
> * this is known at init time,
> * and the user accepts the additional latency.
>
> 'Power of 2' in practice means 'a power of two that is not
> too small to make things inefficient'. So the plugin should
> have the option to require a minimum size as well, e.g. 64.
>
> But I doubt very much if your extension is going to have much
> impact. I expect most hosts to simply ignore it, as implementing
> it could be quite invasive. Imagine a host having a chain a plugins
> in e.g. a channel strip. If one of them requires this extension
> and the host relies on variable buffer size to provide 'sample
> accurate' control of the others, then the host is required to
> implement extra buffering for that plugin. Probably no-go, some
> hosts even refuse plugins that don't work 'in place', even if
> the solution in that case is much simpler.
>
> The following is part of a report on LV2 I was asked to
> write some months ago:
>
> ======
>
> Audio processing (on PCs) is usually done in blocks of frames,
> so all components are designed to work that way, There are at
> least 4 possible ways the block size of a module or plugin
> could be defined:
>
> 1. Fixed at compile time.
> 2. Fixed at instantiation, power of 2 [*]
> 3. Fixed at instantiation, any (reasonable) value.
> 4. Variable - can be different in each process() call.
>
> [*] Or a similar restriction, e.g. either 2^N or 3*2^N.
> For example some FFT based processes could be designed to
> allow a block size of 3*2^N, or even 5*2^N, while making
> it accept any size would be out of the question in many
> cases.
>
> Clearly (1) is undesirable, and it will not be considered
> further. Some algorithms require (2) in order to meet their
> specs. They could be made to work with any block size, but
> this usually means extra latency, or some other form of loss
> of performance.
>
> Almost all more sophisticated audio processing algorithms can
> be implemented more easily and usually more efficiently if (3)
> is guaranteed, even if the block size itself plays no role in
> their definition and does not affect their output in any way.
> This is in particular true for algorithms that partially run
> using some internal block size (determined by e.g. the sample
> rate and some combination of parameters), or those that have
> to manage a long history or complex state as part of their
> operation.
>
> It is almost always possible to allow (4), the exceptions are
> the cases mentioned above that require (2). But an algorithm
> that should perform well will have to be designed so that the
> output it produces does not in any way depend on the actual
> block sizes used at run time.
>
> This includes ignoring any attempt to e.g. control the rate of
> change of its internal parameters by a caller playing with the
> block size for each process() call. The idea that one could
> achieve 'sample accurate' control of an audio process in this
> way is a either a fallacy or irrelevant, depending on the case
> and how you look at it.
>
> All this means that there is *no reason* to ever require (4),
> of a plugin or module, and no serious plugin standard or
> modular audio application should ever do this.
>
> Yet that is precisely what LV2 does. While it is designed
> to be flexible and extensible, the one and only part of its
> specs that is fixed but shouldn't have been gets it wrong.
>
> And allowing an extension to override this is not going to
> work, because such an extension can be very invasive to a
> host. If a host, e.g. Ardour, is from the start designed to
> exploit the freedom of (4), be it for the wrong reasons, it
> is never going to adopt an extension that would cripple major
> parts of its functionality, e.g. automation, or force them
> to be redesigned. Even less so if the plugin system does not
> provide an alternative way, guaranteed to work with any plugin,
> to obtain the same result.
>
> This is the really sad aspect of the situation: LV2 requires
> so little of a plugin that in order to make things like e.g.
> automation possible it must allow hacks such as playing with
> the block size of each call. So hosts will do this, and that
> wart will never go away.
>
> Things should have been the other way round: allowing hosts
> to use variable block sizes should have been the extenstion.
> Of course nobody would ever use it, because in a well designed
> system or application it is not necessary (not even for the
> things e.g. Ardour uses it for).
>

I added variable run-length processing to MusE.
It can break a period into single frame runs if necessary.

If you have a project with a lot of plugins, or power-hungry ones,
 where you are forced to use large Jack buffer sizes to make
 everything work reasonably well, vari-runs work well.
One reason is because only those plugins whose controls changed will
 consume time during your cycle, versus attempting to run Jack at
 very low periods.
 
Thus we can run Jack at 2048 period size and operate a dssi filter or
 oscillator control for example, and the result is so smooooth sounding,
 responsive, and near-instantaneous that you'd swear you were running 32
 period size, because the the runs are broken up into a reasonable near-frame
 resolution.

What about encoder and decoder plugins? Yer switching matrices etc.
Their precise control rates and timestamps must be preserved right?
I guess if LV2 allows hi-speed control rates, it would cure the issue with
 some ladspa audio ports being used for hi-speed control, with no way to
 know that fact.

So with MusE then, it's /possible/ to have hi-speed control port rates.
Although, I don't know of any ladspa plugin that uses it for say,
 encoder/decoder switching matrices, they all use audio ports for that.
Probably more efficient to use audio ports, I suppose.

Caveat: Dssi-vst no likey!
I admit, we needed a special hack to turn off vari-runs for dssi-vst plugins.

But other than the entire dssi-vst, I have not found a ladspa/dssi plugin
 or synth yet that doesn't like it. Can you think of any that I might want
 to reconsider and test?

Also, we're not out of our woods yet, it was a fun experiment, but we still
 need to provide that kind of resolution on our playback, which I admit may
 ultimately require fixed run lengths (but still multiple per period), for
 interpolated floating point controls (not integer), because if even one
 single control is currently on a slope between two points we don't have
 much choice but to do the whole plugin period in adjustable fixed
 run-length segments.
(We do provide a 'Minimum Control Period' user setting as a lower limit
 for such and other uses.)

Whaddya you guys think?
Or did I actually just provide arguments /against/ vari-runs? Ha ha...

Cheers. Tim.

_______________________________________________
Linux-audio-dev mailing list
Linux-audio-dev@email-addr-hidden
http://lists.linuxaudio.org/listinfo/linux-audio-dev
Received on Sun May 27 04:15:01 2012

This archive was generated by hypermail 2.1.8 : Sun May 27 2012 - 04:15:02 EEST