我刚刚在试图弄清楚相同的情况下找到了您的帖子(找到结合 CoreAudio/Audio Unit 和 Swift 的示例代码和示例并不容易)。
通过查看this repository 并阅读(多次:-))Apples 关于Using Swift with Cocoa and Objective-C 的文档,我设法拼凑了一些东西。正如它在关于Function Pointers的部分所说的那样
调用带有函数指针参数的函数时,您可以传递顶级 Swift 函数、闭包字面量或 nil。
所以。在我的课堂之外,我有一个看起来像这样的方法:
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
}
如您所见,我只是在这里调用了一个代表。该委托是这样声明的(也在类之外,但你已经知道了:-))
@objc protocol AURenderCallbackDelegate {
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp: UnsafePointer<AudioTimeStamp>,
inBusNumber: UInt32,
inNumberFrames: UInt32,
ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus
}
这样做使我能够通过遵守AURenderCallbackDelegate 来“回到我的班级”,如下所示:
class AudioUnitGraphManager: NSObject, AURenderCallbackDelegate
然后在我的AudioUnitGraphManager 类中实现renderCallback 方法
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
print("Hello there!")
return noErr
}
最后一个难题是实际启用我喜欢的渲染通知回调:
AudioUnitAddRenderNotify(mixerUnit, renderCallback, UnsafeMutablePointer(unsafeAddressOf(self)))
希望这能给你一些东西来继续奋斗。
Swift 3 的变化
在 Swift 3 中,AURenderCallback 的声明已更改为:
typealias AURenderCallback = (UnsafeMutableRawPointer, UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, UInt32, UInt32, UnsafeMutablePointer<AudioBufferList>?) -> OSStatus
请注意,与之前的 UnsafeMutablePointer<AudioBufferList> 相比,最后一个参数现在是 UnsafeMutablePointer<AudioBufferList>?(现在是可选的)。
这意味着代码现在看起来像这样。
renderCallback 函数
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
}
AURenderCallbackDelegate 协议
@objc protocol AURenderCallbackDelegate {
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp: UnsafePointer<AudioTimeStamp>,
inBusNumber: UInt32,
inNumberFrames: UInt32,
ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus
}
performRender的实际实现
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>?) -> OSStatus {
print("Hello there!")
return noErr
}
启用渲染通知回调
AudioUnitAddRenderNotify(mixerUnit!, renderCallback, Unmanaged.passUnretained(self).toOpaque())