第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文件测试录制数据是否正确。

相关推荐
换个昵称都难39 分钟前
webrtc 视频传输Flexfec模块
音视频·webrtc
Kang.lee39 分钟前
2026.6.4【MIPI C-PHY】C-PHY v2.1协议阅读后问题总结
音视频·soc·asic
小欣加油1 小时前
leetcode1926 迷宫中离入口最近的出口
数据结构·c++·算法·leetcode·职场和发展
星恒随风2 小时前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
浪客灿心3 小时前
项目篇:模块设计与实现
数据库·c++
牛油果子哥q3 小时前
【C++ STL vector】C++ STL vector 终极精讲:动态数组底层原理、两倍扩容机制、迭代器失效、增删查改、性能剖析与工程避坑指南
开发语言·c++
gis分享者3 小时前
OpenCV 新手入门与实战部署指南
人工智能·opencv·计算机视觉
dualven_in_csdn4 小时前
h265视频的播放问题
音视频
为何创造硅基生物5 小时前
独占指针的创建std::make_unique 本身自带堆出现
c++
kyle~5 小时前
ROS 2 与 Isaac Sim 联合仿真(一)体系架构、环境选型与基础通信闭环
c++·机器人·nvidia·仿真·ros2