我想知道PortAudio的PaStreamFinishedCallback
中哪些操作是安全的。我知道通常尝试阻止PaStreamCallback
播放的操作不是一个好主意,因为这可能会导致用户或其他应用程序的音频流出现弹出/故障。同样的限制是否适用于PaStreamFinishedCallback
?我想最终我很好奇是否也在OS的音频线程上调用了该回调。
或者,是否有像Pa_StopStream
这样的函数会阻塞,直到回调返回paComplete
/ paAbort
,但没有引发停止?这实际上是我使用的理想选择,因为我有一个线程是我清理的正确位置。我知道我可以通过向我的线程发出回调信号来完成此操作,然后线程可以调用Pa_StopStream
,但感觉很重。
编辑:为了给我更多关于我的使用的上下文,我有一个环形缓冲区,它包含一些PCM并使用pthread condvar在缓冲区中有空间可用时发出信号。一个线程写入此环,然后PaStreamCallback
读出另一端。当事情结束时,作者在环上设置一个关闭的标志,然后回调消耗剩下的任何东西。我想确保我的戒指消失并且PortAudio冲洗了。回调是唯一知道戒指消退的地方,所以返回paComplete
感觉合适。但后来我需要一些方法来知道释放我的戒指是可以的。
对此的答案是,它高度依赖于主机,即使对于一个主机,行为也可能随时间而变化。我继续阅读实现,我在这里发现了一些有用的信息。
Pa_StopStream
将只调用主机系统的Stop()
行为。我没有阅读所有的实现,但可能大多数都有某种阻止Stop()
。这意味着阻止停止而不实际请求阻止行为是不太可能的。
PaStreamFinishedCallback
也只是主机自己的流停止回调的瘦包装。例如,在OSX Core Audio中,这是Listener
上的kAudioOutputUnitProperty_IsRunning
。这完全取决于主机如何以及何时调用它。我认为这里的智能游戏应该尽可能谨慎 - 假设在这个回调中没有阻塞操作是安全的。
所以,如果你和我一样的情况,一个线程将PCM送入环形缓冲区,而PaStreamCallback
从那个环读取,那么你可能想要
PaStreamFinishedCallback
PaStreamCallback
排出它paComplete
返回PaStreamCallback
PaStreamFinishedCallback
发信号通知pthread_cond_signal
完成工作的生产者线程甚至从音频线程发出信号(和锁定互斥锁)可能是最好的避免,但很难想象还有另一种选择。对于PCM环缓冲器的常规读数,PaStreamCallback
可能在放弃之前旋转一些有限的次数。对于完成信号,生产者线程应该锁定然后立即等待,以便尽可能少地保持锁定。