我正在写一个程序,它使用WASAPI环回捕获来捕获Windows设备上的输出。原则上它工作正常,但每当我试图调试它时,它就会从断点继续后中断。
我可以在Windows自己的示例代码中重现这一点:我使用的是CaptureSharedEventDriven sample。
然后我遵循instructions to change this demo to use loopback,它很简单:
- 在
GetDefaultAudioEndpoint
中将eCapture
更改为eRender
- 将
EnumAudioEndpoints
中的eCapture
更改为eRender
- 将
AUDCLNT_STREAMFLAGS_LOOPBACK
添加到IAudioClient::Initialize
调用
这样就可以正确地捕获音频输出。但是,当我在CWASAPICapture::Start(...)
的末尾(示例中的第262行)断点,然后继续时,捕获就变成了垃圾。捕获的音频每1056个样本(这也是IAudioClient的缓冲区大小)显示不连续性,并且每次迭代丢失384个样本。
我可以通过添加以下调试代码来证明这一点:
[WASAPICapture.cpp, line 358]
hr = _CaptureClient->GetBuffer(&pData, &framesAvailable, &flags, NULL, NULL);
if (SUCCEEDED(hr))
{
UINT32 framesToCopy = min(framesAvailable, static_cast<UINT32>((_CaptureBufferSize - _CurrentCaptureIndex) / _FrameSize));
if (framesToCopy != 0)
{
//
// Adding this in order to trace the output issue:
//
if (flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) {
printf("Discontinuity detected, writing %d samples\n", framesAvailable);
}
else {
printf("Correct render, writing %d samples\n", framesAvailable);
}
命中断点后,对于捕获的其余部分,输出现在将为:
Discontinuity detected, writing 480 samples
Correct render, writing 480 samples
Discontinuity detected, writing 96 samples
Discontinuity detected, writing 480 samples
Correct render, writing 480 samples
Discontinuity detected, writing 96 samples
Correct render, writing 480 samples
Correct render, writing 480 samples
Discontinuity detected, writing 96 samples
etc...
如何使WASAPI从此错误中恢复?
1条答案
按热度按时间bvhaajcl1#
此MS示例包含一个错误,并且缺少一行基本代码。可以在另一个示例中找到正确的实现版本(尽管用例略有不同):ApplicationLoopback
应在
GetBuffer()
和ReleaseBuffer()
代码周围添加while-loop:实际上,ApplicationLoopback示例中的这一行带有大量注解,并附有解释:
总之:音频引擎不需要给予你一个很好的数据包,比如480个样本,可以把它们分成不同的块。由于某种原因,调试断点代码会让它处于这样的状态。如果没有这个while-loop来检查
GetNextPacketSize
,它就无法从中恢复。将此行添加到CaptureSharedEventDriven示例可修复此问题。