Search code examples
iosobjective-cavfoundationcore-audioavaudioengine

Add input callback to AVAudioEngine


I'm attempting to add an input callback to an AVAudioEngine's inputNode but it's never being called.

The hope is that I can use AVAudioEngine to manage the basic AUGraph for both iOS and OS X and I can run my own code in between. I've also tried installing a tap on the input node but I'm unable to change the buffer length.

I've made a single view iOS app and put this code in viewDidLoad:

_audioEngine = [AVAudioEngine new];
_inputNode = _audioEngine.inputNode;
_outputNode = _audioEngine.outputNode;

AURenderCallbackStruct inputCallback;
inputCallback.inputProc = inputCalbackProc;
inputCallback.inputProcRefCon = (__bridge void *)(self);


AudioUnitSetProperty(_inputNode.audioUnit,
                     kAudioOutputUnitProperty_SetInputCallback,
                     kAudioUnitScope_Global,
                     0,
                     &inputCallback,
                     sizeof(inputCallback));


[_audioEngine startAndReturnError:nil];

The render callback is defined as this:

OSStatus inputCalbackProc (void *                           inRefCon,
                           AudioUnitRenderActionFlags * ioActionFlags,
                           const AudioTimeStamp *           inTimeStamp,
                           UInt32                           inBusNumber,
                           UInt32                           inNumberFrames,
                           AudioBufferList *                ioData)
{
    printf("Called");
    return noErr;
}

I've managed to install a render callback on the output node's audio unit in the same way but my input callback is never called.

I've checked that the input node's audio unit is the same as the output node's audio unit which suggests the graph has been set up correctly. I've also tried setting the kAudioOutputUnitProperty_EnableIO on the RemoteIO unit (inputNode.audioUnit)

Anybody got any suggestions?


Solution

  • RemoteIO doesn't actually provide a callback when it's ready to be rendered. As it's the same hardware as the output, you can render the input unit when the output unit gets rendered