0

我是 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;
}
4

0 回答 0