我是按照iOS《音频队列编程指南--播放音频》来做的。在指南的结尾处,有调用了 CFRunLoopRunInMode()
踏踏实实 启动和运行音频队列:
do { // 5
CFRunLoopRunInMode ( // 6
kCFRunLoopDefaultMode, // 7
0.25, // 8
false // 9
);
} while (aqData.mIsRunning);
//...
关于第6行的文档中说:"CFRunLoopRunInMode函数运行包含音频队列的线程的运行循环。"但我的方法返回时,那个运行循环不是照样执行吗?上面的代码是在我的应用中按下播放按钮后由主线程执行的。
现在我很难理解这些对 CFRunLoopRunInMode()
是很好的,因为它们的缺点是我的播放按钮不能正确更新(在音频播放的整个过程中,它看起来是被按下的),而且没有积极的效果,也就是说,如果我把do-while-loop从我的代码中删除,同时也把对 CFRunLoopRunInMode()
而不是直接从这个方法中返回.好吧,这指向了一个明显的解决方案,即简单地保持这些调用被删除,因为这不会产生问题。谁能解释一下为什么这段代码会出现在苹果官方指南中关于在iOS中使用音频队列进行音频播放的内容?
编辑一下
我只是看到在Mac OS X中,存在着和iOS上一样的音频队列API,而iOS的指南似乎是复制粘贴的重复。Mac OS指南. 这让我怀疑这些对运行循环的调用只在Mac OS中需要,而在iOS中不再需要,例如,因为否则Mac OS应用程序将退出或类似的东西。谁能验证一下或者排除一下?
@bunnyhero说的没错。CFRunLoopRunInMode()
通常用于命令行示例
https:/github.comabboodLearning-Core-Audio-Book-Code-SampleblobmasterCH05_PlayerCH05_Playermain.c。
只要您的 AudioQueueRef
不被重新分配,您不必使用 CFRunLoopRunInMode()
在IOS...
我所做的是为音频队列创建一个单独的类,只要我的类指针和 AudioQueueRef
我可以播放、暂停、恢复、停止等。
与OP的问题相关,关于AQ封锁UI线程的问题,为了进一步解放AQ用户,使其免于抄袭。所举的CoreAudio AQ例子 盲目地。
我要补充的是,该示例将AQ配置为在主线程中的当前运行循环中运行,即在 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内部线程中运行,使你的应用更有效率。