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 renderBlockwill 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 call allocateRenderResourcesAndReturnError. These functions will be called exactly once from the main thread, and no calls to the AU's renderBlockwill 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, maximumFramesToRenderis simply a hint from the host to specify the maximum number of frames that it will ever ask for in a call to renderBlockso 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 minValueand maxValueof 0.0f and 1.0f respectively, it should be possible to use setValueto set a value between 0.0f and 1.0f (inclusive). However, some AUs specify an incorrect range and setValuedoesn'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 by maximumFramesToRenderas this is just a worst-case maximum
  • Provide overview parameters
  • Ensure that each parameter's minValueand maxValueare set up correctly. It's easy to add some test code which calls setValueon 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.

  • @johnrob66 said:
    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?

  • @giku said:
    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 😁

Sign In or Register to comment.