On variable buffer sizes in vst 2 and 3 and other host idiosynchrasies

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Thanks for all the answers! To avoid any confusion, let me be clear that I perfectly understand that the host can throw any block size between 0 and maxBlockSize at my plugin, even 0 apparently. And I obviously will make sure that my plugins can handle anything within the specs.

My reasons for starting the thread was to better understand what is happening in between those extremes and how different hosts behave. And in particular if host that are known for passing varying buffer sizes behave the same with VST 3.

But yes, reason is obviously that I'm doing block based processing a lot of the time, because it is efficient and lends itself well for vectorising. Also, did anyone remember if there ever was a document which documented host behaviour, or did I just dream that?
Last edited by noizebox on Thu Dec 31, 2020 3:54 pm, edited 1 time in total.

Post

arne wrote: Thu Dec 31, 2020 1:52 pm MPE is such a small subset of Note Expression that it is so easy to map to it. There's even a helper class in the VST SDK which helps supporting this for plugin formats not supporting note expression. I don't get why people implement shaky MIDI CC message parsing by its own instead of relying on a well defined API and use a helper if the API is not available.
Consider how slow VST3 adoption process was (and let's not get into the reasons why it was like that) and why DAW developers were so slow on the uptake (each had a bunch of their own reasons), that should answer your question. Messing with MIDI that DAW already had implemented is easier than implementing a whole new plugin type hosting, I guess. (Unless you're Ableton and you're really slow on implementing what your users really want from you.)

Things don't always go as intended in life, apparently. Such is the story of VST3. :)

Post

The adoption was slow because Steinberg was nice enough to not abandon VST2 on the release of VST3. Not like Avid did with RTAS when they released AAX.

Post

mystran wrote: Thu Dec 31, 2020 11:49 am
Markus Krause wrote: Thu Dec 31, 2020 10:31 am While nearly all other hosts process blocks with a constant size of 2^n samples like 64, 128, 256, 512, FL Studio processes blocks with a completely random size(312, 45, 52, 1, ...) which changes always.
This is just not true. Most hosts will usually give you blocks that match the driver buffer size and most drivers give you 2^n sizes. However, most hosts will split blocks in some situations.

As an example, both Ableton and Reaper (and probably most others, but these two I just confirmed) will split a block whenever they cross a loop point (which makes sense: otherwise the plugin couldn't get the correct time-info after the loop jump). I can't remember if either of them splits blocks in other situations as well, but the point is that a host that will always send you nice fixed blocks of 2^n is certainly an exception rather than the rule.
I can not confirm dropouts or technical problems with Ableton or Reaper. FL Studio is the only host that suffers from extreme CPU-load-jitter that causes crackles.
I think you also missunderstood me. Please note that all our plugins can handle variable blocksize. But FL Studio splits up blocks in a bad way and is badly optimized. As a result CPU spikes can happen which cause dropouts on plugins that do block-processing.

To make my point clear again:
In FL Studio it can occasionally happen that a block with a single sample (1 sample small!!!) is processed. You can easily prove this for yourself when you monitor sampleFrames. The behavior of FL Studio is completely inefficient when it comes towards CPU optimization. A lot of CPU is wasted for the context-switch, the CPU-cache and also the branch-prediction is messed up. As a result crackles and CPU spikes can happen - especially with more complex plugin or plugins that do block-processing (FFT etc).
https://www.tone2.com
Our award-winning synthesizers offer true high-end sound quality.

Post

Markus Krause wrote: Fri Jan 01, 2021 9:23 am I can not confirm dropouts or technical problems with Ableton or Reaper. FL Studio is the only host that suffers from extreme CPU-load-jitter that causes crackles.
I think you also missunderstood me. Please note that all our plugins can handle variable blocksize. But FL Studio splits up blocks in a bad way and is badly optimized. As a result CPU spikes can happen which cause dropouts on plugins that do block-processing.
Fair enough. I don't necessarily agree that FL's processing is truly a problem (and it's the host I use for my own production; very few plugins actually have any issues with it), but it's true that it does have an impact on CPU usage and it can be somewhat sensitive to plugins that have a large per-block overhead.

That said, FFT processing is problematic in general, because often you want a blocksize larger than the driver buffersize anyway and the problem seems rather hard to completely solve (even with a different plugin interface spec) without an "earliest deadline first" real-time scheduler (which we unfortunately don't have on general purpose operating systems).

Post

1 sample blocks are completely valid. The speed issue is the plugin handling variable block sizes, when that handling becomes longer to process than the block data processing. A host may send 1 sample blocks all the time, always, and the plugin may or may not expect more than 1 sample.

Post

camsr wrote: Fri Jan 01, 2021 10:42 pm 1 sample blocks are completely valid. The speed issue is the plugin handling variable block sizes, when that handling becomes longer to process than the block data processing. A host may send 1 sample blocks all the time, always, and the plugin may or may not expect more than 1 sample.
Let's get real: sending 1 sample at a time constantly would be terrible for performance, but that's not what FL or any other host is doing. Rather what it's doing is splitting the blocks into unpredictable chunks, some of which sometimes end up 1 sample long. On average with a typical ASIO buffer it usually gives you 2-3 blocks at most per buffer. Some of these might be 1 sample, but most of them are a lot longer.

edit: Personally, the main downside I see with very short buffers is that if you have a CPU-hungry plugin (say a synth) that's multi-threading internally, then the short buffers are slightly annoying because dispatching 1 sample buffers to a threadpool typically has far more overhead than computing the whole thing in the main (audio) thread. Fortunately, most buffers even in FL are not that short, so if you check the block size and use a separate codepath for the very short blocks, then things generally work quite fine.
Last edited by mystran on Fri Jan 01, 2021 11:32 pm, edited 3 times in total.

Post

FLStudio is great for testing plugins as you can dynamically change that max buffer size with a slider.
Checkout our plug-ins here.

Post

I never think of the process as passing 'blocks' - I find it best to see the incoming signal as a stream of data.
Blocks of data don't exist, it's just a continuous flow.
If you start thinking, "This is the start of a block, I therefore need to setup something" - then that's the wrong approach.
*edit* Yes, FL Studio is a great test host, the process can be called with a little as 1 sample at any time, and it boots up incredibly fast for testing.

Post

mystran wrote: Fri Jan 01, 2021 11:28 pm
camsr wrote: Fri Jan 01, 2021 10:42 pm 1 sample blocks are completely valid. The speed issue is the plugin handling variable block sizes, when that handling becomes longer to process than the block data processing. A host may send 1 sample blocks all the time, always, and the plugin may or may not expect more than 1 sample.
Let's get real: sending 1 sample at a time constantly would be terrible for performance, but that's not what FL or any other host is doing. Rather what it's doing is splitting the blocks into unpredictable chunks, some of which sometimes end up 1 sample long. On average with a typical ASIO buffer it usually gives you 2-3 blocks at most per buffer. Some of these might be 1 sample, but most of them are a lot longer.

edit: Personally, the main downside I see with very short buffers is that if you have a CPU-hungry plugin (say a synth) that's multi-threading internally, then the short buffers are slightly annoying because dispatching 1 sample buffers to a threadpool typically has far more overhead than computing the whole thing in the main (audio) thread. Fortunately, most buffers even in FL are not that short, so if you check the block size and use a separate codepath for the very short blocks, then things generally work quite fine.
Another downside is how SIMD instructions are utilized, when the block is less than the multiple data components capable of being processed. Speaking from creative perspective here, If there is feedback topology between plugins, then it's just about absolute to use a 1 sample block where needed. In general though, the block should probably never be smaller than 4 (or maybe 8?) samples, regardless of whether there are automations or events. If it were smaller, it would simply be wasting cycles by padding 0s into the instructions for samples that don't exist. I don't think a branched code-path that goes out of it's way to not use SIMD instructions would be any better, except (and only just possibly) if it were processing a 1 sample block topology.

Post

The fact that I couldn't find any example code showing how to properly use VST3 sample-accurate parameter automation led me to believe that nobody takes it seriously enough to implement correctly. The fact that even the VST3 SDK itself doesn't have a good illustration is a major tell in this regard.

No disrespect to anybody who did take the time to implement it correctly, but if JUCE doesn't bother then I don't really see the point.
owner/operator LHI Audio

Post

camsr wrote: Tue Jan 05, 2021 1:09 am
mystran wrote: Fri Jan 01, 2021 11:28 pm
camsr wrote: Fri Jan 01, 2021 10:42 pm 1 sample blocks are completely valid. The speed issue is the plugin handling variable block sizes, when that handling becomes longer to process than the block data processing. A host may send 1 sample blocks all the time, always, and the plugin may or may not expect more than 1 sample.
Let's get real: sending 1 sample at a time constantly would be terrible for performance, but that's not what FL or any other host is doing. Rather what it's doing is splitting the blocks into unpredictable chunks, some of which sometimes end up 1 sample long. On average with a typical ASIO buffer it usually gives you 2-3 blocks at most per buffer. Some of these might be 1 sample, but most of them are a lot longer.

edit: Personally, the main downside I see with very short buffers is that if you have a CPU-hungry plugin (say a synth) that's multi-threading internally, then the short buffers are slightly annoying because dispatching 1 sample buffers to a threadpool typically has far more overhead than computing the whole thing in the main (audio) thread. Fortunately, most buffers even in FL are not that short, so if you check the block size and use a separate codepath for the very short blocks, then things generally work quite fine.
Another downside is how SIMD instructions are utilized, when the block is less than the multiple data components capable of being processed. Speaking from creative perspective here, If there is feedback topology between plugins, then it's just about absolute to use a 1 sample block where needed. In general though, the block should probably never be smaller than 4 (or maybe 8?) samples, regardless of whether there are automations or events. If it were smaller, it would simply be wasting cycles by padding 0s into the instructions for samples that don't exist. I don't think a branched code-path that goes out of it's way to not use SIMD instructions would be any better, except (and only just possibly) if it were processing a 1 sample block topology.
That's exactly the point. That's the reason why complex plugins and plugins that internally do block-processing (like FFT) do not work well with FL Studio.

1) The context-switch causes huge overhead - especially with multi-threaded plugins.

2) Branch-prediction is messed up.

3) CPU Cache is messed up.

4) It can occasionally happen that the plugin with internal block-processing needs to processes a block (like 64 samples) while FL Studio just needs 1 samples. Things get even worse when several instances are running. I want to point out here that internal block-processing for CPU optimization is a common practice. Hardware does it, we do it, U-he does it, all FFT plugins do it, many synthesizers do it.

As a result CPU spikes can appear which cause crackles.
A host should avoid to process blocks below 16 samples. Our CPUs can not handle this well. You can argue that 'the VST specs do not forbid such small sizes'. Fact is that it's simply bad practice and should be avoided

What really makes me angry that Imageline blames the plugin-developers for their bad engine-design. Instead they should just fix it and behave in a common way like other hosts do
https://www.tone2.com
Our award-winning synthesizers offer true high-end sound quality.

Post

In general multi threaded processing in a plugin should be avoided if possible. If for some reason it is necessary then you really need to decide on a minimum block size that is buffered internally. It's obviously really dangerous to have to wait for multiple threads to complete every sample, or even every few samples and is a recipe for drop outs. (Edit: I should say that is my hunch as I only ever needed to multi thread FFTs, so have no experience of waiting for multiple threads every sample).

For FFT processing then you should, presumably, already be buffering, so there shouldn't be any issue there. The context switching, handled by the OS should be taken care of behind the scenes and be independent of the host's block size. FL studio sending a single sample block is not an issue with the right implementation.

Post

Please read my previous post properly. I have given a detailed technical explanation why FL Studio should be fixed. I am coding audio software since 1995 and really know how computers work.

Keep in mind that nearly every VST plugin runs on more than 2 threads. Audio and a second idle thread for GUI.
Our stuff uses up to 4 threads. Audio, idle GUI, idle preprocessing. It is lock-free. No thread needs to wait for the other.
Some othee devs uses a separate threads for every voice.

Multicore CPUs exists since two decades now. And you're saying that plugin-developers should not support it or rewrite their software , just because FL Studio isn't working properly?
We support this since 14 years. Everything works fine in all hosts except FL Studio...
https://www.tone2.com
Our award-winning synthesizers offer true high-end sound quality.

Post

mystran did say that you should not care about the size of blocks host sends. Buffer them internally and report latency (which is what u-he does).

viewtopic.php?p=7989199#p7989199

FL is not broken. It's doing what VST spec allows. The back and forth bickering who's in the wrong is frankly ridiculous. They provide the option for fixed block sizes for plugins that have expectations about block size (which they shouldn't have), so that's all there's to it.

Post Reply

Return to “DSP and Plugin Development”