Windows 使用指向已释放缓冲区的指针存储的 WASAPI 示例

WASAPI sample for Windows Store using pointer to released buffer

我正在使用 Windows 音频会话 (WASAPI) 示例的音频捕获部分,用于 Windows 8.1 商店,最后更新 3/24/2015。我写这篇文章是因为我可以看到一些看似错误或过于复杂的代码示例。我猜那是因为我不完全理解 WASAPI 接口和 Windows 运行时工作队列,所以我希望 Stack Overflow 社区能告诉我为什么这不是一个错误。

他们都在 WASAPICapture.cpp。现在,我将只用最简单(也是最严肃的)示例来试水:将指针指向已释放的缓冲区。

接下来是一些伪代码,用于突出显示有问题的特定行。行号是相对于更完整的代码摘录进一步向下。

P.S。 - 我上网的频率很低,而且我是新手 - 所以请耐心等待我的回复。

Line 1:  hr = m_AudioCaptureClient->GetBuffer( &Data, &FramesAvailable, ...  
         ... returns in Data a pointer to the audio buffer  

Line 21: auto dataByte = ref new Platform::Array<BYTE, 1>( Data, cbBytesToCapture );  
         ... copies from the buffer into a new Platform Array for the GUI's 'scope.  

Line 24: m_AudioCaptureClient->ReleaseBuffer( FramesAvailable );  
         ... releases the buffer  

Line 27: ProcessScopeData( Data, cbBytesToCapture );  
         ... uses the pointer after the underlying buffer has been released!?  

...这里是更完整的代码摘录:

hr = m_AudioCaptureClient->GetBuffer( &Data, &FramesAvailable, &dwCaptureFlags, &u64DevicePosition, &u64QPCPosition );
if (FAILED( hr ))
{
    goto exit;
}

if (dwCaptureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY)
{
    // Pass down a discontinuity flag in case the app is interested and reset back to capturing
    m_DeviceStateChanged->SetState( DeviceState::DeviceStateDiscontinuity, S_OK, true );
    m_DeviceStateChanged->SetState( DeviceState::DeviceStateCapturing, S_OK, false );
}

// Zero out sample if silence
if ( (dwCaptureFlags & AUDCLNT_BUFFERFLAGS_SILENT) || IsSilence )
{
    memset( Data, 0, FramesAvailable * m_MixFormat->nBlockAlign );
}

// Store data in array
auto dataByte = ref new Platform::Array<BYTE, 1>( Data, cbBytesToCapture );

// Release buffer back
m_AudioCaptureClient->ReleaseBuffer( FramesAvailable );

// Update plotter data
ProcessScopeData( Data, cbBytesToCapture );

// Write File and async store
m_WAVDataWriter->WriteBytes( dataByte );

你是对的。

这里有两个问题。

  1. Platform::Array(...) 制作一个副本,这是一个分配。在流线程上分配是一种不好的做法,因为分配可能会阻塞,从而导致故障。
  2. 正在使用数据调用 ProcessScopeData,应用程序不应在调用 ReleaseBuffer() 后读取数据。用 dataBytes 调用它就可以了。