Search code examples
core-audioaudiounitavaudioengine

How do I subclass AVAudioUnit?


Since the way to instantiate an AVAudioUnit is this:

[AVAudioUnit instantiateWithComponentDescription:componentDescription options:0 completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {
    }];

How am I supposed to subclass AVAudioUnit? I have tried this:

[MySubclassOfAVAudioUnit instantiateWithComponentDescription:componentDescription options:0 completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {
    }];

But the audioUnit that is returned in the block is still of type AVAudioUnit and NOT MySubclassOfAVAudioUnit.


Per Rhythmic Fistman's response, I am registering my custom AUAudioUnit subclass with Apple's example code:

componentDescription.componentType = kAudioUnitType_Effect;
componentDescription.componentSubType = 0x666c7472; /*'fltr'*/
componentDescription.componentManufacturer = 0x44656d6f; /*'Demo'*/
componentDescription.componentFlags = 0;
componentDescription.componentFlagsMask = 0;

I want my AVAudioUnit subclass to always use my AUAudioUnit.


Solution

  • From instantiateWithComponentDescription:completionHandler:

    The returned AVAudioUnit instance normally will be of a subclass (AVAudioUnitEffect, AVAudioUnitGenerator, AVAudioUnitMIDIInstrument, or AVAudioUnitTimeEffect), selected according to the component's type.

    UPDATE I got this wrong - you can't instantiate your own AVAudioUnit subclass, you can only instantiate your AUAudioUnit, wrapped in the relevant built-in AVFoundation AVAudioUnit subclass (e.g. AVAudioUnitEffect, etc).

    The following code causes MyAUAudioUnit, a subclass of AUAudioUnit to be instantiated:

    #import <AVFoundation/AVFoundation.h>
    
    @interface MyAUAudioUnit : AUAudioUnit {
    
    }
    @end
    
    @implementation MyAUAudioUnit
        // implement it here
    @end
    
    // later
    - (void)instantiateMyAUAudioUnitWrappedInAVAudioUnit {
        // register it (need only be done once)
        AudioComponentDescription desc;
        desc.componentType = kAudioUnitType_Effect;
        desc.componentSubType = 0x666c7472; /*'fltr'*/
        desc.componentManufacturer = 0x44656d6f; /*'Demo'*/
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;
    
        [AUAudioUnit registerSubclass:MyAUAudioUnit.class asComponentDescription:desc name:@"MyAU" version:1];
    
        // Instantiate as many times as you like:
        [AVAudioUnit instantiateWithComponentDescription:desc options:0 completionHandler:^(AVAudioUnit * audioUnit, NSError *error) {
            NSLog(@"AVAudioUnit: %@, error: %@", audioUnit, error);
        }];
    }
    

    WRONG BIT

    So to have your AVAudioUnit subclass instantiated, you must first register it with the AUAudioUnit method:

    +[AUAudioUnit registerSubclass:asComponentDescription:name:version:]

    There is a code snippet and some possible gotchas in this devforum thread.