Swift中的AURenderCallback

Fir*_*ers 5 xcode audiounit ios swift

我正在创建一个使用Audio Units的应用程序,虽然Objective-C中有很多代码示例(包括Apple自己的aurioTouch等),但我试图在Swift中编写整个代码.

我已经能够设置我的AUGraph并通过它运行一些音频,但我似乎无法弄清楚渲染回调的语法.我尝试了几种方法:

方法1:直接创建AURenderCallback

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

    return noErr
}
Run Code Online (Sandbox Code Playgroud)

因为我只是想让它工作,所以除了在此时返回noErr之外我在这个回调中什么都不做.但是,编译器返回以下错误:

(UnsafeMutablePointer,UnsafeMutablePointer,UnsafePointer,UInt32,UInt32,UnsafeMutablePointer) - > OSStatus'无法转换为'AURenderCallback

文档中AURenderCallback的定义如下:

typealias AURenderCallback = (UnsafeMutablePointer<Void>,UnsafeMutablePointer<AudioUnitRenderActionFlags>,UnsafePointer<AudioTimeStamp>, UInt32, UInt32,UnsafeMutablePointer<AudioBufferList>) -> OSStatus
Run Code Online (Sandbox Code Playgroud)

它似乎与我输入的相同,尽管可能是我不明白文档要求的内容.

方法2:创建表示AURenderCallback的函数

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

    return noErr
}
Run Code Online (Sandbox Code Playgroud)

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

找不到类型'AURenderCallbackStruct'的初始值设定项,它接受类型'的参数列表'(inputProc:(UnsafeMutablePointer,UnsafeMutablePointer,UnsafePointer,UInt32,UInt32,UnsafeMutablePointer) - > OSStatus,inputProcRefCon:nil)

我没有找到很多在Swift中创建AURenderCallbacks的例子,与Objective-C相比,语法似乎有很大差异.任何帮助,将不胜感激.

pbo*_*dsk 7

我刚刚发现你的帖子,同时试图找出相同的结果(找到结合CoreAudio/Audio Unit和Swift的示例代码和示例并不容易).

通过查看此存储库并阅读(几次:-))关于将Swift与Cocoa和Objective-C一起使用的 Apples文档我设法将某些内容组合在一起.正如它在章节中所述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
}
Run Code Online (Sandbox Code Playgroud)

如你所见,我只是在这里召集代表.那个代表是这样声明的(也在课外,但你已经知道:-))

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

这样做使我能够通过符合这样的方式"回到我的班级" AURenderCallbackDelegate:

class AudioUnitGraphManager: NSObject, AURenderCallbackDelegate

然后renderCallback在我的AudioUnitGraphManager课堂上实现该方法

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

最后一个难题是实际启用渲染通知回调,我喜欢这样:

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
}
Run Code Online (Sandbox Code Playgroud)

AURenderCallbackDelegate协议

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

实际执行 performRender

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

启用渲染通知回调

AudioUnitAddRenderNotify(mixerUnit!, renderCallback, Unmanaged.passUnretained(self).toOpaque())
Run Code Online (Sandbox Code Playgroud)