I had an epiphany regarding Audio Units just now, which helped me solve my own problem. I had a misconception about how audio unit connections and rendering callbacks work. I thought they were completely different things, but it turns out that a connection is just a short hand for a render callback.
Executing kAudioUnitProperty_MakeConnection from the output of audio device A to the input of audio device B is the same as kAudioUnitProperty_SetRenderCallback at the input of device B and the call function of the call function AudioUnitRender at the output of audio block A.
I tested this by making a make connection after setting the visualization callback, and the render callback was no longer called.
Therefore, I was able to solve my problem by following these steps:
AURenderCallbackStruct callbackStruct = {0}; callbackStruct.inputProc = MyAURenderCallback; callbackStruct.inputProcRefCon = mixerUnit; AudioUnitSetProperty(ioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackStruct, sizeof(callbackStruct));
And their callback function did something like this:
OSStatus MyAURenderCallback(void *inRefCon, AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { AudioUnit mixerUnit = (AudioUnit)inRefCon; AudioUnitRender(mixerUnit, actionFlags, inTimeStamp, 0, inNumberFrames, ioData); ExtAudioFileWriteAsync(outputFile, inNumberFrames, ioData); return noErr; }
This probably should have been obvious to me, but since I was not sure that there were others who were confused in the same way, so I hope this is also useful to them.
I'm still not sure why I am having problems with the AUGraphAddRenderNotify callback. I will delve into this later, but at the moment I have found a solution that seems to work.