I’ve been trying to make a 2-node graph for weeks, and can’t get it to work. Having overcome numerous errors on my part, I’m up against the wall on this.
I have a test program with a fair number of alternative setups I can try. Here are two, one that works and one that doesn’t. The first uses AUGraphConnectNodeInput() to connect the output of cvtNode to the input of ioNode. The second
emulates a connection by setting up a render callback on ioNode that does nothing but turn around and call AudioNodeRender() on cvtNode. The render callback works, whereas the graph connection does not.
Here’s the code that differs, from the one that does not work:
AURenderCallbackStruct callback;
callback.inputProc = inputCallback;
callback.inputProcRefCon = (__bridge void*) self;
err = AudioUnitSetProperty(mIoUnit, kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global, ELEMENT_MIKE_1, &callback, sizeof(callback));
// check err
err = AUGraphConnectNodeInput(mGraph, cvtNode, 0, ioNode, ELEMENT_SPKR_0);
// check err
callback.inputProc = renderCallback;
callback.inputProcRefCon = (__bridge void*) self;
err = AUGraphSetNodeInputCallback(mGraph, cvtNode, 0, &callback);
// check err
I checked kAudioUnitProperty_LastRenderError on both units, and it’s noErr. At least, it is whenever I checked it which was totally asynchronous to the processing.
Here’s the code called in place of the above, that does work:
AURenderCallbackStruct callback;
callback.inputProc = inputCallback;
callback.inputProcRefCon = (__bridge void*) self;
err = AudioUnitSetProperty(mIoUnit, kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global, ELEMENT_MIKE_1, &callback, sizeof(callback));
// check err
callback.inputProc = renderConnectionCallback;
callback.inputProcRefCon = (__bridge void*) self;
err = AUGraphSetNodeInputCallback(mGraph, ioNode, ELEMENT_SPKR_0, &callback);
// check err
callback.inputProc = renderCallback;
callback.inputProcRefCon = (__bridge void*) self;
err = AUGraphSetNodeInputCallback(mGraph, cvtNode, 0, &callback);
// check err
Here’s the callback that works by emulating a connection, minus debug prints:
static OSStatus renderConnectionCallback(void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData) {
T4AppDelegate* self = (__bridge T4AppDelegate*) inRefCon;
OSStatus err = noErr;
err = AudioUnitRender(self->mCvtUnit, ioActionFlags, inTimeStamp,
0, inNumberFrames, ioData);
return err;
}
(The debug prints are done only once every 99 calls, and are dispatched onto the main queue. Besides, they’re in the code that does work.)
Here’s another approach that also doesn’t work – setting the connection through the AudioUnit API:
AURenderCallbackStruct rcb;
rcb.inputProc = inputCallback;
rcb.inputProcRefCon = (__bridge void*) self;
err = AudioUnitSetProperty(mIoUnit, kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global, ELEMENT_MIKE_1, &rcb, sizeof(rcb));
// check err
AudioUnitConnection conn;
conn.sourceAudioUnit = mCvtUnit;
conn.sourceOutputNumber = 0;
conn.destInputNumber = ELEMENT_SPKR_0;
err = AudioUnitSetProperty(mIoUnit, kAudioUnitProperty_MakeConnection,
kAudioUnitScope_Global, ELEMENT_SPKR_0, &conn, sizeof(conn));
// check err
rcb.inputProc = renderCallback;
rcb.inputProcRefCon = (__bridge void*) self;
err = AudioUnitSetProperty(mCvtUnit, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global, 0, &rcb, sizeof(rcb));
// check err
This fails exactly the same way that AUGraphConnectNodeInput() fails – the input callback is called, but the render callback is silently never called.
I’ve triple checked my code for typos and cut-and-paste-itis but as always there could be something. I’ve pored over the Learning Core Audio book by Adamson and Avila to no avail. The rest of the test application is the same code everywhere
else – not a copy, but the actual same code.
At this point I have something that works – that is, a callback that emulates a connection – so I can move forward. But it bugs the living daylights out of me that the connection doesn’t work. Does anyone have any ideas?
Thank you very much,
Steven J. Clark
VGo Communications