Reputation: 75
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
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