[LV2] Buffersize, Options and Externtion-Data

Robin Gareus robin at gareus.org
Wed Sep 9 07:40:28 PDT 2015


Hi David, LV2-team,

There is a recent misunderstanding regarding block length semantics
which is in need of clarification.

In short: How can a plugin query the current nominal block-size?


Backstory
---------

Some Plugins expect maxBlockLength [1] to be the current block-length.
Most lv2-hosts just passed jack_buffersize and users never changed the
jack-buffersize at runtime so this worked for the most part in recent years.

A few months ago it was brought to the attention of ardour-devs [4] that
some plugins mis-behave or crash during session-export, while looping or
with pluigin-analysis. In those cases the cycle in Ardour does not
correspond to the jack-buffersize, and the plugin was asked to process a
larger or smaller amount of data.

Ardour-4.2 now sets minBlockLength to 0, maxBlockLength to 8192, passes
those fixed values as Instantiation Option and refuses to load plugins
that require fixedBlockLength [3].

Semantically that is correct with the LV2 specs [1, 2, 3] and fixes many
crashes, particularly with plugins which use [1] to pre-allocate
internal buffers.

However some other plugins - esp convolution engines - are not happy
with a buffersize-range without any means to query the current, nominal
period-size. The most recent discussion about this is [7].


Specifications
--------------

"There are two facilities for passing options to an instance:
opts:options allows passing options at instantiation time, and the
opts:interface interface allows options to be dynamically set and
retrieved after instantiation." [5]

[6] mentions that the accessor functions are in the "instantiation" LV2
threading class.


Specs Clarification
-------------------

Is it correct to interpret the spec as follows?

 (1) When the buffer-size is passed as instantiation parameter it is a
fixed value.

 (2) When the min/maxBlockLength is used as opts:interface via
LV2_Descriptor::extension_data() it can be dynamic, using get() set() as
outlined in [6].

 (3) the opts:interface [6] to get/set the value must not be used in the
run() realtime-process function. It's only valid to get/set options
during activate(), deactivate(), worker-thread or state-load/save.


Discussion
----------

If a above interpretation is correct there is no way for a plugin to
know what the current period size it. (except maybe using a
worker-thread to periodically poll the opts:interface)

One possible solution would be to require a host to activate/deactivate
plugins to dynamically set the buffersize (2,3) or to re-instantiate the
plugin (1). This could be tied in with fixedBlockLength [3] without any
changes to the spec, but will render some plugins useless.

Alternatively, hosts could ring-buffer wrap plugins requiring
fixedBlockLength, at the cost of adding latency and potentially increase
CPU load (always run the plugin with fixed small chunk-size).


Another solution on the table is to create a new dedicated extension for
this use-case (maybe even a synchronous callback). That poses some more
questions:

The run() function already passes the actual sample-count. So what
number does "current" mean?  The total number of samples is expected to
span various run() calls resulting in one hardware cycle?  Since the
hardware buffersize can change anytime at what intervals is it updated?


A more general question is: Do we want to encourage DSP to be written in
a way that requires a-priori knowledge about the nominal period-size?



yours truly,
robin



References
----------

[1] http://lv2plug.in/ns/ext/buf-size/#maxBlockLength
[2] http://lv2plug.in/ns/ext/buf-size/#minBlockLength
[3] http://lv2plug.in/ns/ext/buf-size/#fixedBlockLength
[4] http://tracker.ardour.org/view.php?id=6498
[5] http://lv2plug.in/ns/ext/options/
[6]
http://lv2plug.in/doc/html/group__options.html#structLV2__Options__Interface
[7] http://sourceforge.net/p/guitarix/bugs/24/



More information about the Devel mailing list