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

[WASAPI]音频API:从Qt MultipleMedia走到WASAPI,相似与不同

[WASAPI] 从Qt MultipleMedia 来看WASAPI

最近在学习有关Windows上的音频驱动相关的知识,在正式开始说WASAPI之前,我想先说一说Qt的Multiple Media,为什么呢?因为Qt的MultipleMedia实际上是WASAPI的一层封装,它在是线上替我做了很多事,就好像在Microsoft的文档上会推荐你先学习Windows.Media.Capture,然后再看low level的WASAPI。

我这篇文章中,一方面是我Qt MultipleMedia用的比较多,另一方面,Qt MultiMedia也比较简单,为音频相关的API做了很多封装,这样就不需要你自己一个个HRESULT的去调试和测试了。

Qt MultiMedia Audio Recorder

由于Qt在5进6之后对Qt MultiMedia进行了大范围重构,所以这里Qt的项目我做了两个版本,分别为
audio-record-qt

audio-record-qt6

在调用上,Qt6和Qt5没有本质区别,所以这里我将着重聊一聊qt5上的录音机

在Qt5中,录音机的数据流如图所示:

在这里插入图片描述

流程大概如下:

  1. 获取所有设备的信息
  2. 根据名称匹配,获取我们需要的那个设备的QAudioDeviceInfo
  3. 使用QAudioDeviceInfo,获取到QAudioInput(输入)和QAudioOutput(输出)设备
  4. 重写一个QIODevice类,修改其writeData方法,并在其中完成你想要做的事情,包括但不限于:保存为文件,获得耳返数据,进行算法的处理等等。
  5. 将你继承了QIODevice的类的成员变量,放进QAudioInput和QAudioOutput的start中,这样一个完整的流就完成了。

其实WASAPI实际上也就是沿着这个Qt的MultiMedia的思路进行开发就可以了,但是在WASAPI中,没有Qt的封装,接口上会更加复杂一点而已。但是总的流程并没有本质区别。

还有需要注意的一点,就是QIODevice和QByteArray对数据流的封装做的很好,在纯C++中只能自己手动管理,所以这个地方可能会出现内存泄漏的风险,在开发的时候需要多多注意内存泄漏的问题。

WASAPI Audio Recorder

工程地址:
LeventureQys/Windows_Audio_Driver/WASAPI_Testbench

在WASAPI中,和Qt的MultiMedia中大的流程是一样的,但是在接口上来说往往更加复杂,简单的来说,流程大致如下:

在这里插入图片描述

其中和QtMultiMedia中最重要的区别就是没有一个专门的QIODevice去帮我处理线程和数据的关系,而是需要自己单开一个线程,然后从Capture/Render实例中去GetBuffer,然后从中获取数据或者往里面写入数据,再手动释放。

这个过程非常自由,同样也非常容易出现意外,所以在操作WASAPI的过程中需要谨慎谨慎再谨慎。

具体的代码详情见Github链接 LeventureQys/Windows_Audio_Driver/WASAPI_Testbench 我这里只简单说说我在工程中遇到的几个小问题。

  1. 输入设备的IAudioClient Initialize方法失败

我的调用函数如下:

hr = this->ptr_audio_client->Initialize(AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,AUDCLNT_STREAMFLAGS_EVENTCALLBACK,hnsDefaultDevicePeriod,hnsDefaultDevicePeriod,format_wav,NULL);

在这个函数中,第二个参数我设置的是AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_EVENTCALLBACK 这个地方具体要取决于设备是否允许进行回环录制和是否允许回调,并不是所有麦克风都支持这俩。

  1. 录制后的声音播放出来有很强的噪音,但我能确定声音是从麦克风传来的。

这种情况大概率是两边的声音没有对齐,这个根据wav的编码方式来的。简单地说,就是两边的channel和bitrate不匹配,导致声音无法对齐。具体你需要比对这两个format,然后再根据实际情况在音频处理处做应对和调整

WAVEFORMATEX* format_wav = NULL;
hr = ptr_audio_client->GetMixFormat(&format_wav);
if (FAILED(hr)) throw std::exception("Cant Get Mix Format!");WAVEFORMATEX* format_wav_output = NULL;
hr = ptr_output_audio_client->GetMixFormat(&format_wav_output);
if (FAILED(hr)) throw std::exception("Cant Get Mix Format Output!");

具体怎么调整详情可以看

[音视频学习笔记]二、什么是PCM音频?一些常见的PCM处理

比如我这里,我的麦克风的channels是1,但是耳机的channels是2,所以这里在播放的时候需要调整一下,将每一个bit都复制一份,放到输出的音频流中,如代码所示:

BYTE* pRenderData;
hr = ptr_output_audio_client_render->GetBuffer(numFramesAvailable, &pRenderData);
if (FAILED(hr)) {std::cerr << "GetBuffer (render) failed: " << hr << std::endl;return hr;
}
float* inputData = reinterpret_cast<float*>(pData);
float* outputData = reinterpret_cast<float*>(pRenderData);for (UINT32 i = 0; i < numFramesAvailable; i++) {// 将单声道复制到立体声的两个通道outputData[i * 2] = inputData[i];outputData[i * 2 + 1] = inputData[i];
}
到立体声的两个通道outputData[i * 2] = inputData[i];outputData[i * 2 + 1] = inputData[i];
}

相关文章:

[WASAPI]音频API:从Qt MultipleMedia走到WASAPI,相似与不同

[WASAPI] 从Qt MultipleMedia 来看WASAPI 最近在学习有关Windows上的音频驱动相关的知识&#xff0c;在正式开始说WASAPI之前&#xff0c;我想先说一说Qt的Multiple Media&#xff0c;为什么呢&#xff1f;因为Qt的MultipleMedia实际上是WASAPI的一层封装&#xff0c;它在是线…...

【畅购商城】微信支付之支付模块

目录 支付页面 接口 后端实现 前端实现​​​​​​​ ​​​​​​​支付页面 步骤一&#xff1a;创建 flow3.vue组件 步骤二&#xff1a;引入第三方资源&#xff08;js、css&#xff09; <script> import TopNav from ../components/TopNav import Footer from …...

网络安全专有名词详解_2

57.Webshell 就是以ASP、php、jsp、cgi等网页文件形式存在的一种命令执行环境&#xff0c;也叫做网页的后门&#xff0c;可以上传下载文件&#xff0c;查看数据库和执行任意的程序命令等。 58.跨站攻击 XSS&#xff0c;是指攻击者利用网站程序对用户输入过滤不足&#xff0c;输…...

【传感器技术与应用】第2章 基本电量传感器,电位器式传感器,电感式传感器,电容式传感器

注作者了解更多 我的其他CSDN专栏 毕业设计 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数…...

【day20】集合深入探讨

模块19回顾 在深入探讨模块20之前&#xff0c;让我们回顾一下day19中的关键内容&#xff1a; Collection集合&#xff1a;单列集合的顶级接口&#xff0c;提供了add、addAll、clear、size、isEmpty、remove、toArray、contains等方法。迭代器&#xff08;Iterator&#xff09…...

【英语语法】用must表对过去推测时,要用完成时must have been / must have done(不能直接用过去时)

文章目录 疑问解释1. 表达过去的推测2. 与时态一致3. 语法结构的限制4. 例子对比总结 疑问 This must have been a year-round activity as no structures have been found which would have been used to shelter animals in the winter. 为什么must表示对过去推测要用完成时&…...

数值计算期末考试重点(一)(黄云清版教材)

1.误差的分类 2.绝对误差和绝对误差限 3.绝对误差和绝对误差限 例题&#xff08;课后习题1.2&#xff09; 4.有效数字 例题&#xff08;课后习题1.6&#xff09; 5.算法的数值稳定性 例题&#xff08;课后习题1.9&#xff09; 这个手算比较艰难&#xff0c;还是给计算机算吧&am…...

使用 pushy 热更新后 sentry 不能正常显示源码

问题 使用 Android Studio 打包后&#xff0c;上传使用 sentry 官网命令打包的 sourcemap 文件&#xff0c;sentry能正常显示异常位置源码。 使用 pushy 热更新之后&#xff0c;sentry 不能正常显示异常位置的源代码。 如下图&#xff1a; 问题原因&#xff1a; 使用 pushy …...

IntelliJ IDEA 远程调试

IntelliJ IDEA 远程调试 在平时开发 JAVA 程序时&#xff0c;在遇到比较棘手的 Bug 或者是线上线下结果不一致的情况下&#xff0c;我们会通过打 Log 或者 Debug 的方式去定位并解决问题&#xff0c;两种方式各有利弊&#xff0c;今天就简要介绍下如何通过远程 Debug 的情况下…...

Java实现简单爬虫——爬取疫情数据

1.项目准备 在项目中使用到了jsoup和fastjson jsoup用于创建一个连接(绘画) 用于获取和解析HTML页面 而fastjson对数据进行一个格式化 在pom.xml导入坐标 <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</a…...

大数据技术-Hadoop(一)Hadoop集群的安装与配置

目录 一、准备工作 1、安装jdk&#xff08;每个节点都执行&#xff09; 2、修改主机配置 &#xff08;每个节点都执行&#xff09; 3、配置ssh无密登录 &#xff08;每个节点都执行&#xff09; 二、安装Hadoop&#xff08;每个节点都执行&#xff09; 三、集群启动配置&a…...

04.HTTPS的实现原理-HTTPS的混合加密流程

04.HTTPS的实现原理-HTTPS的混合加密流程 简介1. 非对称加密与对称加密2. 非对称加密的工作流程3. 对称加密的工作流程4. HTTPS的加密流程总结 简介 主要讲述了HTTPS的加密流程&#xff0c;包括非对称加密和对称加密两个阶段。首先&#xff0c;客户端向服务器发送请求&#xf…...

flutter插件开发-ios

flutter插件开发是一个重要的技能&#xff0c;拓展flutter与原生的通信&#xff0c;将一些公用的东西封装&#xff0c;给不同的项目使用。 阅读前置&#xff1a; flutter基本通道调用 objective-c基础语法 ios项目基础知识 目录 1、创建一个插件项目2、项目结构3、编写原生代码…...

【AI日记】24.12.29 kaggle 比赛 2-17

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加&#xff1a;kaggle 比赛 Regression with an Insurance Dataset时间&#xff1a;6 小时 读书 书名&#xff1a;教育的本质时间&#xff1a;1 小时 律己 工作时间&#xff1a;优作息&#xff1a…...

设计模式-创建型-工厂方法模式

什么是工厂方法模式&#xff1f; 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是 创建型设计模式之一&#xff0c;目的是通过定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪个类。简而言之&#xff0c;工厂方法模式通过延迟对象的创建过程到子类来…...

解决opencv在windows环境下读取中文图片名问题

在Windows系统下&#xff0c;cv2读取中文图片名时可能会报错&#xff0c;主要是因为OpenCV的imread函数在处理文件路径时&#xff0c;默认使用的是系统的编码格式&#xff0c;而Windows的默认编码可能与文件名的编码不匹配。具体原因包括&#xff1a; 编码不匹配&#xff1a;Wi…...

Apache Commons Pool :介绍与使用

Apache Commons Pool &#xff1a;介绍与使用 什么是 commons-pool2&#xff1f; commons-pool2 是 Apache Commons 提供的一个开源对象池实现框架。它旨在为应用程序提供通用的对象池支持&#xff0c;方便开发者管理资源&#xff08;如数据库连接、网络连接等&#xff09;复…...

sentinel-请求限流、线程隔离、本地回调、熔断

请求限流&#xff1a;控制QPS来达到限流的目的 线程隔离&#xff1a;控制线程数量来达到限流的目录 本地回调&#xff1a;当线程被限流、隔离、熔断之后、就不会发起远程调用、而是使用本地已经准备好的回调去提醒用户 熔断&#xff1a;熔断也叫断路器&#xff0c;当失败、或者…...

微信小程序 app.json 配置文件解析与应用

目录 一、什么是 app.json&#xff1f; 二、app.json 文件的基本结构 三、详细解析 app.json 配置项 1. pages&#xff1a;小程序页面路径配置 2. window&#xff1a;窗口样式配置 3. tabBar&#xff1a;底部标签栏配置 4. networkTimeout&#xff1a;网络请求超时配置 …...

C语言-共用体(联合体)

1.共用体(联合体) 1.共用体union是一个能在同一个存储空间存储不同类型数据的类型 2.共用体所占的内存长度等于其最长成员的长度。 3.同一内存段可以用来存放几种不同类型的成员&#xff0c;但每一瞬时只有一种起作用 4.共用体变量中起作用的成员是最后一次存放的成员&#xff…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...