Qt---录音

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_OBJECT

public:
	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_OBJECT

public:
    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.0

signals:
    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_maxAmplitude
    switch (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 of
        default:
            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);
                    else
                        value = 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));
                    else
                        value = 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);
                    else
                        value = 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));
                    else
                        value = 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_OBJECT

public:
	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转动带来的噪声过大呢)

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

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

相关文章

利用开源工具创建WEBGIS应用

在本文中&#xff0c;我们将大致说明利用开源工具如何与服务器交互以构建交互式或动态 Web GIS。 WebGIS 应用程序已成为展示地理数据的重要模式。我们现在拥有允许用户交互的机制&#xff0c;以便用户可以选择数据&#xff0c;甚至修改或添加新数据。 什么是WEBGIS? 通过网络…

大创项目推荐 深度学习手势识别 - yolo python opencv cnn 机器视觉

文章目录 0 前言1 课题背景2 卷积神经网络2.1卷积层2.2 池化层2.3 激活函数2.4 全连接层2.5 使用tensorflow中keras模块实现卷积神经网络 3 YOLOV53.1 网络架构图3.2 输入端3.3 基准网络3.4 Neck网络3.5 Head输出层 4 数据集准备4.1 数据标注简介4.2 数据保存 5 模型训练5.1 修…

用markdown(typora)画系统框图或系统结构图

markdown本身是不支持画系统框图或系统结构图的&#xff1b;但是可以参考excel的语法格式&#xff0c;用合并单元格填充背景色&#xff0c;来实现我们预期的效果&#xff1b; 源代码是html语法&#xff0c;如果有其它需求也可以自己搜索html语法&#xff0c;进行优化 <ta…

netcat一键开始瑞士军刀模式(KALI工具系列五)

目录 1、KALI LINUX简介 2、netcat工具简介 3、在KALI中使用netcat 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 测试某IP的端口是否打开 4.2 TCP扫描 4.3 UDP扫描 4.4 端口刺探 4.5 直接扫描 5、即时通信 5.1 单击对话互联 5.2 传…

单向无头链表实现

目录 1. 为什么要有链表&#xff1f; 2. 链表的种类 3. 具体功能实现 &#xff08;1&#xff09;节点结构体定义 &#xff08;2&#xff09;申请节点 &#xff08;3&#xff09;尾插 &#xff08;4&#xff09;尾删 &#xff08;5&#xff09;头插 &#xff08;6&#…

文本信息的二维码怎么做?在线制作文本二维码的3个步骤

现在通过二维码来展示文本信息是很常见的一种方式&#xff0c;可以将信息编辑好排版后生成二维码&#xff0c;其他人可以通过扫描生成的二维码来获取文本信息。这种方式传递起来更加的简单快捷&#xff0c;而且二维码可以长期提供内容展示效果降低了推广成本&#xff0c;在很多…

数据库系统概论(第5版)复习笔记

笔记的Github仓库地址 &#x1f446;这是笔记的gihub仓库&#xff0c;内容是PDF格式。 因为图片和代码块太多&#xff0c;放到CSDN太麻烦了&#xff08;比较懒&#x1f923;&#xff09; 如果感觉对各位有帮助的话欢迎点一个⭐\^o^/

Elasticsearch 加速在无服务器上构建 AI 搜索应用程序

作者&#xff1a;来自 Elastic Alvin Richards, Yaru Lin 今天&#xff0c;我们宣布推出 Elasticsearch Serverless 技术预览版&#xff0c;其功能包括&#xff1a; 以开发人员为中心的体验&#xff0c;通过直观的入门和相关代码示例简化创建人工智能驱动的搜索&#xff0c;所…

常态化运营,让数据安全工作落地生根!

数据安全如同城堡的基石&#xff0c;其重要性无需赘述。 数据安全防护体系的建设&#xff0c;解决数据安全措施“有”和“无”的问题&#xff1b;常态化的数据安全运营工作&#xff0c;解决的是数据安全“能用”和“好用”的问题。 因此&#xff0c;如何让数据安全成为一种常…

国赛部分复现

MISC 神秘文件 下载解压后是个pptm文件&#xff0c;内容丰富 使用010打开ppt查看 发现为PK开头&#xff0c;属于压缩包文件。复制粘贴ppt&#xff0c;修改副本后缀为.zip并解压 part1 查看属性&#xff0c;发现奇怪字符 QFCfpPQ6ZymuM3gq 根据提示Bifid chipher&#xff0c;…

2024中青杯数学建模竞赛B题药物属性预测思路代码论文分享

2024年中青杯数学建模竞赛B题论文和代码已完成&#xff0c;代码为B题全部问题的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建立和求解、问题2模型的建立和求解、问题3模型的建立和求解&#xff09;、模型…

一剪梅-答赠云安客刘自果

当众网友看了笔者“边吸氧边动鼠标”的短视频之后&#xff0c;纷纷发来微信问候。其中我的远房亲戚&#xff0c;那个正在潜心写作数十万字的长篇纪实文学《川江向东流》的66岁贤弟刘自果&#xff08;号云安客&#xff0c;亦称自果居士&#xff09;&#xff0c;发来微信鼓励我&a…

图生代码,从Hello Onion 代码开始

从Hello Onion 代码开始 1&#xff0c;从代码开始 原生语言采用java 作为载体。通过注解方式实现“UI可视化元素"与代码bean之间的映射. 转换示例 2&#xff0c;运行解析原理 在执行JAVA代码期间&#xff0c;通过读取注解信息&#xff0c;转换为前端的JSON交由前端JS框…

java中的TreeMap类和Hashtable类+Map集合遍历+集合小结

一、TreeMap类 实现了Map接口&#xff0c;元素为键值对、键不可重复、值可重复 特点&#xff1a;可排序 要求&#xff1a;Key类必须实现Comparable接口 底层结构&#xff1a;红黑树 1、可排序 2、常用方法 与HashMap一致 二、Hashtable类 实现了Map接口&#xff0c;元素…

springboot+jsp校园理发店美容美发店信息管理系统0h29g

前台管理:会员管理、会员预定、开单点单、收银结帐、技师提成 后台管理:数据维护、物料管理、数据查询、报表分析、系统设置等 灵活的付款方式&#xff0c;支持现金、挂帐、会员卡&#xff0c;同时支持多种折扣方式并可按用户要求设置多种结帐类型善的充值卡管理模块:支持优惠卡…

Postman进阶功能-Mock服务与监控

大家好&#xff0c;前面跟大家分享一些关于 Postman 的进阶功能&#xff0c;当我们深入探索 Postman 的进阶功能时&#xff0c;Mock 服务与监控这两个重要方面便跃然眼前。 首先&#xff0c;Mock 服务为我们提供了一种灵活便捷的方式&#xff0c;让我们在某些实际接口尚未准备好…

IS-IS基本配置 IS-IS邻接关系

一.IS-IS基本配置 原理概述 和 OSPF 路由协议一样&#xff0c; IS-IS 也是一个应用非常广泛的 IGP 路由协议&#xff0c;很多 ISP 网络、特别是大型的ISP网络都部署了IS-IS网络协议。 RIP 、 OSPF 等许多 IGP 都是针对 IP ( Internet Protocol &#xff09;这个网络层协议而开…

【Vue】性能优化

使用 key 对于通过循环生成的列表&#xff0c;应给每个列表项一个稳定且唯一的 key&#xff0c;这有利于在列表变动时&#xff0c;尽量少的删除和新增元素。 使用冻结的对象 冻结的对象&#xff08;Object.freeze(obj)&#xff09;不会被响应化&#xff0c;不可变。 使用函…

Vue2基础及其进阶面试(一)

简单版项目初始化 新建一个vue2 官网文档&#xff1a;介绍 — Vue.js 先确保下载了vue的脚手架 npm install -g vue-cli npm install -g vue/cli --force vue -V 创建项目 vue create 自己起个名字 选择自己选择特性 选择&#xff1a; Babel&#xff1a;他可以将我们写…

springboot+jwt+shiro+vue+elementUI+axios+redis+mysql完成一个前后端分离的博客项目

目录 简易博客项目(springbootjwtshirovueelementUIaxiosredismysql)第一章 整合新建springboot,整合mybatisplus第一步 创建项目(第八步骤就行)数据库:1、 修改pom.xml2、修改配置文件3、创建数据库vueblog然后执行下面命令生成表 第二步 配置分页MybatisPlusConfig生成代码(d…