头文件:
#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;//声音格式为PCMwaveform.nSamplesPerSec = 48000;//采样率,16000次/秒waveform.wBitsPerSample = 16;//采样比特,16bits/次waveform.nChannels = 1;//采样声道数,2声道waveform.nAvgBytesPerSec = 16000;//每秒的数据率,就是每秒能采集多少字节的数据waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数waveform.cbSize = 0;//一般为0MMRESULT 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: