WASAPI GetNextPacketSize 啥时候返回 0

Posted

技术标签:

【中文标题】WASAPI GetNextPacketSize 啥时候返回 0【英文标题】:When does WASAPI GetNextPacketSize return 0WASAPI GetNextPacketSize 什么时候返回 0 【发布时间】:2016-11-14 10:46:51 【问题描述】:

sample code of WASAPI capture on MSDN,循环直到 GetNextPacketSize 返回 0。 我只是想知道什么时候会发生这种情况:

    如果麦克风上注册了静音,会发生这种情况吗? (在这种情况下,如果我一直在麦克风上发出噪音,它会无限循环吗?) 这取决于我缺少的一些音频捕获基本概念(我对音频 API 很陌生 :))。

【问题讨论】:

【参考方案1】:

API 帮助确定要捕获的数据缓冲区的大小,以便 API 客户端无需猜测或分配过多的缓冲区等。当没有数据要捕获时,API 将返回零(不是单帧)。当/如果您过早调用 API 时,这可能会在正在进行的音频捕获会话中发生,并且基本上预计调用者稍后会再次尝试,因为仍然可以生成新数据。

在某些情况下,零返回可能表示流的结束。具体来说,如果您从环回设备捕获并且没有活动的播放会话可以为环回传递生成数据,则捕获 API 可能会一直不传递任何数据,直到出现新的播放会话。

示例代码循环与Sleep 调用一起检查零数据包大小。这样,循环期望在睡眠时间期间至少生成一些数据,并且在连续生成音频数据的正常条件下,外循环内的每次第一次调用都不会返回零长度。内部循环尝试读取尽可能多的非空缓冲区,直到零表示已准备好交付的所有数据都已返回给客户端。

外循环一直运行,直到接收器通过bDone 变量传递捕获结束事件。这里有一个问题,根据示例代码,内部循环可能会以某种方式滚动而不会进入外部循环 - 并且捕获未正确停止。该示例假定接收器处理数据的速度足够快,因此内部循环可以处理所有当前可用的数据并突破以到达Sleep 调用。也就是说,WASAPI 调用都是非阻塞的,并且假设这些循环运行得非常快,这个想法是音频数据的处理速度比捕获它的速度快,并且循环将大部分线程时间花费在 Sleep 调用中.对于初学者来说,也许不是最好的示例代码。您也可以通过检查内部循环中的bDone 来改进这一点,使其更可靠。

【讨论】:

感谢罗曼的解释。现在我清楚了。但是在示例代码中,“录制停止”场景仍然存在更多混淆。有 2 个循环(检查是否停止的外部 while 循环和检查数据包大小的内部 while 循环)。如果 pMySink 返回 'bDone' 为真并且数据包仍在到来,那么即使 pMySink 发出停止信号,记录仍将继续。另一方面,如果我们在内循环中也检查 bDone,那么如果流中仍有数据要读取,则可能会丢失数据包。 我在上面附加了。 bDone 被假定为“捕获结束”信号,这意味着接收器不需要新数据。显然,通常可以有新的数据可用,尤其是。如果源是实时的。该示例并未考虑到您之后可能需要从您用bDone 指示的点继续捕获。 谢谢,现在我明白了。实际上我正在制作一个音频捕获应用程序,用户可以按下录制和停止按钮来开始和停止录制。记录(WASAPI 捕获)是在单独的非 UI 线程中完成的,UI 将发出记录停止信号,所以我的意图是不捕获额外内容,但也不要有任何中断。您的解释消除了我的困惑,现在我将微调我的实现。

以上是关于WASAPI GetNextPacketSize 啥时候返回 0的主要内容,如果未能解决你的问题,请参考以下文章

WASAPI 捕获的数据包不对齐

使用 WASAPI 录制音频流

WASAPI 的问题

Core Audio (WASAPI) 缓冲区事件计时

C# NAudio asio 和 wasapi

WASAPI 音频设备的同步