如何具有高优先级线程进行音频处理

时间:2019-07-18 15:03:33

标签: ios swift avaudioengine avaudioplayernode

我有一个iOS应用程序,正在使用AVAudioEngine播放音频。我将AudioFile中的帧读取到AVAudioPCMBuffer中,然后将缓冲区发布到AVAudioPlayerNode.scheduleBuffer中。我在DispatchQueue上读取帧。我的问题是,当应用程序还有很多其他工作要做时(与服务器同步并下载文件),DispatchQueue上的读取帧会延迟几秒钟执行,这会导致声音中断。 我已将DispatchQueueQos设置为尽可能高的.userInteractive,并且我在应用中没有其他具有相同qos的队列,但是有时仍需要几秒钟来在该队列上执行代码。

对此有解决方案吗?是否可以通过某种方式告诉操作系统该队列用于音频或类似内容?

注意:如果应用程序运行一些繁重的后台操作,则AVPlayer不会出现此问题。

编辑:一些代码可以更好地理解。问题在于有时将任务发布到队列中需要花费几秒钟的时间(从注释1到注释2)。

var audioProcessingQueue = DispatchQueue(label: "audioProcessing", qos: .userInteractive)
var player = AVAudioPlayerNode()
//comment 1
self.audioProcessingQueue.async(flags: .barrier) {
    //comment 2
    //some buffer processing here...
    player.scheduleBuffer(buffer, at: nil)
}

谢谢

1 个答案:

答案 0 :(得分:0)

两件事:

1)您提供的代码排在什么队列上? 因为听起来像那个队列可能与您的下载任务共享其质量。 调度到另一个队列确实需要多个步骤。因此,仅由于传递了“ comment1”,其他队列之一可能会在分配时获得线程时间来做一些工作。是的,这会导致某些延迟,这似乎是最可能的原因。

2)WWDC 2016视频Concurrent Programming with GCD in Swift 3可能会有所帮助。 如果cpu的所有核心已经在忙于其他任务,则将新的东西分派到更高优先级的队列中不会立即自动启动任务。 GCD会尽力而为,但是也许您在其他队列上的工作非常紧张/正在做中断会导致问题的事情。

因此,如果必须立即启动某些内容,请确保一个CPU内核/线程处于空闲状态。我会尝试使用OperationQueue并设置其maxConcurrentOperationCount。然后将所有下载操作放到该操作队列中,让内核/线程准备好启动音频。

但是,我认为选项2在这里无效,因为您说的是有时需要几秒钟。