Some notes for AU developers
This would probably be better as a blog, but I don't have one of those so I thought I'd add some notes here. I've now gained a fair amount of experience looking into AU compatibility issues and since they often fall into a few common themes I thought it would be worth sharing.
Sample rate and buffer size
NanoStudio always uses the hardware's current rate for real-time render. On older devices this is always 44.1kHz, but on newer devices it can be 48kHz depending upon the hardware output device currently in use (eg. internal speakers vs. headphone jack). Some external USB audio interfaces may choose a higher sample rate.
During mixdown (offline render), NanoStudio always uses a fixed number of frames (typically 256). Users may choose the sample rate for the mixdown, from 22.05kHz up to 96kHz. Audio units should be able to handle this range.
NanoStudio always follows these rules:
- The number of frames requested by the call to the AU's
renderBlock
will always a multiple of 64 - The number of frames requested will always be more than zero
- The number of frames requested will always be less than or equal to
maximumFramesToRender
- If NanoStudio needs to change the sample rate or buffer size, it will first call
deallocateRenderResources
, set up the new properties and then callallocateRenderResourcesAndReturnError
. These functions will be called exactly once from the main thread, and no calls to the AU'srenderBlock
will be made in between.
Some older AUs are hardcoded to a fixed rate (eg. 44.1kHz) or they use [AVAudioSession sharedInstance].sampleRate
to obtain the sample rate. Instead, they must obtain the sample rate from the bus format specified by the host, which can be different to the AVAudioSession's hardware rate. NanoStudio sets all input and output buses of the AU to the same sample rate, so checking the first output bus is enough as follows:
f64 SampleRate = [avAudioUnit.AUAudioUnit.outputBusses objectAtIndexedSubscript:0].format.sampleRate;
Some AUs expect to always get the number of frames specified by maximumFramesToRender
. However, maximumFramesToRender
is simply a hint from the host to specify the maximum number of frames that it will ever ask for in a call to renderBlock
so that the AU can allocate the worst case buffer size in its implementation of allocateRenderResourcesAndReturnError
. Instead, the AU should only render the number of frames that the host passes to the AU's renderBlock
(which follows the rules outlined above).
The symptoms of not handling the host's sample rate/buffer size correctly typically manifest themselves as the instrument sounding out of pitch, or a crackly/chopped sound because the wrong size buffer is rendered.
Parameter changes are not sent to the host's observer functions
NanoStudio registers two observers with the AU's parameter tree prior to calling allocateRenderResourcesAndReturnError
:
tokenByAddingParameterObserver
tokenByAddingParameterRecordingObserver
These observer functions are used to record automation parameter changes and mark the project as modified when an AU's parameter is altered using its native editor UI. Some AUs don't sent these observer messages, so NanoStudio doesn't record automation movements and doesn't mark the project as modified even though the user has modified the AU's parameters.
To ensure that these observer functions are called, the AU should use AUParameter.setValue when setting state from the UI.
Providing overview parameters
NanoStudio will automatically create a default macro mapping if the user hasn't saved their own one. To do this, it uses the following rules:
- It checks for the most 'useful' parameters by calling the AU's
parametersForOverviewWithCount
- If the AU doesn't provide any overview parameters, it simply chooses the first 10 parameters in the tree
If the AU specifies overview parameters then this provides a better user experience.
AUParameter.setValue doesn't work over the range specified by its minValue and maxValue
For example, if an AU parameter has a minValue
and maxValue
of 0.0f and 1.0f respectively, it should be possible to use setValue
to set a value between 0.0f and 1.0f (inclusive). However, some AUs specify an incorrect range and setValue
doesn't work for all the values which should be possible
In summary
- Always use the host's sample rate by reading it from the AU's output bus
- Always render the number of frames passed to
renderBlock
, not the number of frames specified bymaximumFramesToRender
as this is just a worst-case maximum - Provide overview parameters
- Ensure that each parameter's
minValue
andmaxValue
are set up correctly. It's easy to add some test code which callssetValue
on the minimum and the maximum values and then reads the value back to ensure it matches.
I'm always keen to improve AU compatibility, so feel free to drop me a line at https://www.blipinteractive.co.uk/contact.php and I'm happy to help.
Also feel free to contribute to this thread if you think I've got anything wrong - this has been a learning experience for me and I won't claim to be an authority on this by any means.
- Matt
Comments
I’ve noticed that some au’s eg poison-202 allow the built in patch buttons to work perfectly, and some don’t work at all eg Sunrizer. Is this something that is specific to nanostudio or is it part of the auv3 spec?
It’s extremely handy, wish it would work for all.
Thanks.
Digital d1 half works - nanostudio can identify and move up/down the preset list, but the synth does not load the selection. You have to use the synth built in preset browser.
there is also issue with mixdown with oth D1 and FM Player 2 in NS (and Cubasis), here is more info about that, guys are working on workaround
https://forum.audiob.us/discussion/comment/674242/#Comment_674242
Thanks, so most likely this is the au not working correctly? From the ns manual it does say if an au has factory presets you can select them from the patch browser.
yes, to me it looks that this problem with patches is on plugin side
Just because there was no time to add it yet.. AUfx presets are capable to have patches too.. sooner or later it will be added, most orobably with AUfx parameters automation support
yeah.. i actually do not have much information about future plans in terms of timelines .. i know what is on todo list in general , i know main milestones (iphone, audio tracks) but no particular details ....
Bass 808 from audiokit doesnt work. Stuck on loading screen.
I am on 12.4 ios. Perhaps it work for others with different ios?
Other things work from audiokit, that's
so strange.
I have one question regarding AU Host development..
Host records parameter changes via tokenByAddingParameterRecordingObserver and set parameters using scheduleParameterBlock...
The problem is that scheduleParamterBlock triggers recordingObserver so we have a loop.
What is wrong here? How to avoid this?
Sorry - not got any info regarding the above but @giku : it’s great to see you here. Drambo is just utterly superb 👌 And the recent wavetable osc and wt effects update - wow! Just wow!
Thank you for creating- and releasing - something so truly incredible. 🙌🙌🙌
Oh, while I’m at it - respect to Matt @Blip Interactive for NS2 too of course 😁