【发布时间】:2014-08-14 12:08:36
【问题描述】:
嘿嘿。我想用 Swift 中的新 AVAudioEngine 实现一个实时音频应用程序。有人对新框架有经验吗?实时应用程序如何工作?
我的第一个想法是将(处理后的)输入数据存储到 AVAudioPCMBuffer 对象中,然后让它由 AVAudioPlayerNode 播放,正如您在我的演示课程中看到的那样:
import AVFoundation
class AudioIO {
var audioEngine: AVAudioEngine
var audioInputNode : AVAudioInputNode
var audioPlayerNode: AVAudioPlayerNode
var audioMixerNode: AVAudioMixerNode
var audioBuffer: AVAudioPCMBuffer
init(){
audioEngine = AVAudioEngine()
audioPlayerNode = AVAudioPlayerNode()
audioMixerNode = audioEngine.mainMixerNode
let frameLength = UInt32(256)
audioBuffer = AVAudioPCMBuffer(PCMFormat: audioPlayerNode.outputFormatForBus(0), frameCapacity: frameLength)
audioBuffer.frameLength = frameLength
audioInputNode = audioEngine.inputNode
audioInputNode.installTapOnBus(0, bufferSize:frameLength, format: audioInputNode.outputFormatForBus(0), block: {(buffer, time) in
let channels = UnsafeArray(start: buffer.floatChannelData, length: Int(buffer.format.channelCount))
let floats = UnsafeArray(start: channels[0], length: Int(buffer.frameLength))
for var i = 0; i < Int(self.audioBuffer.frameLength); i+=Int(self.audioMixerNode.outputFormatForBus(0).channelCount)
{
// doing my real time stuff
self.audioBuffer.floatChannelData.memory[i] = floats[i];
}
})
// setup audio engine
audioEngine.attachNode(audioPlayerNode)
audioEngine.connect(audioPlayerNode, to: audioMixerNode, format: audioPlayerNode.outputFormatForBus(0))
audioEngine.startAndReturnError(nil)
// play player and buffer
audioPlayerNode.play()
audioPlayerNode.scheduleBuffer(audioBuffer, atTime: nil, options: .Loops, completionHandler: nil)
}
}
但这与实时相去甚远,效率也不高。有什么想法或经验吗?而且没关系,如果你更喜欢 Objective-C 或 Swift,我很感谢所有笔记、评论、cmets、解决方案等。
【问题讨论】:
-
Objective-C 不推荐用于实时编程。我还不知道 Apple 在 Swift 实时编程方面采取了官方立场,但在 prod.lists.apple.com/archives/coreaudio-api/2014/Jun/… 上有一些讨论
-
感谢您提供的链接,但从本次讨论到现在的要点:没有人知道任何事情。 ;-) 但问题是关于新的编程语言,或者如果 Objective-C 能够实时处理,那么我如何将 AVAudioEngine 用于实时应用程序,这是 Apple 在其 WWDC14 会议号中宣传的。 502.跨度>
-
Objective-C 可用于编写实时音频应用程序,但在 Core Audio 的
IOProcs中可以执行的操作有一些限制。例如,没有内存分配,没有锁,没有 Objective-C 方法调用等。参见rossbencina.com/code/… 我想在内部AVAudioEngine在实时方法中只使用 C,我也打赌水龙头有相同的限制IOProcs. -
Michael,对于缓冲区抽头,我建议使用简单明了的 C。由于 ARC、内部锁和内存分配,Swift 和 ObjC 都引入了不可预测的开销。 C 最适合用于处理缓冲区。在将数据提供给主线程进行显示时,请使用无锁循环缓冲区和 ObjC。但是你为什么要自己复制输入缓冲区呢?您可以将
AVAudioEngine.inputNode直接连接到AVAudioEngine.outputNode。 -
您所说的“实时”是指录制,并执行诸如绘制麦克风信号的波形之类的操作,或者将捕获的音频即时馈送到语音识别器?如果是这样,请告诉我,我会发布我的代码作为答案。
标签: swift avfoundation real-time core-audio avaudioengine