AUv3 explicit registration of audio units

I am investigating AUv3 to see if it is suitable for an upcoming iOS project.


In the Audio Unit Development Fundamentals for the AUv2 on OS X it states that:


"A host application can explicitly register audio units installed in arbitrary locations by using the Component Manager’s RegisterComponent, RegisterComponentResource, or RegisterComponentResourceFile functions. Audio units registered in this way are available only to the host application that invokes the registration. This lets you use audio units to add features to a host application you are developing, without making your audio units available to other hosts."


However the classes that do this are all deprecated and not available in iOS anyway.


Is there any equivalent to this "explicit registration" available in the AVAudioUnitComponentManager structure that will allow me to keep some audio units private to my app?

Replies

After some further trawling of the docs I think this may be possible.


On the AUAudioUnit page it states:


Version 3 audio unit components can be registered in the following ways:


The documentation for the second method states (my italics):


This method dynamically registers the supplied AUAudioUnit subclass with the Audio Component system, in the context of the current process only. After registering the subclass, it can be instantiated via the

AudioComponentInstanceNew
function, the
initWithComponentDescription:error:
or
initWithComponentDescription:options:error:
method, or via any other APIs which instantiate audio units via their component descriptions (e.g. Audio Toolbox or AV Foundation APIs).


I'll try this out and report back.

This was indeed possible. The AudioUnitV3Example gives an example in FilterDemoApp/ViewController.swift viewDidLoad()

If you want to keep some v3 AUs private to your host don't package them up as extensions. In your app create a subclass(s) AUAudioUnit(s) and as stated above use registerSubclass:asComponentDescription:name:version: to dynamically registers your AUAudioUnit subclass with the Audio Component system, in the context of the current process (only). Then you can use the AVAudioUnit class method instantiateWithComponentDescription:options:completionHandler: or AUAudioUnit class method instantiateWithComponentDescription:options:completionHandler: or AudioComponentInstantiate() depending on your requirements.


You can see this usage in the sample:


AudioComponentDescription desc;
/*  Supply the correct AudioComponentDescription based on your AudioUnit type, manufacturer and creator.

        You need to supply matching settings in the AUAppExtension info.plist under:

        NSExtension
            NSExtensionAttributes
                AudioComponents
                    Item 0
                        type
                        subtype
                        manufacturer

        If you do not do this step, your AudioUnit will not work!!!
    */
    desc.componentType = 'aufx';
    desc.componentSubType = 'f1tR';
    desc.componentManufacturer = 'Demo';
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;

    [AUAudioUnit registerSubclass: AUv3FilterDemo.class asComponentDescription:desc name:@"Demo: Local AUv3" version: UINT32_MAX];


AVAudioUnit.instantiateWithComponentDescription(componentDescription, options: []) { avAudioUnit, error in
   guard let avAudioUnit = avAudioUnit else { return }
           
    self.testUnitNode = avAudioUnit
    self.engine.attachNode(avAudioUnit)
...


For any v3 AUs you want to be publicly available, package those up as extensions and include them in the App.

Could you possible go into a bit more detail on this. I'm a little confused as you talk about not packaging the audio unit extension but making sure the information is in the AppExtenion info.plist

You just have to subclass an AUAudioUnit within your iOS project, register it using +[AUAudioUnit registerSubclass:asComponentDescription:name:version:] and then instantiate using i.e. +[AVAudioUnit instantiateWithComponentDescription:options:completionHandler:]

Note that the documentation for the registerSubclass:asComponentDescription:name:version: is lacking in detail.


I was listing my available AudioUnits including a mix of system and explicitly registered ones. The system ones were fine but the explicitly registered ones would not display a name despite my providing one in the registerSubclass call.


I wasted a day before I finally managed to work out that the registerSubclass call is expecting the name parameter to be of the form "Company Name:Unit Name". If the name you supply to registerSubclass does not contain a colon then neither the name or manufacturerName will be populated when you retrieve the unit as an AVAudioUnitComponent using AVAudioUnitComponentManager.sharedAudioUnitComponentManager().componentsMatchingDescription.

Yes, this is a good point and exposed a bug where the absence of a colon should be handled as an empty manufacturer, not an empty name. Also, I've asked pubs to update the API reference docs.


The value for name should follow this specific pattern (this is the same format as the name key in the AudioComponents array).


<company name>: <audio unit name>


By convention, an audio unit's component name is its manufacturer's name, plus ": “ (colon), plus the audio unit's name. The audioUnitName and manufacturerName properties are derived from the component name.


Example: "Demo: Local AUv3"


thanks!