PortAudio 内部发生的事情取决于许多因素,包括:
- PortAudio 正在与哪个原生音频 API 对话
- 您传递给什么缓冲区大小和延迟参数
Pa_OpenStream()
- 音频硬件及其驱动程序的功能,包括其支持的缓冲区大小、缓冲模型和时序特性。
在某些情况下,PortAudio 会从本机音频 API 请求更大的缓冲区,然后快速连续多次调用 PortAudio 用户回调。如果您选择了较小的回调缓冲区大小和较长的延迟,则可能会发生这种情况。
另一种情况是本机音频 API 不支持您为回调大小(framesPerBuffer
参数 to Pa_OpenStream()
)请求的缓冲区大小。在这种情况下,PortAudio 将被迫使用驱动程序支持的缓冲区大小,然后在该缓冲区大小和回调缓冲区大小之间“调整”。这种适应过程会导致不规则的时序。
还有一种可能是原生音频 API 使用了一个大的环形缓冲区。每次 PortAudio 轮询本机主机 API 时,它都会根据需要多次调用您的回调来填充本机环形缓冲区。在这种情况下,不规则的时间与轮询率有关。
以上不是唯一的可能性。
由于上述原因之一,对您的情况发生的事情的一种可能的解释是,PortAudio 快速连续调用您的回调 3 次(猜测是本机缓冲区大小是您的回调缓冲区大小的 3 倍)。
另一种可能性是本机音频子系统不规则地向 PortAudio 发出信号。如果 PortAudio 下方的系统层正在执行与我上面描述的类似类型的缓冲,则可能会发生这种情况。例如,我已经看到 Windows 7 上的 DirectSound 会发生这种情况。ASIO4ALL 驱动程序将表现出 +/- 1ms 的抖动(这不是您所看到的)。
您可以尝试将请求的流延迟降低到 0,看看是否会改变结果。这将强制使用双缓冲,这可能会也可能不会产生稳定的输出。另一件要尝试的事情是使用paFramesPerBufferUnspecified
参数,这将导致使用本机缓冲区大小调用回调 - 然后您可以观察是否有更大的周期性,缓冲区大小是多少,以及缓冲区大小是否与回调不同回调。
您没有说明您针对的是哪个操作系统和主机 API,因此很难提供比上述更具体的细节。
PortAudio wiki 上详细描述了各种 PortAudio 主机 API 后端使用的内部缓冲模型。
回答一个相关问题:为什么会这样?除了它是本机音频子系统的较低层或缓冲区适应过程的函数的情况外,它通常是指定较大的建议延迟的结果Pa_OpenStream()
。如果指定的延迟非常高,一些 PortAudio 主机 API 会放宽缓冲周期,以减少高频定时器回调可能导致的系统负载。