robotcoder
robotcoder

Reputation: 75

Is there a Callback for an iOS Core Audio Unit, if the unit is connected to both an input unit and output unit?

I have an Audio Unit which is sitting between two other units. That is to say, my unit has another unit assigned to its input node, and it has another unit assigned to its output node.

I want to access the AudioBufferList that is fed into my unit. I would like to access this buffer list within a callback. However, if my unit's input bus is already connected to another audio unit, then my RenderCallback is never called.

What callback can I use to access the passed-in audio buffer(s) of a given unit?

AURenderCallbackStruct splitterCallback;
    splitterCallback.inputProc = (AURenderCallback) SplitterCallback;
    splitterCallback.inputProcRefCon = (__bridge void*) self;
    status = AudioUnitSetProperty(splitterAuUnit,
                                  kAudioUnitProperty_SetRenderCallback,
                                  kAudioUnitScope_Input,
                                  0, &splitterCallback,  sizeof(splitterCallback));


  AudioUnitElement genericOutputBus  = 0;
    AudioUnitConnection genericOutToIoUnitIn;
    genericOutToIoUnitIn.sourceAudioUnit    = genericAuUnit;
    genericOutToIoUnitIn.sourceOutputNumber = genericOutputBus;
    genericOutToIoUnitIn.destInputNumber    = ioUnitOutputElement;



    AudioUnitSetProperty (
                          splitterAuUnit,                     // connection destination
                          kAudioUnitProperty_MakeConnection,  // property key
                          kAudioUnitScope_Input,              // destination scope
                          ioUnitOutputElement,                // destination element
                          &genericOutToIoUnitIn,                // connection definition
                          sizeof (genericOutToIoUnitIn)
                          );

// Callback
static OSStatus SplitterCallback(void                        *inRefCon,
                               AudioUnitRenderActionFlags  *ioActionFlags,
                               const AudioTimeStamp        *inTimeStamp,
                               UInt32                      inBusNumber,
                               UInt32                      inNumberFrames,
                               AudioBufferList             *ioData)
    {
    @autoreleasepool {
        NSLog(@"splitterCallback"); // This is never called. :(
    }
}

Upvotes: 2

Views: 773

Answers (1)

user3078414
user3078414

Reputation: 1937

Here is the Core Audio procedure for registering a callback within an AUGraph API without breaking the API. It is tested in OSX, but this part of the API is common to iOS too. Assuming you want to listen to the signal from input of the output unit, one unit "upstream" would be the splitterAuUnit. I would register the callback MyRenderProc() in the following way:

AudioUnitAddRenderNotify(splitterAuUnit,
                         MyRenderProc,
                         &player);

Inside your callback it is important to check for render actions and post render errors:

if (*ioActionFlags & kAudioUnitRenderAction_PostRender){
    static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
    if (!(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)){

        Float32* data = (Float32 *)ioData->mBuffers[0].mData; //just for one channel!
    //    …   …   
    }
}

Upvotes: 1

Related Questions