There are a lot of DAWs out there. Some DAWs have a unique ways of handling threading for example, and other operations.
For example, I had a GUI bug that only showed itself in Reaper. Reaper is unique in some ways.
Definitely Logic Pro needs special attention as I understand.
I’ve got Ableton Lite.
I’ll probably end up trying to download trial version of the DAWs that offer that.
Any other DAWs you could suggest have their own unique ways of doing things, that I should especially scrutinize when testing?
FL use variable size buffers, for first plugin was testing mostly on ableton, bitwig, brainmodular, and end up assuming blocsize would always be fixed, of asio size, as they all behaved the same, made lot of optimizations according to this… then was quite painfull to discover FL was killing all that work randomly asking 4,7,68,whatev buffer sizes, implying a different strategy…
more a wrong assumption newbie error tho…
A probably related one is, that block sizes are different in Logic depending if it is placed on an Audio or an Instrument track. However that observation was a long time ago, it might have changed in the meantime.
Some hosts pump 0’s when playback is stopped, others don’t. This can make visualisers freeze if they assume a constant flow of samples.
confirmed;: Logic and Studio One do this extra long buffer thingy to boost performance and to get the playback tracks at the best possible latency. That is the live monitoring which then uses the hardware buffersize.
Using your own hopsizes is highly recommended. Just forget about the hosted buffersize, make your own size. The eausest way is to use a “tick()” function at the top that pushes 1 sample into your code and gets 1 sample back. Now you can do analytical stuff every Nth Smaple. The host doesnt need to know that.
FL is particularly aggressive with variable block size requests (and currently works that way by default - but you can disable it per plugin), and although I have FIFO code to make everything render internally in fixed chunks I got a dropped audio frame bug recently that occurred at after the first dozen or so of blocks are rendered when rendering to file specifically (fixed now).
(Moral of the story don’t forget to test file rendering and not just live audio.)
You should also be aware that some DAWs are triggering multiple prepareToPlay calls in a row, before and after render, and FL by default triggers that on playback start even if nothing has changed in the audio interface configuration (a feature that can be turned off).
Another thing I had to fix (because I use multiple real time audio threads) with AU plugins and audio workgroups (for mac silicon) was making sure to properly un-register threads that are registered to the audio workgroup of the main callback on prepareToPlay, and be careful that the audio work group is not attempted to be registered if when retrieved it’s a null-pointer (because Apple’s workgroup registration API doesn’t check for null-pointers and will crash)… this is the case when rendering to file since in that case renders are usually happening in faster than real-time and not tied to a hardware callback.
Other things to be aware of, some DAWs (Ableton 11 in Windows for example appears to do it by default) will process real-time processing audio sub-blocks in multiple threads (which usually would not be an issue, and you might not even notice it, but might be worth noting that your JUCE renderBlock calls might not always come in on the same thread).
Also… outside of audio, there are various GUI scaling issues that can appear in different DAWs… Ableton has a option to ‘auto scale’ plugins… turn it off and you might get issues with popup menus in Windows being at a different scale to the rest of the plugin.
Maschine: it uses a fixed (and big) buffer size regardless of what you select in your audio device settings.
Pro Tools: if I remember correctly, when Pro Tools loads a song/session that contains your plug-in, it will do the following:
- Call your setStateInformation() with a default state for your plug-in that PT picked up upon scanning or upon first istantiation of your plug-in.
- Set all your automated parameters to the default values that it obtained at the same time it queried for the default state at point 1.
- Finally call your setStateInformation() with the state that was saved for your plug-in inside the song/session
- In the end, it will set all your automated parameters to the values they had when the song/session was saved.
All of the above calls will arrive from a worked thread that’s not the message thread.
There is a macro in JUCE that you can
#define, to skip steps 1. and 2. above: search for
And the AAX format also provides a native flag to instruct Pro Tools to make all those calls from the message thread like most of the other DAWs, but currently there’s no JUCE way to specify it (for a reason, see: [AAX][PULL REQUEST] Force Protools to do chunk calls in message thread option - #15 by reuk)
Does this mean it can pass you a block size that’s larger than the one that prepareToPlay gets?
As far as I remember I’ve never seen this. Block sizes have always been less than the prepareToPlay amount. Although I have seen zero sized blocks before
here are some special bitwig things:
- the playhead doesn’t work correctly after having re-opened a project. when you start playback it sends the ppq to all 3rd party plugins as if you’d start from bar 1, no matter on which bar you are. you can move the start-playhead somewhere else and it will fix itself by doing so, but once the playhead hits a loop point it will be problematic again, unless you also move the loop points around at least once after starting the project. but then everything works fine.
- when you enable the sidechain input of a plugin by defining a sidechain source it will not suspend the process and call prepareToPlay but just keep on calling processBlock, so better get ready for your sidechain stuff to still work without sidechain activated.
- i wanted to add 3 points to this list, because that looks cooler than 2, but i can’t come up with something rn. maybe i’ll edit this post later
the trick is to not immediatly return from processBlock the moment numSamples is 0 but always process the things that are important for the visualizers before. that works in all of the hosts that at least keep on calling processBlock with numSamples 0 instead of using numSamples 0 to signal an end of processBlock calls entirely, in which case some people have proposed adding manual checks for continuous processing directed from the message thread instead