第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数据先存入文件:

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/283554.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023-刻苦自励,2024-奋起直追!

点击上方“嵌入式应用研究院”&#xff0c;选择“置顶/星标公众号” 干货福利&#xff0c;第一时间送达&#xff01; 来源 | 嵌入式应用研究院 整理&排版 | 嵌入式应用研究院 一、引言 时光如影&#xff0c;岁月如梭。转眼之间&#xff0c;2023年已经过去&#xff0c;在这一…

拒绝采样(算法)总结

先说说什么是拒绝采样算法&#xff1a;就类似于数学上的求阴影面积的方法&#xff0c;直接求求不出来&#xff0c;就用大面积 - 小面积 阴影面积的办法。 所谓拒绝 和 采样 &#xff1a;就像是撒豆子计个数&#xff0c;计算概率问题一样&#xff0c;大桶里面套小桶&#xff0c…

[C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计

源码地址&#xff1a; github地址&#xff1a;https://github.com/Ahmednull/L2CS-Net L2CS-Net介绍&#xff1a; 眼睛注视&#xff08;eye gaze&#xff09; 是在各种应用中使用的基本线索之一。 它表示用户在人机交互和开放对话系统中的参与程度。此外&#xff0c;它还被用…

Docker 从入门到实践:Docker介绍

前言 在当今的软件开发和部署领域&#xff0c;Docker已经成为了一个不可或缺的工具。Docker以其轻量级、可移植性和标准化等特点&#xff0c;使得应用程序的部署和管理变得前所未有的简单。无论您是一名开发者、系统管理员&#xff0c;还是IT架构师&#xff0c;理解并掌握Dock…

【数据结构】栈和队列(队列的基本操作和基础知识)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​ 目录 前言 队列 队列的概念和结构 队列的…

域名转移:将腾讯云转移至阿里云

当时注册域名时&#xff0c;腾讯域云相对便宜&#xff0c;但目前阿里云在业界更加成熟&#xff0c;因此将自己申请的域名由阿里云转移至阿里云&#xff0c;并记录转移过程。 一、域名转出 进入腾讯云&#xff0c;登陆后选择控制台&#xff0c;选择我的资源–域名注册–全部域名…

【华为机试】2023年真题B卷(python)-滑动窗口最大值

一、题目 题目描述&#xff1a; 有一个N个整数的数组&#xff0c;和一个长度为M的窗口&#xff0c;窗口从数组内的第一个数开始滑动直到窗口不能滑动为止&#xff0c; 每次窗口滑动产生一个窗口和&#xff08;窗口内所有数的和&#xff09;&#xff0c;求窗口滑动产生的所有窗口…

LTPI协议的理解——1、LTPI协议的定义和结构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 LTPI协议的理解——1、LTPI协议的定义和结构 定义DC-SCM 2.0 LTPI 结构GPIO通道I2C/SMBus通道Uart通道OEM通道数据通道 总结 定义 LTPI (LVDS Tunneling Protocol & Int…

单片机数据发送程序

#include<reg51.h> //包含单片机寄存器的头文件 /***************************************************** 函数功能&#xff1a;向PC发送一个字节数据 ***************************************************/ void Send(unsigned char dat) { SBUFdat; whil…

【ESP-NOW with ESP32:从多个开发板接收数据(多对一)】

【ESP-NOW with ESP32&#xff1a;从多个开发板接收数据&#xff08;多对一&#xff09;】 1. 项目概况2. 先决条件2.1 环境配置2.2 所需零件 3. 获取接收板 MAC 地址4. ESP32 发送码 &#xff08;ESP-NOW&#xff09;4.1 代码的工作原理4.2 setup&#xff08;&#xff09;4.3 …

异步处理方案

目录 1.通过promise的链式调用将异步方法变为同步执行 2.使用async及await 3.回调函数方式 4.三种方式对比 5.async及await使用的注意点 1.通过promise的链式调用将异步方法变为同步执行 function get1(){return new Promise((resolve,reject) >{console.log(执行get1接…

B端产品学习-市场调研与分析

B端产品市场调研与分析 目录&#xff1a; 为什么要做产品调研 B端产品调研对比C端产品调研 B端产品调研要怎么做 为什么要做产品调研 杰克特劳特说过&#xff1a;“成为唯一。如果不能争得第一&#xff0c;那就找到一个能够成为第一的细分&#xff0c;这就是定位的第一法则…

激发大规模ClickHouse数据加载(3/3)确保加载大规模数据的可靠性

本文字数&#xff1a;7016&#xff1b;估计阅读时间&#xff1a;18 分钟 作者&#xff1a;Tom Schreiber 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 本文在公众号【ClickHouseInc】首发 本文是“激发大规模ClickHouse数据加载”系列文章的最后一篇&#xff1a; 激发…

【华为机试】2023年真题B卷(python)-猴子爬山

一、题目 题目描述&#xff1a; 一天一只顽猴想去从山脚爬到山顶&#xff0c;途中经过一个有个N个台阶的阶梯&#xff0c;但是这猴子有一个习惯&#xff1a; 每一次只能跳1步或跳3步&#xff0c;试问猴子通过这个阶梯有多少种不同的跳跃方式&#xff1f; 二、输入输出 输入描述…

springboot基于Java的大学生迎新系统

springboot基于Java的大学生迎新系统 源码获取&#xff1a; https://docs.qq.com/doc/DUXdsVlhIdVlsemdX

Windows磁盘空间占用分析工具-WizTree

文章目录 WizTree作用WizTree树状分析图WizTree特点获取网址 WizTree作用 平时我们电脑用久了&#xff0c;产生很多文件&#xff0c;导致盘符空间不足&#xff0c;但是不知道那些文件占用比较多&#xff0c;这就需要磁盘空间分析工具-WizTree来分析文件占用情况 WizTree树状分…

信息网络协议基础_绪论

文章目录 交换技术基本概念电路交换电话交换网 分组交换数据报交换虚电路交换 网络体系结构新的网络技术和体系结构Delay/Disruption Tolerant Networking(DTN)如何理解间隙性&#xff1f; Software Define Networking(SDN)Future Internet ArchitectureNDN(Named Data Network…

测试C#使用OpenCvSharp从摄像头获取图片

OpenCvSharp也支持获取摄像头数据&#xff0c;不同于之前测试AForge时使用AForge控件显示摄像头数据流并从中截图图片&#xff0c;OpenCvSharp中显示摄像头数据流需要周期性地从摄像头中截取图片并显示在指定控件中。本文学习C#使用OpenCvSharp从摄像头获取图片的基本方式。  …

【算法练习】leetcode链表算法题合集

链表总结 增加表头元素倒数节点&#xff0c;使用快慢指针环形链表&#xff08;快慢指针&#xff09;合并有序链表&#xff0c;归并排序LRU缓存 算法题 删除链表元素 删除链表中的节点 LeetCode237. 删除链表中的节点 复制后一个节点的值&#xff0c;删除后面的节点&#x…

uniapp中的uview组件库丰富的Form 表单用法

目录 基本使用 #Form-item组件说明 #验证规则 #验证规则属性 #uView自带验证规则 #综合实战 #校验错误提示方式 #校验 基本使用 此组件一般是用于表单验证使用&#xff0c;每一个表单域由一个u-form-item组成&#xff0c;表单域中可以放置u-input、u-checkbox、u-radio…