【发布时间】:2017-04-28 13:00:30
【问题描述】:
Apple 建议不要在 AudioUnit 输入或渲染回调中使用 Objective-C 和 Swift。所以回调主要是用 C 语言编写的,我们可以快速复制数据并将该数据传递给辅助线程进行处理。为了在 C 和 Objective C 之间共享变量,建议使用 inRefCon 作为指向 Controller 对象的指针,然后访问它的变量。在下面的代码中,我访问了 MyController 对象的两个成员变量 - muteAudio 和回调队列。这不是完整的代码,只是一个突出问题的示例。
static OSStatus renderCallback (void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
MyController* THIS = (MyController *)inRefCon;
if (!THIS->muteAudio) {
for (UInt32 i=0; i<ioData->mNumberBuffers; ++i)
memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
return noErr;
}
OSStatus status = AudioUnitRender(THIS->mAudioUnit,
ioActionFlags,
inTimeStamp,
kInputBus,
inNumberFrames,
ioData);
if (status != noErr) {
// printf("Render error %d", status);
}
dispatch_async(THIS->mCallbackQueue,^{
//Execute some code
if (THIS->mActive) {
....
}
});
return noErr;
}
我的问题:
一个。诸如 THIS->silentAudio 之类的访问 MyController 实例成员变量的调用与访问属性的 Objective C 消息传递有何不同?我的理解是像 THIS->silentAudio 这样的调用实际上是在指针位置直接访问内存,而不是 Objective C 消息传递,但只是为了确认这是否正确。
b.如何将上述 (THIS->silentAudio) 准确地翻译成 Swift? Swift 运行时是否会像 Objective C 一样使用指针而不是消息传递来访问 MyController 的私有变量?
c。在 Swift 的情况下,隐式/显式展开能否对性能产生影响?
请原谅我对 Swift 的了解,因为我是新手。
编辑:根据hotpaw2的回答,我将代码翻译如下:
func renderCallback(inRefCon:UnsafeMutableRawPointer, ioActionFlags:UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp:UnsafePointer<AudioTimeStamp>,
inBusNumber:UInt32,
inNumberFrames:UInt32,
ioData:UnsafeMutablePointer<AudioBufferList>?) -> OSStatus
{
let controller = unsafeBitCast(inRefCon, to: MyController)
if !controller.muteAudio {
....
}
return noErr;
}
我现在的疑问是 controller.muteAudio 是否确实被 Swift 编译器翻译为访问内存 baseAddress + offset 或者它可以是 Swift 消息传递。
【问题讨论】:
-
控制器是 C 结构吗?然后确定。如果没有,Swift 编译器不会对访问做出这样的保证。
-
不,它不是 C 结构,我把它做成了一个继承自 NSObject 的类。所以我的结论是最好按照你的建议把它变成一个 C 结构。
-
实际上,简单的 NSObjects 通常被实现为 C 结构体。但是,如果您想确保 Swift 代码不会尝试通过 getter/setter 访问它们,您可能想要声明简单的实例变量而不是使用属性(或从 Swift 中隐藏属性和方法)。
-
它们是简单的变量,但是没有 getter 或 setter 的公共变量。一些变量被声明为私有(设置)公共变量......不确定这是否会造成麻烦,但为了安全起见,我可以将所有变量声明为公共变量。在 Objective-C 中,成员变量都是 var,所以 THIS->memberVar 就像 Struct 一样。 Swift 没有成员变量这样的东西,所以不确定。
标签: objective-c swift3 core-audio avaudiosession audiounit