头文件:
#ifndef __CAPTURE_AUDIO__
#define __CAPTURE_AUDIO__
#include <functional>
#include <windows.h>
#pragma comment(lib, "winmm.lib")
class CaptureAudio
{
public:
CaptureAudio();
~CaptureAudio();
public:
bool Init(const std::function<void(unsigned char* pPcmAudioData, long nLen)>& pFunc);
void Uninit();
private:
bool Capture();
private:
static unsigned int __stdcall Process(void* args);
private:
unsigned char* m_pAudioData = nullptr;
private:
HANDLE m_threadRecv = INVALID_HANDLE_VALUE;
HANDLE m_threadEvent = INVALID_HANDLE_VALUE;
private:
WAVEHDR m_wHdr; //采集音频时包含数据缓存的结构体
HWAVEIN m_hWaveIn;//输入设备
private:
std::function<void(unsigned char* pPcmAudioData, long nLen)> m_pFunc;
};
#endif
源文件:
#include "CaptureAudio.h"
#include <chrono>
#include <thread>
using namespace std;
CaptureAudio::CaptureAudio()
{
while (!m_pAudioData) {
try{
m_pAudioData = new unsigned char[1024 * 1024];
}
catch (...){}
}
}
CaptureAudio::~CaptureAudio()
{
if (m_pAudioData) {
delete[]m_pAudioData;
m_pAudioData = nullptr;
}
}
bool CaptureAudio::Init(const std::function<void(unsigned char* pPcmAudioData, long nLen)>& pFunc)
{
UINT nDev = waveInGetNumDevs();
if (nDev == 0) {
return false;
}
WAVEFORMATEX waveform; //采集音频的格式,结构体
waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCM
waveform.nSamplesPerSec = 48000;//采样率,16000次/秒
waveform.wBitsPerSample = 16;//采样比特,16bits/次
waveform.nChannels = 1;//采样声道数,2声道
waveform.nAvgBytesPerSec = 16000;//每秒的数据率,就是每秒能采集多少字节的数据
waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数
waveform.cbSize = 0;//一般为0
MMRESULT hResults = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)0, (DWORD_PTR)this, CALLBACK_NULL);//使用waveInOpen函数开启音频采集
if (hResults != MMSYSERR_NOERROR) {
return false;
}
m_threadEvent = CreateEvent(NULL, true, false, L"");
m_threadRecv = (HANDLE)_beginthreadex(NULL, 0, Process, this, 0, NULL);
m_pFunc = pFunc;
return true;
}
void CaptureAudio::Uninit()
{
if (m_threadRecv != INVALID_HANDLE_VALUE && m_threadEvent != INVALID_HANDLE_VALUE) {
SetEvent(m_threadEvent);
WaitForSingleObject(m_threadRecv, INFINITE);
CloseHandle(m_threadRecv);
CloseHandle(m_threadEvent);
m_threadRecv = INVALID_HANDLE_VALUE;
m_threadEvent = INVALID_HANDLE_VALUE;
}
waveInUnprepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));
waveInStop(m_hWaveIn);
waveInClose(m_hWaveIn);
}
bool CaptureAudio::Capture()
{
waveInUnprepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));
memset(m_pAudioData, 0, 1024 * 1024);
m_wHdr.lpData = (LPSTR)m_pAudioData;
m_wHdr.dwBufferLength = 1024 * 1024;
m_wHdr.dwBytesRecorded = 0;
m_wHdr.dwUser = 0;
m_wHdr.dwFlags = WHDR_DONE;
m_wHdr.dwLoops = 1;
waveInPrepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));//准备一个波形数据块头用于录音
waveInAddBuffer(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));//指定波形数据块为录音输入缓存
MMRESULT hResults = waveInStart(m_hWaveIn);//开始录音
if (hResults != MMSYSERR_NOERROR) {
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
waveInReset(m_hWaveIn);
if (m_pFunc) {
m_pFunc(m_pAudioData, m_wHdr.dwBytesRecorded);
}
return true;
}
unsigned int CaptureAudio::Process(void* args)
{
CaptureAudio* pThis = (CaptureAudio*)args;
while (true) {
if (WaitForSingleObject(pThis->m_threadEvent, 0) == WAIT_OBJECT_0) {
break;
}
pThis->Capture();
}
return 0;
}
生成的文件pcm: