【发布时间】:2017-07-22 14:17:14
【问题描述】:
我已经用 Swift 编写了一个示例项目来试用相对较新的 Core Audio V3 API 内容。一切似乎都可以创建自定义音频单元并在进程中加载它。但实际的音频渲染并不顺利。我经常读到渲染代码需要使用 C 或 C++,但我也听说 Swift 速度很快,我认为我可以在其中编写一些最小的音频渲染代码。
渲染代码
override var internalRenderBlock: AUInternalRenderBlock {
get {
return {
(_ actionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
_ timeStamp: UnsafePointer<AudioTimeStamp>,
_ frameCount: AUAudioFrameCount,
_ outputBusNumber: Int,
_ bufferList: UnsafeMutablePointer<AudioBufferList>,
_ renderEvent: UnsafePointer<AURenderEvent>?,
_ pull: AudioToolbox.AURenderPullInputBlock?) -> AUAudioUnitStatus in
let bufferList = bufferList.pointee
let theBuffers = bufferList.mBuffers // only one (AudioBuffer) ??
guard let theBufferData = theBuffers.mData?.assumingMemoryBound(to: Float.self) else {
return 1 // come up with better error?
}
let amountFrames = Int(frameCount)
for frame in 0...amountFrames / 2 {
let frame = theBufferData.advanced(by: frame)
frame.pointee = sin(self.phase)
self.phase += 0.0001
}
return noErr
}
}
}
听起来很糟糕
产生的声音不是我所期望的。我最初的想法是 Swift 是错误的选择。然而有趣的是,AudioToolbox 确实为这个AUAudioUnit 的呈现属性提供了一个类型别名,如下所示:
public typealias AUInternalRenderBlock = (UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, AUAudioFrameCount, Int, UnsafeMutablePointer<AudioBufferList>, UnsafePointer<AURenderEvent>?, AudioToolbox.AURenderPullInputBlock?) -> AUAudioUnitStatus
这让我相信也许可以用 Swift 编写渲染代码。
观察到的问题
但是,这里还是有一些问题。 (除了我明显缺乏 Swift 内存管理方面的能力)。
A) 尽管theBuffers 说它的mNumberOfBuffers 是2,theBuffers 最终不是一个数组,而是(AudioBuffer) 类型。我不明白括号的必要性。我找不到第二个AudioBuffer。
B) 更重要的是,当我向我可以访问的AudioBuffer 写入基本的正弦波时,产生的声音会失真且不一致。这会是斯威夫特的错吗?用 Swift 编写任何音频单元渲染代码是不可能的吗?或者在这里做了一些假设以某种方式破坏了我的渲染?
终于
如果只是在 Swift 中编写这部分是不可行的,那么我希望有一些资源可以用于音频单元渲染块的 Swift 和 C 互操作。那么,返回闭包的属性是否可以用 Swift 编写,但闭包的实现会调用 C 语言?还是该属性必须简单地返回一个原型与闭包类型匹配的 C 函数?
提前致谢。
该项目的其余部分可以在here 中查看上下文。
【问题讨论】:
-
在最近一次关于 Core Audio 的 WWDC 会议中,Apple 明确表示要在 C 中执行某些音频上下文代码,而不是 Swift 或 Obj C。(但我关于 Swift 中 V3 渲染的 github gist 似乎无论如何都可以工作。 ..目前...可能会中断)。
-
这一点我已经很清楚了。我被公共“标题”中的 Swift 类型别名吓跑了。为什么会在那里?
标签: swift core-audio audiounit