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