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

相关推荐
Ethon_王1 小时前
走进Qt--工程文件解析与构建系统
c++·qt
工藤新一¹2 小时前
C++/SDL进阶游戏开发 —— 双人塔防游戏(代号:村庄保卫战 13)
c++·游戏·游戏引擎·毕业设计·sdl·c++游戏开发·渲染库
EQ-雪梨蛋花汤2 小时前
【Part 2安卓原生360°VR播放器开发实战】第二节|基于等距圆柱投影方式实现全景视频渲染
android·音视频·vr
让我们一起加油好吗2 小时前
【C++】类和对象(上)
开发语言·c++·visualstudio·面向对象
大霸王龙2 小时前
Python对比两张CAD图并标记差异的解决方案
python·opencv·计算机视觉
好想有猫猫2 小时前
【Redis】服务端高并发分布式结构演进之路
数据库·c++·redis·分布式·缓存
不是杠杠2 小时前
驼峰命名法(Camel Case)与匈牙利命名法(Hungarian Notation)详解
c++
Epiphany.5562 小时前
基于c++的LCA倍增法实现
c++·算法·深度优先
落羽的落羽2 小时前
【落羽的落羽 C++】vector
c++
newki3 小时前
学习笔记,Linux虚拟机中C/C++的编译相关流程步骤
c语言·c++