9

我正在关注 iOS“音频队列编程指南 - 播放音频”。在指南的结尾处,在Start and Run an Audio QueueCFRunLoopRunInMode()步骤中有调用:

do {                                               // 5
    CFRunLoopRunInMode (                           // 6
        kCFRunLoopDefaultMode,                     // 7
        0.25,                                      // 8
        false                                      // 9
    );
} while (aqData.mIsRunning);
//...

关于第 6 行的文档说:“CFRunLoopRunInMode 函数运行包含音频队列线程的运行循环。” 但是,当我的方法返回时,该运行循环是否仍然执行?上面的代码在我的应用程序中按下播放按钮时由主线程执行。

现在我很难理解这些调用CFRunLoopRunInMode()有什么好处,因为它们的缺点是我的播放按钮没有正确更新(它看起来在音频播放的整个过程中都被按下)并且没有正面效果,即,如果我从我的代码中删除 do-while-loop 以及对的调用CFRunLoopRunInMode(),而是直接从此方法返回,音频也可以很好地播放。好吧,这指出了简单地删除这些调用的明显解决方案,因为这不会造成问题。有人能解释一下为什么这段代码包含在 Apple 的官方指南中,关于在 iOS 中使用音频队列进行音频播放吗?

编辑:

我只是看到在 Mac OS X 中,存在与 iOS 上相同的音频队列 API,并且 iOS 指南似乎是Mac OS 指南的复制粘贴副本。这使我怀疑这些对运行循环的调用仅在 Mac OS 中需要,而在 iOS 中不再需要,例如因为否则 Mac OS 应用程序将退出或类似的东西。有人可以验证或排除吗?

4

3 回答 3

2

@bunnyhero 是对的,CFRunLoopRunInMode()通常用于命令行示例

https://github.com/abbood/Learning-Core-Audio-Book-Code-Sample/blob/master/CH05_Player/CH05_Player/main.c

只要你AudioQueueRef没有被释放,你就不必CFRunLoopRunInMode()在IOS中使用......

我所做的是为音频队列创建一个单独的类,只要我的类指针AudioQueueRef被分配,我就可以播放、暂停、恢复、停止等......

于 2015-05-21T20:44:36.610 回答
0

与 OP 的问题有关,关于 AQ 阻塞 UI 线程,以进一步使 AQ 用户免于复制盲目引用的 CoreAudio AQ 示例,

我要补充一点,该示例将 AQ 配置为在主线程的当前 runloop 中运行,在Listing 3-11 Creating a playback audio queue

AudioQueueNewOutput (                                // 1
    &aqData.mDataFormat,                             // 2
    HandleOutputBuffer,                              // 3
    &aqData,                                         // 4
    CFRunLoopGetCurrent (),                          // 5
    kCFRunLoopCommonModes,                           // 6
    0,                                               // 7
    &aqData.mQueue                                   // 8
);

,见上面的参数值CFRunLoopGetCurrent ()。文字说明

当前运行循环,以及将在其上调用音频队列播放回调的运行循环。

查看函数原型:

OSStatus AudioQueueNewOutput(
    const AudioStreamBasicDescription *inFormat,   // 2
    AudioQueueOutputCallback inCallbackProc,       // 3
    void *inUserData,                              // 4
    CFRunLoopRef inCallbackRunLoop,                // 5
    CFStringRef inCallbackRunLoopMode,             // 6
    UInt32 inFlags,                                // 7
    AudioQueueRef  _Nullable *outAQ                // 8
);

如果将#5 替换为NULL,则 AQ 将在 CoreAudio 内部线程中运行,从而提高应用程序的效率。

于 2020-06-09T13:20:49.913 回答
0

CFRunLoopRunInMode需要在代码执行结束时(例如,在运行终端应用程序时)保持音频队列处于活动状态。iOS 应用程序包含一个生命周期:要使音频队列保持活动状态,您只需将其声明AudioQueueRef为成员变量。否则,如果它在方法范围内声明,它会在执行该方法后被销毁 - 因此,它将停止 - 除非您使用CFRunLoopRunInMode.

总而言之,只要您在未从内存中释放的实例化类中保存一个成员变量AudioQueueRef- 或新的 - ,就不需要a 。AVAudioEngineCFRunLoopRunInMode

于 2020-08-24T17:38:31.490 回答