AURenderCallback in Swift

I just found your post while trying to figure out the same (it's not easy finding sample code and examples combining CoreAudio/Audio Unit and Swift).

By looking at this repository and reading (several times :-)) Apples documentation about Using Swift with Cocoa and Objective-C I managed to piece something together. As it says in the section about Function Pointers

When calling a function that takes a function pointer argument, you can pass a top-level Swift function, a closure literal, or nil.

So. Outside of my class I have a method that looks like this:

func renderCallback(inRefCon:UnsafeMutablePointer<Void>,
ioActionFlags:UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp:UnsafePointer<AudioTimeStamp>,
inBusNumber:UInt32,
inNumberFrames:UInt32,
ioData:UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
    let delegate = unsafeBitCast(inRefCon, AURenderCallbackDelegate.self)
    let result = delegate.performRender(ioActionFlags,
        inTimeStamp: inTimeStamp,
        inBusNumber: inBusNumber,
        inNumberFrames: inNumberFrames,
        ioData: ioData)
    return result
}

As you can see, I just call a delegate here. That delegate is declared like so (also outside the class but you already knew that :-))

@objc protocol AURenderCallbackDelegate {
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
    inTimeStamp: UnsafePointer<AudioTimeStamp>,
    inBusNumber: UInt32,
    inNumberFrames: UInt32,
    ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus
}

Doing so enables me to "get back inside my class" by conforming to the AURenderCallbackDelegate like so:

class AudioUnitGraphManager: NSObject, AURenderCallbackDelegate

And then implementing the renderCallback method in my AudioUnitGraphManager class

func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
    print("Hello there!")
    return noErr
}

The final piece of the puzzle is to actually enable the render notify callback which I do like so:

AudioUnitAddRenderNotify(mixerUnit, renderCallback, UnsafeMutablePointer(unsafeAddressOf(self)))

Hopefully this gives you something to continue the struggle with.

Changes in Swift 3

In Swift 3 the declaration for AURenderCallback has changed to this:

typealias AURenderCallback = (UnsafeMutableRawPointer, UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, UInt32, UInt32, UnsafeMutablePointer<AudioBufferList>?) -> OSStatus

Notice the last parameter is now UnsafeMutablePointer<AudioBufferList>? compared to UnsafeMutablePointer<AudioBufferList> before (it is an optional now).

This means that the code now looks like this.

The renderCallback function

func renderCallback(inRefCon:UnsafeMutablePointer<Void>,
ioActionFlags:UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp:UnsafePointer<AudioTimeStamp>,
inBusNumber:UInt32,
inNumberFrames:UInt32,
ioData:UnsafeMutablePointer<AudioBufferList>?) -> OSStatus {
    let delegate = unsafeBitCast(inRefCon, AURenderCallbackDelegate.self)
    let result = delegate.performRender(ioActionFlags,
        inTimeStamp: inTimeStamp,
        inBusNumber: inBusNumber,
        inNumberFrames: inNumberFrames,
        ioData: ioData)
    return result
}

The AURenderCallbackDelegate protocol

@objc protocol AURenderCallbackDelegate {
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
    inTimeStamp: UnsafePointer<AudioTimeStamp>,
    inBusNumber: UInt32,
    inNumberFrames: UInt32,
    ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus
}

The actual implementation of performRender

    func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus {
    print("Hello there!")
    return noErr
}

Enabling the render notify callback

AudioUnitAddRenderNotify(mixerUnit!, renderCallback, Unmanaged.passUnretained(self).toOpaque())