I'm working with the Audio Capture portion of the Windows Audio Session (WASAPI) sample for Windows 8.1 Store, last update 3/24/2015. I'm writing because I can see examples of code that appears to be wrong or overly complicated. I'm guessing that's because I don't fully understand the WASAPI interface and the Windows Runtime work queues, so I'm hoping the Stack Overflow community can tell me why this isn't a bug.
All of them are in WASAPICapture.cpp. For now, I'll just test the waters with the simplest (and most serious) example: usage of a pointer into a buffer that has been released.
What follows is some pseudocode to highlight the specific lines in question. Line numbers are relative to the more complete code extract further down.
P.S. - my access to the Internet is sporadic, and I'm a newbie - so please be patient with my responses.
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!?
... and here is the more complete code excerpt:
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 );
You are correct.
There are two problems here.