AURenderCallback在Swift中

我正在创build一个使用audio单元的应用程序,尽pipe在Objective-C(包括苹果自己的aurioTouch和其他)中有很多代码示例,但我试图在Swift中编写整个代码。

我已经能够build立我的AUGraph并通过它运行一些audio,但我似乎无法弄清楚回显的callback语法。 我已经尝试了几种方法:

方法1:直接创build一个AURenderCallback

let render : AURenderCallback = { ( inRefCon: UnsafeMutablePointer<Void>, ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBufNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus in return noErr } 

在这个callback中,除了返回noErr之外,我什么都没有做,因为我只是想让它工作。 但是,编译器返回以下错误:

(UnsafeMutablePointer,UnsafeMutablePointer,UnsafePointer,UInt32,UInt32,UnsafeMutablePointer) – > OSStatus'不能转换为'AURenderCallback

AURenderCallback在文档中的定义是这样的:

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

这似乎与我所input的一样,虽然可能是我不明白文档要求什么。

方法2:创build一个代表AURenderCallback的函数

 func render( inRefCon: UnsafeMutablePointer<Void>, ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBufNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus { return noErr } 

这不会给任何错误作为一个函数,但是当我把它放入inputProc参数AURenderCallbackStruct中时,我收到一个错误:

(InputProc:(UnsafeMutablePointer,UnsafeMutablePointer,UnsafePointer,UInt32,UInt32,UnsafeMutablePointer) – > OSStatus,inputProcRefCon:nil)无法findtypes为“AURenderCallbackStruct”的初始化程序。

我还没有发现在Swift中创buildAURenderCallbacks的很多例子,与Objective-C相比,在语法上似乎有很大的不同。 任何帮助,将不胜感激。

我只是find你的文章,试图找出相同的(这是不容易find示例代码和CoreAudio /audio单元和Swift结合的例子)。

通过查看这个仓库和阅读(几次:-))苹果关于使用cocoa和Objective-C的Swift的文档,我设法把东西拼凑在一起。 正如它在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

然后在我的renderCallback类中实现renderCallback方法

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

拼图的最后一部分是实际启用渲染通知callback,我这样做:

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 } 

启用渲染通知callback

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