自学内容网 自学内容网

windows 桌面采集音频

头文件:

#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:

 


原文地址:https://blog.csdn.net/sz76211822/article/details/142556701

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!