4
votes

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?

3

3 Answers

2
votes

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

1
votes

Can you show your code for enabling I/O? Mind that it should be on scope kAudioUnitScope_Inputand element 1.

0
votes

There are two things I see that could be wrong. You don't metion the audio session. I wonder if you have set it to something that takes an input:

let audioSession = AVAudioSession.sharedInstance()
audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
audioSession.setActive(true)

Also kAudioOutputUnitProperty_EnableIO needs to be applied to kAudioUnitScope_Input because you can enable/disable input or output independently.

AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input, bus1, &enableInput,sizeof(enableInput))

There are other things to check but you said that you had a callback working elsewhere so these are specific to this unit and bus.

Note: this code is NOT complete and is only the main and relevant points in setting up a audio session and enabling input.