PortAudio的PaStreamFinishedCallback安全操作

时间:2017-12-28 21:49:34

标签: c audio portaudio

我想知道PortAudio PaStreamFinishedCallback中哪些操作是安全的。我知道通常尝试阻止PaStreamCallback播放的操作不是一个好主意,因为这可能会导致用户或其他应用程序的音频流出现弹出/故障。同样的限制适用于PaStreamFinishedCallback吗?我想最终我很好奇是否也在操作系统的音频线程上调用了回调。

或者,是否有一个像Pa_StopStream这样的函数会阻塞,直到回调返回paComplete / paAbort,但不会导致停止?这实际上是我使用的理想选择,因为我有一个线程是我清理的正确位置。我知道我可以通过向我的线程发出回调信号来完成此操作,然后线程可以调用Pa_StopStream,但感觉很重。

编辑:为了给我更多关于我的使用的上下文,我有一个环形缓冲区,它包含一些PCM并使用pthread condvar在缓冲区中有空间可用时发出信号。一个线程写入此环,然后PaStreamCallback读出另一端。当事情结束时,作者在环上设置一个关闭的标志,然后回调消耗剩下的任何东西。我想确保我的戒指消失,而PortAudio正在冲洗。回调是唯一知道戒指何时消失的地方,因此返回paComplete感觉合适。但是我需要一些方法来知道我的戒指可以解除分配。

1 个答案:

答案 0 :(得分:0)

答案是,它很大程度上取决于主机,即使对于一台主机,行为也可能随时间而变化。我继续阅读实现,我在这里发现了一些有用的信息。

Pa_StopStream只会调用主机系统的Stop()行为。我没有阅读所有的实现,但可能大多数都有某种阻塞Stop()。这意味着阻止停止而不实际请求停止将不太可能是受支持的行为。

PaStreamFinishedCallback也只是主机自己的流停止回调的瘦包装器。例如,在OSX Core Audio中,这是Listener上的kAudioOutputUnitProperty_IsRunning。这完全取决于主机如何以及何时调用它。我认为这里的智能游戏应该尽可能谨慎 - 假设在这个回调中没有阻塞操作是安全的。

所以,如果你和我一样的情况,一个线程将PCM送入一个环形缓冲区,而PaStreamCallback从该环读取,那么你可能想要

  • 订阅PaStreamFinishedCallback
  • 生产者线程关闭环形缓冲区并让PaStreamCallback消耗它
  • 当戒指耗尽时,从paComplete返回PaStreamCallback
  • 在我的案例中使用PaStreamFinishedCallback
  • pthread_cond_signal发出工作完成的生产者线程的信号
  • 生产者线程通过取消分配醒来并清理

甚至可以避免从音频线程发出信号(和锁定互斥锁),但很难想象还有其他选择。对于PCM环缓冲区的常规读取,PaStreamCallback可能在放弃之前旋转一些有限次数。对于完成信号,生产者线程应该锁定然后立即等待,以便尽可能少地保持锁定。