windows下简单的音频采集示例

来源:互联网 发布:淘宝上万宝贝怎么上传 编辑:程序博客网 时间:2024/05/16 14:37

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

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

代码块

#include "stdafx.h"#include <MMDeviceAPI.h>#include <AudioClient.h>#include <AudioPolicy.h>#define MAX_AUDIO_FRAME_SIZE 192000template <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 0