Qt---录音

news/2024/7/22 0:33:41/文章来源:https://blog.csdn.net/weixin_51883798/article/details/139132508

1.获取麦克风阵列:

    QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);for (int i = 0; i < infos.count(); i++){qDebug() << infos.at(i).deviceName();}

"麦克风阵列 (Realtek(R) Audio)"

2.QAudioFormat

	QAudioFormat formatAudio;formatAudio.setSampleRate(8000);formatAudio.setChannelCount(1);formatAudio.setSampleSize(16);formatAudio.setSampleType(QAudioFormat::SignedInt);formatAudio.setByteOrder(QAudioFormat::LittleEndian);formatAudio.setCodec("audio/pcm");

音频文件计算大小_比特率和时间求音频大小-CSDN博客

采样频率,声道数,采样位数

什么是大小端?如何确定大小端?-CSDN博客

pcm编码_百度百科 (baidu.com)

3.QList的push_back()

This function is provided for STL compatibility. It is equivalent to append(value).

 4.进行录音测试,获取过程中录入音量的最大值。

#pragma once#include <QObject>
#include "GNIODevice.h"
#include <QStringList>
#include <QAudioRecorder>
#include <QAudioInput>
#include <QAudioFormat>
#include <QAudioBuffer>
#include <QAudioProbe>
#include <QFile>
#include <QMutex>
#include <qeventloop.h>
class MacController1  : public QObject
{Q_OBJECTpublic:MacController1(QObject *parent);~MacController1();QStringList getMacList();void StartTestingMac(int macIndex);void StopTestingMac();
private:QAudioFormat formatAudio;GNIODevice* device;int currentVolume;int max_Volume;QAudioInput * audioInput;private:void runTest(int index);
public slots:void UpdateTestDisplay();
};
#include "MacController1.h"
#include <thread>
MacController1::MacController1(QObject *parent): QObject(parent)
{formatAudio.setSampleRate(8000);formatAudio.setChannelCount(1);formatAudio.setSampleSize(16);formatAudio.setSampleType(QAudioFormat::SignedInt);formatAudio.setByteOrder(QAudioFormat::LittleEndian);formatAudio.setCodec("audio/pcm");currentVolume = 0;max_Volume = 0;
}MacController1::~MacController1()
{}
void MacController1::runTest(int index)
{device->start();audioInput->start(device);
}
void MacController1::StartTestingMac(int macIndex)
{device = new GNIODevice(formatAudio, this);connect(device, SIGNAL(update()), this, SLOT(UpdateTestDisplay()));QAudioDeviceInfo testInfo;QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);testInfo = infos.at(macIndex);audioInput = new QAudioInput(testInfo,formatAudio, this);std::thread test(&MacController1::runTest, this,macIndex);test.detach();
}
void MacController1::StopTestingMac()
{device->stop();audioInput->stop();delete device;delete audioInput;device = nullptr;audioInput = nullptr;qDebug() << "max_Volume:" << max_Volume;
}
void MacController1::UpdateTestDisplay()
{int volume = device->level() * 100;if (volume < 0 || volume > 100){volume = 0;}currentVolume = volume;if (max_Volume < currentVolume) {max_Volume = currentVolume;}
}
QStringList MacController1::getMacList()
{QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);QStringList ansList;for (int i = 0; i < infos.count(); i++){ansList.push_back(QString::number(i + 1) + QString::fromLocal8Bit(": ") + infos[i].deviceName());}return ansList;
}
#pragma once
#include <QIODevice>
#include <QAudioFormat>
class GNIODevice :public QIODevice
{Q_OBJECTpublic:GNIODevice(const QAudioFormat& format, QObject* parent);//音频格式~GNIODevice();void start();void stop();qreal level() const { return m_level; }qint64 readData(char* data, qint64 maxlen) override;qint64 writeData(const char* data, qint64 len) override;private:const QAudioFormat m_format;quint32 m_maxAmplitude;//最大振幅qreal m_level; // 0.0 <= m_level <= 1.0signals:void update();
};
#include "GNIODevice.h"
#include <QDebug>
#include <QtEndian>const int BufferSize = 4096;//缓存大小GNIODevice::GNIODevice(const QAudioFormat& format, QObject* parent) : QIODevice(parent)
, m_format(format)
, m_maxAmplitude(0)
, m_level(0.0)
{//sampleSize,sampleType--->m_maxAmplitudeswitch (m_format.sampleSize()) {case 8:switch (m_format.sampleType()) {case QAudioFormat::UnSignedInt:m_maxAmplitude = 255;break;case QAudioFormat::SignedInt:m_maxAmplitude = 127;break;default:break;}break;case 16:switch (m_format.sampleType()) {case QAudioFormat::UnSignedInt:m_maxAmplitude = 65535;break;case QAudioFormat::SignedInt:m_maxAmplitude = 32767;break;default:break;}break;case 32:switch (m_format.sampleType()) {case QAudioFormat::UnSignedInt:m_maxAmplitude = 0xffffffff;break;case QAudioFormat::SignedInt:m_maxAmplitude = 0x7fffffff;break;case QAudioFormat::Float:m_maxAmplitude = 0x7fffffff; // Kind ofdefault:break;}break;default:break;}
}GNIODevice::~GNIODevice()
{
}void GNIODevice::start()
{open(QIODevice::WriteOnly);
}void GNIODevice::stop()
{close();
}qint64 GNIODevice::writeData(const char* data, qint64 len)
{if (m_maxAmplitude) {Q_ASSERT(m_format.sampleSize() % 8 == 0);const int channelBytes = m_format.sampleSize() / 8;const int sampleBytes = m_format.channelCount() * channelBytes;Q_ASSERT(len % sampleBytes == 0);const int numSamples = len / sampleBytes;quint32 maxValue = 0;const unsigned char* ptr = reinterpret_cast<const unsigned char*>(data);for (int i = 0; i < numSamples; ++i) {for (int j = 0; j < m_format.channelCount(); ++j) {quint32 value = 0;if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) {value = *reinterpret_cast<const quint8*>(ptr);}else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) {value = qAbs(*reinterpret_cast<const qint8*>(ptr));}else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) {if (m_format.byteOrder() == QAudioFormat::LittleEndian)value = qFromLittleEndian<quint16>(ptr);elsevalue = qFromBigEndian<quint16>(ptr);}else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) {if (m_format.byteOrder() == QAudioFormat::LittleEndian)value = qAbs(qFromLittleEndian<qint16>(ptr));elsevalue = qAbs(qFromBigEndian<qint16>(ptr));}else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::UnSignedInt) {if (m_format.byteOrder() == QAudioFormat::LittleEndian)value = qFromLittleEndian<quint32>(ptr);elsevalue = qFromBigEndian<quint32>(ptr);}else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::SignedInt) {if (m_format.byteOrder() == QAudioFormat::LittleEndian)value = qAbs(qFromLittleEndian<qint32>(ptr));elsevalue = qAbs(qFromBigEndian<qint32>(ptr));}else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::Float) {value = qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff); // assumes 0-1.0}maxValue = qMax(value, maxValue);ptr += channelBytes;}}maxValue = qMin(maxValue, m_maxAmplitude);m_level = qreal(maxValue) / m_maxAmplitude;}emit update();return len;
}qint64 GNIODevice::readData(char* data, qint64 maxlen)
{Q_UNUSED(data)Q_UNUSED(maxlen)return 0;
}

代码来源于CSDN的一个博主的下载资源。但我暂时找不到是谁了!!!

5.实现录音功能(存在bug)

#pragma once#include <QObject>
#include "GNIODevice.h"
#include <QStringList>
#include <QAudioRecorder>
#include <QAudioInput>
#include <QAudioFormat>
#include <QAudioBuffer>
#include <QAudioProbe>
#include <QFile>
#include <QMutex>
#include <qeventloop.h>
class MacController2  : public QObject
{Q_OBJECTpublic:MacController2(QObject *parent);~MacController2();QStringList getMacList();void StartRecordingVoice(int macIndex);void StopRecordingVoice();
private:QAudioInput* audioInput;GNIODevice* device;QAudioFormat formatAudio;QAudioProbe* probe;QAudioRecorder* recorder;QString fileName;
public slots:void processBuffera(const QAudioBuffer& buffer);
};
#include "MacController2.h"
#include "qurl.h"
MacController2::MacController2(QObject *parent): QObject(parent)
{probe = nullptr;recorder = nullptr;fileName = "E:/try/1.wav";
}MacController2::~MacController2()
{}
QStringList MacController2::getMacList()
{QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);QStringList ansList;for (int i = 0; i < infos.count(); i++){ansList.push_back(QString::number(i + 1) + QString::fromLocal8Bit(": ") + infos[i].deviceName());}return ansList;
}
void MacController2::StartRecordingVoice(int macIndex)
{qDebug() << fileName;probe = new QAudioProbe(this);connect(probe, &QAudioProbe::audioBufferProbed,this, &MacController2::processBuffera); //关联函数QAudioDeviceInfo info = QAudioDeviceInfo::availableDevices(QAudio::AudioInput).at(macIndex);recorder = new QAudioRecorder(this);QAudioEncoderSettings settings = recorder->audioSettings();probe->setSource(recorder);settings.setCodec("audio/PCM");   // 这些是QAudioRecorder是设置,见名思意settings.setBitRate(96000);//settings.setSampleRate(44100);settings.setChannelCount(2);settings.setQuality(QMultimedia::EncodingQuality::HighQuality);settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);recorder->setAudioSettings(settings);recorder->setAudioInput(info.deviceName());recorder->setOutputLocation(QUrl::fromLocalFile(fileName));recorder->setContainerFormat("audio/wav");recorder->record();
}
void MacController2::processBuffera(const QAudioBuffer& buffer)
{QByteArray arr;qDebug() << "HAS VOICE in mac!";//controlVoiceData(false, arr, buffer);
}
void MacController2::StopRecordingVoice()
{recorder->stop();recorder->deleteLater();
}

噪音其实有点大

QAudioProbe对象probe的槽函数仍在执行

从音频文件在线应用程序中删除背景噪音 - 免费在线音频文件背景噪音清洁器 (aspose.app)

降噪处理了一下

(我在想是不是CPU转动带来的噪声过大呢)

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

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

相关文章

内存泄漏案例分享3-view的内存泄漏

案例3——view内存泄漏 前文提到&#xff0c;profile#Leaks视图无法展示非Activity、非Fragment的内存泄漏&#xff0c;换言之&#xff0c;除了Activity、Fragment的内存泄漏外&#xff0c;其他类的内存问题我们只能自己检索hprof文件查询了。 下面有一个极佳的view内存泄漏例子…

ubuntu20.04 10分钟搭建无延迟大疆无人机多线程流媒体服务器

1.使用效果 无人机画面 2.服务器视频端口 3.使用教程 3.1.下载ubuntu对应软件包&#xff1a;系统要求ubuntu16以上 3.2修改端口&#xff08;config.xml文件&#xff09; 3.3启动服务 目录下输入&#xff1a;终端启动&#xff1a;./smart_rtmpd 后台启动&#xff1a;nohup ./…

如何选择序列化协议:关键因素与场景分析

如何选择序列化协议&#xff1a;关键因素与场景分析 序列化协议的选择直接影响着系统的性能、可维护性及跨平台兼容性。以下是针对不同场景下&#xff0c;几种常见序列化协议的选择建议&#xff1a; 1. 公司间系统调用&#xff08;性能要求宽松&#xff09; SOAP (基于XML)&a…

LeetCode 279 —— 完全平方数

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此图利用动态规划进行求解&#xff0c;首先&#xff0c;我们求出小于 n n n 的所有完全平方数&#xff0c;存放在数组 squareNums 中。 定义 dp[n] 为和为 n n n 的完全平方数的最小数量&#xff0c;那么有状态…

操作教程|通过DataEase开源BI工具对接金山多维表格

前言 金山多维表格是企业数据处理分析经常会用到的一款数据表格工具&#xff0c;它能够将企业数据以统一的列格式整齐地汇总至其中。DataEase开源数据可视化分析工具可以与金山多维表格对接&#xff0c;方便企业更加快捷地以金山多维表格为数据源&#xff0c;制作出可以实时更…

k8s pv 一直是release状态

如下图所示&#xff0c;pv 一直是release状态 这个时候大家可能就会想到现在我的 PVC 被删除了&#xff0c;PV 也变成了 Released 状态&#xff0c;那么我重建之前的 PVC 他们不就可以重新绑定了&#xff0c;事实并不会&#xff0c;PVC 只能和 Available 状态的 PV 进行绑定。…

ssm137基于SSM框架的微博系统+vue

微博系统网站的设计与实现 摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管理就…

保安维稳,四信以科技构筑高速公路安全智慧防线

近日&#xff0c;广东梅大高速发生严重塌方事故&#xff0c;造成了严重的人员伤亡和财产损失。这一事件在公众心中敲响了安全的警钟&#xff0c;再次引起了公众对于交通设施运营安全性的重点关注。 国务院安委会办公室和国家防灾减灾救灾委员会办公室等主管机构先后印发紧急通知…

make disclean V=1 分析

文章目录 make distclean步骤1&#xff1a;2090-2114行&#xff0c;执行依赖 clean步骤2&#xff1a;2120-2124行&#xff0c;执行依赖 $(mrproper-dirs)步骤3&#xff1a;2118-2129行&#xff0c;执行依赖 mrproper步骤4&#xff1a;2135-2142行&#xff0c;实现 distclean 编…

flutter 的webview中touchstart和touchend 执行异常问题解决

效果 背景 使用flutter 调用webview内网页&#xff0c;网页内容是监听touchstart和 touchend&#xff0c;触发不同是事件&#xff0c;但是发现每次长按都 手指抬起后 才会执行 touchstart和touchend&#xff0c;满足不了我的需求&#xff0c;我的需求是当手指按下 立即执行touc…

大模型时代的具身智能系列专题(三)

清华高阳团队 高阳为清华叉院助理教授&#xff0c;本科毕业于清华大学计算机系&#xff0c;博士毕业于UC Berkeley。博士导师是Vision领域的大牛Trevor Darrell&#xff0c;读博期间和Sergey Levine合作开始强化学习方面的探索&#xff0c;博后跟随Pieter Abbeel做强化学习&am…

Windows下mingw32编译ffmpeg5.1.4实现rtsp拉流

由于客户要求&#xff0c;要在Windows下使用mingw32编译&#xff0c;去ffmpeg.org下载需要编译的版本&#xff0c;使用msys2方法进行编译&#xff0c;使用QT5.10的编译器&#xff0c;基本上把网上的方法试了个遍&#xff0c;编译全部库总是报错出问题 查看了ffbuild文件夹中con…

【全开源】JAVA情侣扭蛋机情侣游戏系统源码支持微信小程序+微信公众号+H5

一、引言&#xff1a;增添恋爱甜蜜&#xff0c;扭出惊喜时刻 在恋爱生活中&#xff0c;总是需要一些小小的惊喜和乐趣来增添甜蜜。为此&#xff0c;我们精心打造了“情侣扭蛋机情侣游戏系统小程序源码”&#xff0c;为情侣们提供一个充满趣味和创意的互动平台。 二、独特扭蛋…

C++的第一道门坎:类与对象(一)

1.面向过程与面向对象 1.1面向过程 我们之前学习的C语言就是一种面向过程的语言&#xff0c;面向过程的语言强调的是具体实现的过程&#xff0c;一般用函数来具体实现。我们用面向过程的思想&#xff0c;就可以把炒菜分为以下几个步骤: 1.2面向对象 而对于面向对象的语言而言…

【ARMv8/v9 异常模型入门及渐进 10 -- WFI 与 WFE 使用详细介绍 1】

请阅读【ARMv8/v9 ARM64 System Exception】 文章目录 WFI 与 WFE等待事件&#xff08;WFE&#xff09;发送事件&#xff08;SEV&#xff09;本地发送事件&#xff08;SEVL&#xff09;WFE 唤醒事件 WFE 使用场景举例与代码实现wfe睡眠函数sev 事件唤醒函数全局监视器和自旋锁 …

如何异地组网添加摄像机?

本文将介绍如何使用天联技术实现异地组网添加摄像机&#xff0c;并保障数据的安全性。 安防摄像机的应用愈发广泛&#xff0c;无论是家庭安防还是企业监控&#xff0c;摄像机都扮演着重要角色。在一些特殊场合或者特殊需求下&#xff0c;我们需要将摄像机添加到异地网络中进行监…

uniapp android使用uni.chooseLocation,app云打包后,定位地址列表一直在加载中

复现BUG 1、自己生成一个证书 参考生成证书流程 2、使用刚生成证书的SHA1 &#xff0c;重新创建一个高德key 高德开放平台地址 3、打包&#xff08;打包的包名要与高德申请key所填的包名一致&#xff09;

Java面试八股之Synchronized锁升级的原理

Synchronized锁升级的原理 Synchronized锁升级是Java为了提高并发性能而引入的一项优化措施&#xff0c;这一机制主要发生在JDK 1.6及之后的版本中。Synchronized锁升级旨在减少锁带来的性能开销&#xff0c;通过从低开销的锁逐步升级到高开销的锁&#xff0c;以适应不同的竞争…

从零入门激光SLAM(二十一)——FAST-LIO2论文解析

FAST-LIO2: Fast Direct LiDAR-Inertial Odometry 论文地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9697912 代码&#xff1a;https://github.com/hku-mars/FAST_LIO 一、文章概述 1.问题导向 基于视觉传感器的高分辨率和高精度的实时密…

Docker笔记-搭建达梦Python环境(dmPython + SQLAlchemy)

背景 达梦提供的C接口&#xff0c;dpi和java的jar包已经很好用了&#xff0c;想不到&#xff0c;来了一个用python的同事&#xff0c;这里就只能适应下他了&#xff0c;在不影响其他环境下搭建一个python的达梦环境。最后发现&#xff0c;python对进行达梦增删改查&#xff0c…