我已經在Swift中編寫了一個示例項目來嘗試使用相對較新的Core Audio V3 API。一切似乎都圍繞創建自定義音頻單元並在過程中加載它。但實際的音頻渲染效果並不理想。我經常讀到渲染代碼需要使用C或C++,但我也聽說Swift速度很快,並認爲我可以在其中編寫一些最小的音頻渲染代碼。音頻單元在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
的渲染屬性typealias:
public typealias AUInternalRenderBlock = (UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, AUAudioFrameCount, Int, UnsafeMutablePointer<AudioBufferList>, UnsafePointer<AURenderEvent>?, AudioToolbox.AURenderPullInputBlock?) -> AUAudioUnitStatus
這將導致我認爲,這也許是可以寫在斯威夫特渲染代碼。
觀察到的問題
但是,仍然有一些事情在這裏出錯。 (除了我明顯缺乏Swift內存管理能力外)。
A)
儘管theBuffers
稱其mNumberOfBuffers
爲2,theBuffers
卷取不是陣列而是(AudioBuffer)
類型。我不明白括號的必要性。我找不到第二個AudioBuffer
。
B)
更重要的是,當我寫一個基本的正弦波到我可以訪問的一個AudioBuffer
時,產生的聲音是失真和不一致的。這可能是斯威夫特的錯嗎?在Swift中編寫任何音頻單元渲染代碼是不可能的?或者在這裏做出了一些假設,以某種方式打破我的渲染?
最後
如果只是寫這部分斯威夫特是不可行的話,那麼我想對互操作斯威夫特和C音頻單元渲染塊的一些資源。那麼,返回閉包的屬性是否可以用Swift編寫,但閉包的實現是否會調用C?還是該屬性不得不簡單地返回一個C函數,該函數的原型與閉包的類型相匹配?
在此先感謝。
對於上下文,本項目的其餘部分可以看到here。
[在Swift中使用AudioBufferList](https://stackoverflow.com/questions/24838106/using-audiobufferlist-with-swift) –
在最近一次關於Core Audio的WWDC會議中,Apple明確表示要做某些音頻上下文代碼在C中,而不是Swift或Obj C.(但我的github要求在Swift中使用V3渲染似乎無論如何...當前...可能會中斷)。 – hotpaw2
在這一點上我已經清楚了。我在公開的「標題」中被Swift typealias拋棄了。爲什麼會那樣? –