Ios 斯威夫特的奥伦德

Ios 斯威夫特的奥伦德,ios,xcode,swift,audiounit,Ios,Xcode,Swift,Audiounit,我正在创建一个使用音频单元的应用程序,虽然Objective-C中有很多代码示例(包括苹果自己的aurioTouch和其他),但我正在尝试用Swift编写整个程序 我已经能够设置我的AUGraph并通过它运行一些音频,但是我似乎无法理解渲染回调的语法。我尝试了几种方法: 方法1:直接创建一个回调 let render : AURenderCallback = { ( inRefCon: UnsafeMutablePointer<Void>, ioActionFlags

我正在创建一个使用音频单元的应用程序,虽然Objective-C中有很多代码示例(包括苹果自己的aurioTouch和其他),但我正在尝试用Swift编写整个程序

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

方法1:直接创建一个回调

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

    return noErr
}
let render:AURenderCallback={(
inRefCon:不可女性化的指针,
ioActionFlags:UnsafemeutablePointer,
inTimeStamp:UnsafePointer,
inBufNumber:UInt32,
inNumberFrames:UInt32,
ioData:Unsameutablepointer)->骨状态
返回noErr
}
我在这个回调中除了返回noErr之外什么都不做,因为我只是想让它工作。但是,编译器返回以下错误:

(非女性化指针, 不可女性化的指针, 不安全指针,UInt32,UInt32, Unsafemeutablepointer)->OSStatus不可转换 "光彩夺目"

文档中的AURenderCallback定义如下:

typealias AURenderCallback = (UnsafeMutablePointer<Void>,UnsafeMutablePointer<AudioUnitRenderActionFlags>,UnsafePointer<AudioTimeStamp>, UInt32, UInt32,UnsafeMutablePointer<AudioBufferList>) -> OSStatus
typealias AURenderCallback=(不安全指针、不安全指针、不安全指针、UInt32、UInt32、不安全指针)->OSStatus
它似乎与我输入的内容相同,尽管可能是我不理解文档要求的内容

方法2:创建一个表示回调函数的函数

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

    return noErr
}
func渲染(
inRefCon:不可女性化的指针,
ioActionFlags:UnsafemeutablePointer,
inTimeStamp:UnsafePointer,
inBufNumber:UInt32,
inNumberFrames:UInt32,
ioData:非女性指针)->OSStatus{
返回noErr
}
这不会作为函数给出任何错误,但当我将其放入inputProc参数中的AURenderCallbackStruct时,我收到一个错误:

找不到类型“AURenderCallbackStruct”的初始值设定项 接受类型为“(inputProc: (非女性化指针, 不可女性化的指针, 不安全指针,UInt32,UInt32, Unsafemeutablepointer)->OSStatus,inputProcRefCon: 零)


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

我刚刚找到了你的帖子,同时试图找出相同的问题(很难找到结合CoreAudio/Audio Unit和Swift的示例代码和示例)

通过查看和阅读(多次:-)有关苹果的文档,我成功地拼凑出了一些东西。正如它在关于
函数指针的章节中所说的那样

调用采用函数指针参数的函数时,可以传递顶级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
}
最后一个难题是实际启用render notify回调,我非常喜欢它:

AudioUnitAddRenderNotify(mixerUnit、renderCallback、unsafemablepointer(unsafeAddressOf(self)))

希望这能给你一些继续奋斗的东西

Swift 3的变化 在Swift 3中,
AURenderCallback
的声明已更改为:

typealias AURenderCallback=(unsafemtablerawpointer,unsafeptablepointer,UnsafePointer,UInt32,unsafemt32,unsafemtablepointer?->OSStatus

请注意,最后一个参数现在是
UnsafeMutablePointer?
,而以前是
UnsafeMutablePointer
(现在是可选参数)

这意味着代码现在看起来像这样

renderCallback
功能
performRender的实际实现

我参加聚会有点晚了,但我找到了一种比上述答案更直接的方法。我们可以使用您可以在callbackStruct中设置的
inRefCon
指针
inRefCon
传递给回调函数,因此如果将
inRefCon
设置为类引用,则可以直接“找到返回类的方法”,而无需与委托进行循环。我是这样做的:

/* below code is inside some function in MyClass */ 

var callbackStruct = AURenderCallbackStruct()

// set inRefCon to reference to self by casting to pointer
callbackStruct.inputProcRefCon = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())

// create our C closure
callbackStruct.inputProc = {
             (inRefCon : UnsafeMutableRawPointer,
              ioActionFlags : UnsafeMutablePointer<AudioUnitRenderActionFlags>,
              inTimeStamp : UnsafePointer<AudioTimeStamp>,
              inBusNumber : UInt32,
              inNumberFrames : UInt32,
              ioData : UnsafeMutablePointer<AudioBufferList>?) -> OSStatus in
            
            // get reference to my class by de-referencing inRefCon
            let _self = Unmanaged<MyClass>.fromOpaque(inRefCon).takeUnretainedValue()
            // time to profit with reference to our class _self
            // ...
            return 0
}

// set callback
AudioUnitSetProperty(audioUnit!,
                     kAudioUnitProperty_SetRenderCallback,
                     kAudioUnitScope_Global,
                     0,
                     &callbackStruct,
                     UInt32(MemoryLayout.size(ofValue: callbackStruct)))

/*下面的代码位于MyClass*中的某个函数内
var callbackStruct=AURenderCallbackStruct()
//通过强制转换到指针,将inRefCon设置为引用self
callbackStruct.inputProclefcon=UnsafementableRawPointer(Unmanaged.passUnretained(self).toOpaque())
//创建我们的C闭包
callbackStruct.inputProc={
(在refcon:unsafemeutablerawpointer中,
ioActionFlags:UnsafemeutablePointer,
inTimeStamp:UnsafePointer,
InBunsNumber:UInt32,
inNumberFrames:UInt32,
ioData:Unsameutablepointer?->OSStatus in
//通过反引用inRefCon获取对我的类的引用
let _self=Unmanaged.from不透明(inRefCon).takeUnrepainedValue()
//是时候根据我们班的情况获利了
// ...
返回0
}
//设置回调
AudioUnitSetProperty(audioUnit!,
kAudioUnitProperty_SetRenderCallback,
考迪翁尼茨考普大学全球,
0,
&调用backstruct,
UInt32(MemoryLayout.size(of值:callbackStruct)))

使用委托是一种有趣的方法。但是,在尝试启用回调时,我收到以下错误:“找不到接受类型为”(UnsafeMutablePointer)的参数列表的类型“UnsafeMutablePointer”的初始值设定项。”“我已经四处寻找了如何解决此问题,但我非常困惑。至少可以说,这些指针类型令人沮丧。为了调试的目的,我尝试创建一个AURenderCallbackStruct对象,以便可以使用点语法单独定义参数。这很好:“renderCallbackStruct”。
func performRender(ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>, inTimeStamp: UnsafePointer<AudioTimeStamp>, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
    print("Hello there!")
    return noErr
}
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
}
    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())
/* below code is inside some function in MyClass */ 

var callbackStruct = AURenderCallbackStruct()

// set inRefCon to reference to self by casting to pointer
callbackStruct.inputProcRefCon = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())

// create our C closure
callbackStruct.inputProc = {
             (inRefCon : UnsafeMutableRawPointer,
              ioActionFlags : UnsafeMutablePointer<AudioUnitRenderActionFlags>,
              inTimeStamp : UnsafePointer<AudioTimeStamp>,
              inBusNumber : UInt32,
              inNumberFrames : UInt32,
              ioData : UnsafeMutablePointer<AudioBufferList>?) -> OSStatus in
            
            // get reference to my class by de-referencing inRefCon
            let _self = Unmanaged<MyClass>.fromOpaque(inRefCon).takeUnretainedValue()
            // time to profit with reference to our class _self
            // ...
            return 0
}

// set callback
AudioUnitSetProperty(audioUnit!,
                     kAudioUnitProperty_SetRenderCallback,
                     kAudioUnitScope_Global,
                     0,
                     &callbackStruct,
                     UInt32(MemoryLayout.size(ofValue: callbackStruct)))