I have an AUGraph setup with a couple of File Player audio units feeding into a MultiChannelMixer unit, which then feeds into a Remote I/O output. This setup has worked just fine.
Now I've been struggling to add a callback in such a way that I can calculate the sound level of the individual file players.
private let meteringCallback: AURenderCallback = { (
inRefCon,
ioActionFlags,
inTimeStamp,
inBusNumber,
frameCount,
ioData ) -> OSStatus in
var status = noErr
var track: AUTrack = unsafeBitCast(inRefCon, to: AUTrack.self)
status = AudioUnitRender(track.fileAU!,
ioActionFlags,
inTimeStamp,
inBusNumber,
frameCount,
ioData!);
var samples = [Float]()
let ptr = ioData!.pointee.mBuffers.mData?.assumingMemoryBound(to: Float.self)
samples.append(contentsOf: UnsafeBufferPointer(start: ptr, count: Int(frameCount)))
// ... fancy algorithm calculating DB value ...
}
AUTrack simple holds information about that particular track. Passing the entire class instance to the callback (as is usually done in examples) would not make sense here because there are multiple file players.
Now I need to set this callback somewhere, so I can capture the value off each of the file players feeding into the mixer. Yet I keep getting a -10877 (invalid element) error when I try to do that.
I try to setup the metering callback with this.
// Set metering callback
var meteringCallbackStruct = AURenderCallbackStruct(inputProc: meteringCallback,
inputProcRefCon: &self.tracks[1])
status = AudioUnitSetProperty(self.tracks[1].fileAU!,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Output,
0,
&meteringCallbackStruct,
UInt32(MemoryLayout<AURenderCallbackStruct>.size))
I'm not quite sure how to solve this.
And wouldn't this callback "eat" the samples unless I somehow pass them back to the mixer unit?