当前位置: 首页 > news >正文

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

相关文章:

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

今天是2024年1月1日&#xff0c;新年的第一缕阳光已经普照大地&#xff0c;祝愿看到这篇文章的所有程序员或程序爱好者都能在新的一年里持之以恒&#xff0c;事业有成。 今天也是我加入CSDN的第4100天&#xff0c;但回过头看一看&#xff0c;这么长的时间也没有在CSDN写下几篇…...

图片预览 element-plus 带页码

vue3、element-plus项目中&#xff0c;点击预览图片&#xff0c;并显示页码效果如图 安装 | Element Plus <div class"image__preview"><el-imagestyle"width: 100px; height: 100px":src"imgListArr[0]":zoom-rate"1.2":max…...

【小白专用】winform启动界面+登录窗口 更新2024.1.1

需求场景&#xff1a;先展示启动界面&#xff0c;然后打开登录界面&#xff0c;如果登录成功就跳转到主界面 首先在程序的入口路径加载启动界面&#xff0c;使用ShowDialog显示界面&#xff0c; 然后在启动界面中添加定时器&#xff0c;来实现显示一段时间的效果&#xff0c;等…...

自动化网络故障修复管理

什么是故障管理 故障管理是网络管理的组成部分&#xff0c;涉及检测、隔离和解决问题。如果实施得当&#xff0c;网络故障管理可以使连接、应用程序和服务保持在最佳水平&#xff0c;提供容错能力并最大限度地减少停机时间。专门为此目的设计的平台或工具称为故障管理系统。 …...

Git:常用命令(二)

查看提交历史 1 git log 撤消操作 任何时候&#xff0c;你都有可能需要撤消刚才所做的某些操作。接下来&#xff0c;我们会介绍一些基本的撤消操作相关的命令。请注意&#xff0c;有些操作并不总是可以撤消的&#xff0c;所以请务必谨慎小心&#xff0c;一旦失误&#xff0c…...

Oracle 12c rac 搭建 dg

环境 rac 环境 &#xff08;主&#xff09;byoradbrac 系统版本&#xff1a;Red Hat Enterprise Linux Server release 6.5 软件版本&#xff1a;Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit byoradb1&#xff1a;172.17.38.44 byoradb2&#xff1a;…...

Cisco模拟器-交换机端口的隔离

设计要求将某台交换机的端口划分在不同的VLAN。以实现连接在相同VLAN端口上的计算机可以通信&#xff0c;而连接在不同VLAN端口上的计算机无法通信的目的。 通过设计&#xff0c;一方面可以加强计算机网络的安全&#xff0c;另一方面通过隔绝不同VLAN间的广播包也可以提高网络…...

zdppy_api框架快速入门

概述 zdppy_api是一款为了快速开发而生的&#xff0c;基于异步的&#xff0c;使用简单的Python后端API接口开发框架。 本框架的目标是让Python后端开发变得越来越简单&#xff0c;直到发现原来还可以更简单&#xff01; 一切都是为了提高开发效率&#xff01;&#xff01;&…...

https证书配置过程

相关网址&#xff1a; FreeSSL首页 - FreeSSL.cn一个提供免费HTTPS证书申请的网站 ACME v2证书自动化快速入门 acme.sh简单教程-CSDN博客...

如何用C语言程序生成任意手性(即具有任意m和n值),任意长度的碳纳米管,并输出三维空间坐标呢?

如何用C语言程序生成任意手性&#xff08;即具有任意m和n值&#xff09;&#xff0c;任意长度的碳纳米管&#xff0c;并输出三维空间坐标呢&#xff1f; 生成任意手性、任意长度的碳纳米管可以使用 Chirality Vector 和 Unit Vector 的概念来表示。Chirality Vector (n, m) 描述…...

C++每日一练(8):图像相似度

题目描述 给出两幅相同大小的黑白图像&#xff08;用0-1矩阵&#xff09;表示&#xff0c;求它们的相似度。 说明&#xff1a;若两幅图像在相同位置上的像素点颜色相同&#xff0c;则称它们在该位置具有相同的像素点。两幅图像的相似度定义为相同像素点数占总像素点数的百分比。…...

C++面试宝典第12题:数组元素相除

题目 从控制台输入若干个整数作为数组,将数组中每一个元素除以第一个元素的结果,作为新的数组元素值。比如:可以先输入3,作为数组元素的个数;然后输入3个整数,作为数组元素的值。 解析 这道题本身并不复杂,但里面隐藏了不少“坑点”和“雷区”,主要考察应聘者全面思考问…...

oCPC实践录 | 目标ROI的出价与转化回传调控算法

这篇文章我们聊聊广告主在oCPC下&#xff0c;怎么调控自己的出价或者回传转化优化自己的ROI。 ROI是广告主最关心的指标了&#xff0c;根据oCPC出价的基本原理ocpc_bid pcvr * given_cpa * k, 广告主在整个出价中有两个可以控制的变量来影响出价&#xff0c;一个是直接的give…...

百倍量化之Dbcd-v2中性策略

Dbcd-v2中性策略 1. 指标含义 该指标主要是计算偏置的因子,并根据偏置的平均来分析这个股票的稳定性。相比于v1,策略是更换了dbcd的计算方式 第一步主要操作就是计算当前值和前段时间的平均值的偏置 ma = bt.indicators.SimpleMovingAverage(self.data, period=self.p.peri…...

系统学习Python——装饰器:函数装饰器-[装饰器状态保持方案:函数属性]

分类目录&#xff1a;《系统学习Python》总目录 如果我们没有在使用Python3.X并因此无法利用一条nonlocal语句&#xff0c;或者我们希望代码具有可移植性&#xff0c;能在Python3.X和Python2.X上同时工作一一我们仍然能够针对某些可改变的状态使用函数属性来避免使用全局变量和…...

逻辑卷学习后续----------缩容

一、缩容&#xff1a;缩减大小 ext4可以 &#xff0c; xfs无法缩减&#xff0c;缩减会影响业务 1.解挂载 2.检查文件系统完整性 3.缩减文件系统 4.缩减逻辑卷上下一致 5.再挂载回去 添加磁盘 文件系统只能装ext4 缩减文件系统 resize2fs 挂载失败需要重新安装文件系统…...

15-网络安全框架及模型-BLP机密性模型

目录 BLP机密性模型 1 背景概述 2 模型原理 3 主要特性 4 优势和局限性 5 困难和挑战 6 应用场景 7 应用案例 BLP机密性模型 1 背景概述 BLP模型&#xff0c;全称为Bell-LaPadula模型&#xff0c;是在1973年由D.Bell和J.LaPadula在《Mathematical foundations and mod…...

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

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

[2024区块链开发入门指引] - 比特币与区块链诞生

一份为小白用户准备的免费区块链基础教程 工欲善其事,必先利其器 Web3开发中&#xff0c;各种工具、教程、社区、语言框架.。。。 种类繁多&#xff0c;是否有一个包罗万象的工具专注与Web3开发和相关资讯能毕其功于一役&#xff1f; 参见另一篇博文&#x1f449; 2024最全面…...

【大数据面试知识点】Spark中的累加器

Spark累加器 累加器用来把Executor端变量信息聚合到Driver端&#xff0c;在driver程序中定义的变量&#xff0c;在Executor端的每个task都会得到这个变量的一份新的副本&#xff0c;每个task更新这些副本的值后&#xff0c;传回driver端进行merge。 累加器一般是放在行动算子…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...