第6课 用window API捕获麦克风数据并加入队列备用

今天是2024年1月1日,新年的第一缕阳光已经普照大地,祝愿看到这篇文章的所有程序员或程序爱好者都能在新的一年里持之以恒,事业有成。

今天也是我加入CSDN的第4100天,但回过头看一看,这么长的时间也没有在CSDN写下几篇文章,真是一种遗憾。为了弥补这个遗憾,我会继续坚持把这套教程写完。目前的教程总体而言写的还比较粗略,很多细节没有展开写,后面找时间再继续优化,现在主要是梳理一下整体思路,先搞个框架出来。

1.捕获麦克风数据入队列备用

上节课我们已经用openCV成功打开摄像头并实现了预览功能,这节课我们来看一下如何捕获麦克风数据。要捕获麦克风数据,就要先打开麦克风,打开麦克风的方法与《第3课 使用FFmpeg获取并播放音频流》中打开扬声器的方法差不多:

复制代码
//打开麦克风
void fmle::openMic(){
	int nIndex = 0;
	inWaveform.wFormatTag = WAVE_FORMAT_PCM;
	inWaveform.nSamplesPerSec = 44100;
	inWaveform.wBitsPerSample = 16;
	inWaveform.nChannels = 2;
	inWaveform.nBlockAlign = (inWaveform.wBitsPerSample * inWaveform.nChannels) / 8;
	inWaveform.nAvgBytesPerSec = inWaveform.nBlockAlign * inWaveform.nSamplesPerSec;
	inWaveform.cbSize = 0;
	waveInOpen(&hWaveIn, nIndex, &inWaveform, (DWORD)micCallback, 0L, CALLBACK_FUNCTION);
	waveHdrArr = new WAVEHDR[audioDataArrNum];
	for (int i = 0; i < audioDataArrNum; i++)
	{
		waveHdrArr[i].lpData = new char[audioDataSize];
		waveHdrArr[i].dwBufferLength = audioDataSize;
		waveHdrArr[i].dwBytesRecorded = 0;
		waveHdrArr[i].dwUser = NULL;
		waveHdrArr[i].dwFlags = 0;
		waveHdrArr[i].dwLoops = 1;
		waveHdrArr[i].lpNext = NULL;
		waveHdrArr[i].reserved = 0;
		waveInPrepareHeader(hWaveIn, &waveHdrArr[i], sizeof(WAVEHDR));
		waveInAddBuffer(hWaveIn, &waveHdrArr[i], sizeof(WAVEHDR));
	}
	waveInStart(hWaveIn);
}

DWORD CALLBACK fmle::micCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{

	switch (uMsg)
	{
	case WIM_OPEN:
		TRACE("WIM_OPEN\n");
		break;

	case WIM_DATA:


	{
					 //TRACE("WIM_DATA\n");
					 LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;
					 if (pwh->dwBytesRecorded > 0){
						 EnterCriticalSection(&pThis->queLock);
						 pThis->tmpAudioQueObj.type = 0;
						 pThis->tmpAudioQueObj.dataArr = pwh->lpData;
						 pThis->tmpAudioQueObj.dataLen = pwh->dwBytesRecorded;
						 pThis->inAudioQue.push(pThis->tmpAudioQueObj);
						 if (pThis->inAudioQue.size() > pThis->audioDataArrNum){
							 pThis->inAudioQue.front().dataLen = 0;
							 pThis->inAudioQue.front().dataArr = NULL;
							 pThis->inAudioQue.front().dataLen = NULL;
							 delete[]pThis->inAudioQue.front().dataArr;
							 pThis->inAudioQue.pop();
						 }
						 LeaveCriticalSection(&pThis->queLock);
					 }
					 waveInAddBuffer(pThis->hWaveIn, pwh, sizeof(WAVEHDR));
					 TRACE("pThis->inAudioQue.size():%d\n", pThis->inAudioQue.size());
	}

		break;

	case WIM_CLOSE:
		TRACE("WIM_CLOSE\n");
		waveInStop(pThis->hWaveIn);
		waveInReset(pThis->hWaveIn);
		waveInClose(pThis->hWaveIn);
		break;
	default:
		break;
	}
	return 0;
}

2.将麦克风数据存成文件检测是否正常

上述方法虽然可以将麦克风数据存入队列备用,但我们如何知道它是否正确捕获了呢?我们可以把捕获的pcm数据先存入文件:

cpp 复制代码
FILE *pcmFile;
fopen_s(&pcmFile, "rec.pcm", "wb");
fwrite(pwh->lpData, 1, pwh->dwBytesRecorded, pcmFile);

想一想,上述代码应该分别加在什么地方呢?

录制pcm文件后可以使用Audacity来导入pcm文件测试录制数据是否正确。

相关推荐
我变成萤火虫15 小时前
河南萌新联赛2026第(四)场:南阳理工学院
数据结构·c++·算法·贪心算法·stl·动态规划
随风而飘18618 小时前
R&S 罗德与施瓦茨 R&S VTC-VTE-VTS 视频测试仪
音视频
学如逆水,不进则退18 小时前
在线免费音频剪辑:NBTools 可视化波形裁剪 MP3/WAV,本地处理免上传
前端·音视频
余额瞒着我当琳20 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
ShineWinsu21 小时前
对于C++:布隆过滤器(bloomfilter)的详细解析
c++·面试·位图·位运算·布隆过滤器·海量数据·比特位
李子红了时1 天前
批量修改MP4视频文件名并导出标题txt文本
前端·音视频
牛油果子哥q1 天前
C++内存模型与深浅拷贝万字详解:栈堆静态内存布局、深浅拷贝底层差异、内存泄漏根治、拷贝崩溃踩坑、手写深拷贝实战
java·开发语言·c++
大鹏的NLP博客1 天前
通用 Linux 嵌入式板端 C/C++ ABI 与 Glibc 依赖治理规范
linux·c++·交叉编译
AnyChat研究院1 天前
全栈信创深度适配,AnyChat为多领域数智化升级夯实安全可控根基
音视频·信创·安全可控·国产化·信创国产化·信创适配·信创音视频
ysa0510301 天前
c++常用自带函数用法与注意
c++·笔记·算法