我是 WASAPI 的新手,按照这里的 msdn 参考代码 http://msdn.microsoft.com/en-us/library/windows/desktop/dd370800(v=vs.85).aspx使用 WASAPI 捕获音频蜜蜂。
出于我的目的,稍微修改了 msdn 参考代码。我正在使用麦克风录制我的声音并播放它,它在使用 SoundRecorder 和其他 Windows 内置应用程序时工作正常,但使用我的测试应用程序,没有得到任何有效的声音,只是得到一些噪音。
这是我的代码,请告诉我,我哪里出错了:
// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
#define TIME_COUNTER_LIMIT 20
WAVEFORMATEX sinWaveFormat;
CWaveFile sinwave;
HRESULT RecordAudioStream()
{
HRESULT hr;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
REFERENCE_TIME hnsActualDuration;
UINT32 bufferFrameCount;
UINT32 numFramesAvailable;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioClient *pAudioClient = NULL;
IAudioCaptureClient *pCaptureClient = NULL;
WAVEFORMATEX *pwfx = NULL;
UINT32 packetLength = 0;
UINT32 time_counter = 0;
BYTE *pData;
DWORD flags;
UINT32 bytesToCapture = 0;
UINT64 u64DevicePosition = 0;
UINT64 u64QPCPosition = 0;
BYTE temp_buffer[10000];
CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator);
EXIT_ON_ERROR(hr)
hr = pEnumerator->GetDefaultAudioEndpoint(
eCapture, eConsole, &pDevice);
EXIT_ON_ERROR(hr)
hr = pDevice->Activate(
__uuidof(IAudioClient), CLSCTX_ALL,
NULL, (void**)&pAudioClient);
EXIT_ON_ERROR(hr)
hr = pAudioClient->GetMixFormat(&pwfx);
EXIT_ON_ERROR(hr)
// convert from Float to PCM and from WAVEFORMATEXTENSIBLE to WAVEFORMATEX
if ((pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) ||
((pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
(reinterpret_cast<WAVEFORMATEXTENSIBLE *>(pwfx)->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
{
pwfx->wFormatTag = WAVE_FORMAT_PCM;
pwfx->wBitsPerSample = 16;
pwfx->nBlockAlign = pwfx->nChannels * 2; // (nChannels * wBitsPerSample) / 8
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
pwfx->cbSize = 0;
}
hr = open_capture_file(pwfx);
EXIT_ON_ERROR(hr)
hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_SHARED,
0,
hnsRequestedDuration,
0,
pwfx,
NULL);
EXIT_ON_ERROR(hr)
// Get the size of the allocated buffer.
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)
hr = pAudioClient->GetService(
__uuidof(IAudioCaptureClient),
(void**)&pCaptureClient);
EXIT_ON_ERROR(hr)
/*
// Notify the audio sink which format to use.
hr = pMySink->SetFormat(pwfx);
EXIT_ON_ERROR(hr)
*/
// Calculate the actual duration of the allocated buffer.
hnsActualDuration = (double)REFTIMES_PER_SEC *
bufferFrameCount / pwfx->nSamplesPerSec;
hr = pAudioClient->Start(); // Start recording.
EXIT_ON_ERROR(hr)
// Sleep for half the buffer duration.
Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
hr = pCaptureClient->GetNextPacketSize(&packetLength);
EXIT_ON_ERROR(hr)
bytesToCapture = packetLength * pwfx->nBlockAlign;
while (packetLength != 0 && time_counter <= TIME_COUNTER_LIMIT)
{
time_counter++;
// Get the available data in the shared buffer.
hr = pCaptureClient->GetBuffer(
&pData,
&numFramesAvailable,
&flags, &u64DevicePosition, &u64QPCPosition);
EXIT_ON_ERROR(hr)
if (packetLength != numFramesAvailable)
{
printf("packetlength = %d, numFramesAvailable = %d, does not match.\n", packetLength, numFramesAvailable);
bytesToCapture = numFramesAvailable * pwfx->nBlockAlign;
}
printf("packetlength = %d, numFramesAvailable = %d, bytesToCapture = %d.\n",
packetLength, numFramesAvailable, bytesToCapture);
if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
{
memset(pData, 0, numFramesAvailable * pwfx->nBlockAlign);
}
if (bytesToCapture > sizeof(temp_buffer))
{
printf("bytesToCapture = %d, more than buffer size = %d\n.", bytesToCapture, sizeof(temp_buffer));
continue;
}
memcpy(temp_buffer, pData, bytesToCapture);
hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
EXIT_ON_ERROR(hr)
// Copy the available capture data to the audio sink.
hr = write_to_file(
temp_buffer, bytesToCapture);
EXIT_ON_ERROR(hr)
// Sleep for half the buffer duration.
//Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
hr = pCaptureClient->GetNextPacketSize(&packetLength);
EXIT_ON_ERROR(hr)
bytesToCapture = packetLength * pwfx->nBlockAlign;
}
hr = pAudioClient->Stop(); // Stop recording.
EXIT_ON_ERROR(hr)
Exit:
CoTaskMemFree(pwfx);
SAFE_RELEASE(pEnumerator);
SAFE_RELEASE(pDevice);
SAFE_RELEASE(pAudioClient);
SAFE_RELEASE(pCaptureClient);
return hr;
}