windows下简单的音频采集示例

最近需要在window下进行音频采集,网上找了很久都没找到win7下如何采集pcm数据的完整示例,经过一翻折腾后写了一个很简单的demo程序以供同行进行参考,如有不正确的地方请指正

本例是采用audio core进行音频采集

代码块

#include "stdafx.h"
#include <MMDeviceAPI.h>
#include <AudioClient.h>
#include <AudioPolicy.h>

#define MAX_AUDIO_FRAME_SIZE 192000

template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
    (*ppT)->Release();
    *ppT = NULL;
}
}

int _tmain(int argc, _TCHAR* argv[])
{

    IAudioClient *      _AudioClient;
    IAudioCaptureClient *_CaptureClient;
    IMMDevice * _Device;
    IMMDeviceEnumerator *deviceEnumerator = NULL;
    HANDLE _AudioSamplesReadyEvent=NULL;

    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&deviceEnumerator));
    if (FAILED(hr))
    {
        printf("Unable to retrieve CoCreateInstance %x\n", hr);
        goto Exit;
    }
    //这里可以调用EnumAudioEndpoints选择使用其它设备
    hr = deviceEnumerator->GetDefaultAudioEndpoint(eCapture,eMultimedia,&_Device);
    if (FAILED(hr))
    {
        printf("Unable to retrieve device %x\n", hr);
        goto Exit;
    }
    SafeRelease(&deviceEnumerator);

    _Device->AddRef();    // Since we're holding a copy of the endpoint, take a reference to it.  It'll be released in Shutdown();

    _AudioSamplesReadyEvent = CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
    if (_AudioSamplesReadyEvent == NULL)
    {
        printf("Unable to create samples ready event: %d.\n", GetLastError());
        return false;
    }

    hr = _Device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&_AudioClient));
    if (FAILED(hr))
    {
        printf("Unable to activate audio client: %x.\n", hr);
        return false;
    }

    WAVEFORMATEX *      _MixFormat;
    UINT32              _BufferSize;
    hr = _AudioClient->GetMixFormat(&_MixFormat);
    if (FAILED(hr))
    {
        printf("Unable to get mix format on audio client: %x.\n", hr);
        return false;
    }

    size_t _FrameSize = (_MixFormat->wBitsPerSample / 8) * _MixFormat->nChannels;

    //InitializeAudioEngine
    hr = _AudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, 20*10000, 0, _MixFormat, NULL);

    if (FAILED(hr))
    {
        printf("Unable to initialize audio client: %x.\n", hr);
        return false;
    }

    //
    //  Retrieve the buffer size for the audio client.
    //
    hr = _AudioClient->GetBufferSize(&_BufferSize);
    if(FAILED(hr))
    {
        printf("Unable to get audio client buffer: %x. \n", hr);
        return false;
    }
    hr = _AudioClient->SetEventHandle(_AudioSamplesReadyEvent);
    if (FAILED(hr))
    {
        printf("Unable to set ready event: %x.\n", hr);
        return false;
    }

    hr = _AudioClient->GetService(IID_PPV_ARGS(&_CaptureClient));
    if (FAILED(hr))
    {
        printf("Unable to get new capture client: %x.\n", hr);
        return false;
    }

    //开始采集

    hr = _AudioClient->Start();
    if (FAILED(hr))
    {
        printf("Unable to get new capture client: %x.\n", hr);
        return false;
    }

    bool stillPlaying = true;
    while (stillPlaying)
    {
        DWORD waitResult = WaitForSingleObject( _AudioSamplesReadyEvent, INFINITE);

        BYTE *pData,*pBuffer;
        INT nBufferLenght;
        UINT32 framesAvailable;
        DWORD  flags;
        pBuffer=new BYTE[MAX_AUDIO_FRAME_SIZE];
        hr = _CaptureClient->GetBuffer(&pData, &framesAvailable, &flags, NULL, NULL);
        if (SUCCEEDED(hr))
        {
            if (framesAvailable!=0)
            {
                if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
                {
                    //
                    //  Fill 0s from the capture buffer to the output buffer.
                    //
                }
                else
                {
                    //
                    //  Copy data from the audio engine buffer to the output buffer.
                    //

                    CopyMemory(pBuffer,pData,framesAvailable*_FrameSize);
                    printf("get capture frames: %d!\n", framesAvailable);
                }
            }
            delete[] pBuffer;
            hr = _CaptureClient->ReleaseBuffer(framesAvailable);
            if (FAILED(hr))
            {
                printf("Unable to release capture buffer: %x!\n", hr);
            }
        }
    }
Exit:

    return 0;
}

特别提醒一下,我在win7下采集到的pcm数据格式是32位浮点型,如果你需要编码成其它格式的话注意做相应的转换

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值