0

I am new to WASAPI, following the msdn reference code, here, http://msdn.microsoft.com/en-us/library/windows/desktop/dd370800(v=vs.85).aspx, to capture audio using WASAPI apis.

Modified msdn reference code slightly for my purpose. I am using a microphone to record my voice, and play it back, it works fine when using SoundRecorder and other Windows in-built apps, but using my test application, not getting any valid sound, just getting some noise.

Here is my code, please let me know, where could I be going wrong:

// 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;
}
user3622275
  • 21
  • 1
  • 6
  • In your code, I see you doing SetFormat on the pSink variable/pointer, but it is not used anywhere else...could you explain this? – dylansweb May 14 '14 at 20:38
  • That part of the code is commented out. Actually I had to get rid of this check ->time_counter <= TIME_COUNTER_LIMIT, and change while loop terminating logic, little bit, and with those changes, capture works fine. – user3622275 Jul 24 '14 at 18:06

0 Answers0