捕获本地扬声器设备/麦克风的pcm数据,方案还是很多的,而且也比较简单,这个就直接上代码,有不懂的可以私信,相互交流
#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <stdio.h>
#include <mmsystem.h>int main(int argc, char* argv[])
{
IMMDeviceEnumerator *pMMDeviceEnumerator = NULL;
IAudioCaptureClient *pAudioCaptureClient = NULL;
IAudioClient *pAudioClient = NULL;
WAVEFORMATEX *pwfx = NULL;
IMMDevice* pDevice = NULL;
BYTE *pData(NULL);
DWORD dwFlags(0);FILE *fp = fopen("test.pcm", "wb+");
if (!fp)
return -1;//使用COM库,必须调用CoInitialize/CoInitializeEx
CoInitialize(NULL);
//获取枚举音频设备的对象
HRESULT hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pMMDeviceEnumerator);
if (FAILED(hr)) return -1;
//获取默认的扬声器设备 eRender:播放设备 eCapture:麦克风设备//hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
pMMDeviceEnumerator->Release();
if (FAILED(hr)) return -1;do
{
//获取IAudioClient对象,用来获取音频数据格式等
hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);
if (FAILED(hr)) break;
//获取该音频设备的默认混音格式,当然大多数人会去尝试一下48K-2通道-16位能否获取,这边略过了,直接获取默认的格式
hr = pAudioClient->GetMixFormat(&pwfx);
if (FAILED(hr)) break;printf("WAVEFORMATEX {%dHz %d channels %d bit}\r\n", pwfx->nSamplesPerSec, pwfx->nChannels, pwfx->wBitsPerSample);
//设置缓存长度为10ms数据
//这个写法是获取扬声器设备的数据
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK, 10*1000, 0, pwfx, NULL);//这个写法是获取麦克风设备的数据
//hr= pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK| AUDCLNT_STREAMFLAGS_NOPERSIST,10*1000,pwfx,NULL);
if (FAILED(hr)) break;
//获取捕获对象
hr = pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pAudioCaptureClient);
if (FAILED(hr)) break;
//开始捕获
hr = pAudioClient->Start();
if (FAILED(hr)) break;UINT32 nNextPacketSize = 0;
UINT32 nNumFramesToRead = 0;
int nFrameSize = (pwfx->wBitsPerSample / 8) * pwfx->nChannels;//一帧的数据大小
while (true)
{
//获取是否有包数据到来
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
if (FAILED(hr))
{
Sleep(1);
continue;
}
//可获取的包数据=0,继续循环等待,这边其实可以事件等待的
if (nNextPacketSize == 0)
{
Sleep(1);
continue;
}
//获取pcm数据
dwFlags = 0;
hr = pAudioCaptureClient->GetBuffer(
&pData,
&nNumFramesToRead,
&dwFlags,
NULL,
NULL
);
if (FAILED(hr))
{
break;
}
//判断是否是静音包
if (dwFlags & AUDCLNT_BUFFERFLAGS_SILENT)
printf("Get AUDCLNT_BUFFERFLAGS_SILENT\r\n");//获取到音频数据大小
if (nNumFramesToRead > 0)
{
if (fp)
{
fwrite(pData,1, nFrameSize * nNumFramesToRead,fp);
}
pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
}
}
} while (true);
//释放各资源
fclose(fp);
if (pAudioCaptureClient != NULL)
{
pAudioCaptureClient->Release();
pAudioCaptureClient = NULL;
}if (pwfx != NULL)
{
CoTaskMemFree(pwfx);
pwfx = NULL;
}if (pAudioClient != NULL)
{
pAudioClient->Stop();
pAudioClient->Release();
pAudioClient = NULL;
}if (pDevice)
{
pDevice->Release();
pDevice = NULL;
}
return 0;
}