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

QT-播放原始PCM音频流

QT +=  multimedia

audioplay.h

/*************************************************************************
接口描述:原始音频播放类
拟制:
接口版本:V1.0
时间:20220922
说明:
*************************************************************************/#ifndef AUDIOPLAY_H
#define AUDIOPLAY_H#include <QAudioFormat>
#include <QAudioOutput>
#include <QMutex>
#include <QThread>class AudioThread;
class AudioPlay : public QObject
{Q_OBJECT
public:explicit AudioPlay(QObject *parent = nullptr);~AudioPlay();public:void inputVoice(char *pcVoice, int nLen);   //PCM数据输入void setSampleRate(int nSampleRate);        //设置采样率void stop();                                //停止播放signals:void sendDataSignal(QByteArray qbaData);void inputVoiceSignal(QByteArray qbaData);void setSampleRateSignal(int nSampleRate);void stopAudio();private slots:void audioStateChanged(QAudio::State state);private:QAudioFormat m_audioFormat;int m_nSampleRate;bool m_bAudioOpen;QAudioOutput *m_pAudioOutput;AudioThread *m_pAudioThread;QThread *m_pThread;private:void audioPlay();void setFormat();void releaseAudio();
};class AudioDevice : public QIODevice
{Q_OBJECT
public:explicit AudioDevice(QObject *parent = nullptr);public:void inputData(char *pcData, int nLen);void start();void stop();// QIODevice interface
protected:qint64 readData(char *data, qint64 maxlen);qint64 writeData(const char *data, qint64 len);qint64 bytesAvailable() const;private:QByteArray m_qbaAudioBuffer;
};class AudioThread : public QObject
{Q_OBJECT
public:explicit AudioThread(QAudioOutput *pAudioOutput, QObject *parent = nullptr);~AudioThread();public slots:void inputData(QByteArray qbaData);private:QAudioOutput *m_pAudioOutput;AudioDevice *m_pAudioDevice;
};#endif // AUDIOPLAY_H

audioplay.cpp

#include "audioplay.h"
#include <QDebug>static QMutex m_mutex;AudioPlay::AudioPlay(QObject *parent): QObject(parent)
{m_nSampleRate = 8000;m_bAudioOpen = false;m_pAudioOutput = nullptr;m_pAudioThread = nullptr;setFormat();m_pThread = new QThread;m_pThread->start();connect(this,&AudioPlay::inputVoiceSignal,this,[&](QByteArray qbaData) {if (!m_bAudioOpen) {audioPlay();}emit sendDataSignal(qbaData);},Qt::QueuedConnection);connect(this,&AudioPlay::setSampleRateSignal,this,[&](int nSampleRate) {if (m_nSampleRate != nSampleRate) {m_nSampleRate = nSampleRate;setFormat();}},Qt::QueuedConnection);connect(this, &AudioPlay::stopAudio, this, [&] {m_bAudioOpen = false;releaseAudio();});
}AudioPlay::~AudioPlay()
{releaseAudio();m_pThread->exit();if (m_pThread != nullptr) {m_pThread->deleteLater();m_pThread = nullptr;}
}void AudioPlay::inputVoice(char *pcVoice, int nLen)
{emit inputVoiceSignal(QByteArray(pcVoice, nLen));
}void AudioPlay::setSampleRate(int nSampleRate)
{emit setSampleRateSignal(nSampleRate);
}void AudioPlay::stop()
{emit stopAudio();
}void AudioPlay::audioStateChanged(QAudio::State state)
{switch (state) {case QAudio::IdleState:m_bAudioOpen = false;releaseAudio();setFormat();break;default:break;}
}void AudioPlay::audioPlay()
{QList<QAudioDeviceInfo> outputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);if (outputDevices.size() <= 0) {return;}if (m_pAudioOutput == nullptr) {m_pAudioOutput = new QAudioOutput(m_audioFormat);connect(m_pAudioOutput, &QAudioOutput::stateChanged, this, &AudioPlay::audioStateChanged);if (m_pAudioThread) {m_pAudioThread->deleteLater();m_pAudioThread = nullptr;}m_pAudioThread = new AudioThread(m_pAudioOutput);m_pAudioThread->moveToThread(m_pThread);connect(this,&AudioPlay::sendDataSignal,m_pAudioThread,&AudioThread::inputData,Qt::QueuedConnection);}m_bAudioOpen = true;
}void AudioPlay::setFormat()
{if (m_pAudioOutput != nullptr) {m_pAudioOutput->reset();m_pAudioOutput->start();}//设置采样率m_audioFormat.setSampleRate(m_nSampleRate);//设置通道数m_audioFormat.setChannelCount(1);//设置采样大小,一般为8位或16位m_audioFormat.setSampleSize(16);//设置编码方式m_audioFormat.setCodec("audio/pcm");//设置字节序m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);//设置样本数据类型m_audioFormat.setSampleType(QAudioFormat::SignedInt);
}void AudioPlay::releaseAudio()
{if (m_pAudioThread != nullptr) {m_pAudioThread->deleteLater();m_pAudioThread = nullptr;}if (m_pAudioOutput != nullptr) {m_pAudioOutput->stop();m_pAudioOutput->deleteLater();m_pAudioOutput = nullptr;}
}AudioDevice::AudioDevice(QObject *parent): QIODevice(parent)
{QMutexLocker locker(&m_mutex);m_qbaAudioBuffer.clear();
}void AudioDevice::inputData(char *pcData, int nLen)
{QMutexLocker locker(&m_mutex);m_qbaAudioBuffer.append(pcData, nLen);
}void AudioDevice::start()
{if (!this->isOpen()) {open(QIODevice::ReadOnly);}
}void AudioDevice::stop()
{QMutexLocker locker(&m_mutex);m_qbaAudioBuffer.clear();this->close();
}qint64 AudioDevice::bytesAvailable() const
{QMutexLocker locker(&m_mutex);qint64 llReturn = m_qbaAudioBuffer.size() + QIODevice::bytesAvailable();return llReturn;
}qint64 AudioDevice::readData(char *data, qint64 maxlen)
{QMutexLocker locker(&m_mutex);memset(data, 0, maxlen);if (m_qbaAudioBuffer.size() < maxlen) {maxlen = m_qbaAudioBuffer.size();}if (maxlen > 0) {memcpy(data, m_qbaAudioBuffer.left(maxlen).data(), maxlen);m_qbaAudioBuffer.remove(0, maxlen);}return maxlen;
}qint64 AudioDevice::writeData(const char *data, qint64 len)
{Q_UNUSED(data);Q_UNUSED(len);return 0;
}AudioThread::AudioThread(QAudioOutput *pAudioOutput, QObject *parent): QObject(parent)
{m_pAudioOutput = nullptr;m_pAudioDevice = nullptr;m_pAudioDevice = new AudioDevice(this);m_pAudioDevice->start();m_pAudioOutput = pAudioOutput;m_pAudioOutput->start(m_pAudioDevice);
}AudioThread::~AudioThread()
{if (m_pAudioDevice != nullptr) {m_pAudioDevice->stop();m_pAudioDevice->deleteLater();m_pAudioDevice = nullptr;}
}void AudioThread::inputData(QByteArray qbaData)
{if (m_pAudioDevice != nullptr) {m_pAudioDevice->inputData(qbaData.data(), qbaData.size());}
}

相关文章:

QT-播放原始PCM音频流

QT multimedia audioplay.h /************************************************************************* 接口描述&#xff1a;原始音频播放类 拟制&#xff1a; 接口版本&#xff1a;V1.0 时间&#xff1a;20220922 说明&#xff1a; ********************************…...

【杂谈】聊聊我是如何从Java转入Web3的

我先说说我基本的一个情况吧&#xff1a; 我是之前是一位从业了传统web2行业三年的Java开发&#xff0c;在2018年尾才开始去关注区块链的&#xff0c;之前虽然也有混迹在币圈&#xff0c;但是没怎么关注到币圈的内在运行逻辑。 后面因为当时元宇宙和Web3的概念特别火&a…...

ArrayList

目录 1.ArrayList简介 2.ArrayList的构造 2.1ArrayList() 2.2ArrayList(Collection c) 2.3ArrayList(int initialCapacity) 3.ArrayList常见操作 4.ArrayList的遍历的遍历 1.ArrayList简介 在集合框架中&#xff0c; ArrayList 是一个普通的类&#xff0c;实现了 List…...

不重启Docker能添加自签SSL证书镜像仓库吗?

应用背景 在企业应用Docker规划初期配置非安全镜像仓库时&#xff0c;有时会遗漏一些仓库没配置&#xff0c;但此时应用程序已经在Docker平台上部署起来了&#xff0c;体量越大就越不会让人去直接重启Docker。 那么&#xff0c;不重启Docker能添加自签SSL证书镜像仓库吗&…...

Ajax介绍

1.与服务器进行数据交换&#xff1a;通过 Ajax 可以给服务器发送请求&#xff0c;并获取服务器响应的数据。 2.异步交互&#xff1a;可以在 不重新加载整个页面 的情况下&#xff0c;与服务器交换数据并 更新部分网页 的技术&#xff0c;如&#xff1a; 搜索联想、用户名是否可…...

docker 学习--02 常用命令

docker 学习–02 常用命令 docker 学习-- 01 基础知识 docker 学习-- 03 环境安装&#xff08;win10&#xff09; 文章目录 docker 学习--02 常用命令1. 帮助启动类命令1.1启动docker1.2 停止docker1.3 重启docker1.4 查看docker1.5 设置开机自启1.6 查看docker概要信息1.7 查…...

socks5 保障网络安全与爬虫需求的完美融合

Socks5代理&#xff1a;跨足网络安全和爬虫领域的全能选手 Socks5代理作为一种通用的网络协议&#xff0c;为多种应用场景提供了强大的代理能力。它不仅支持TCP和UDP的数据传输&#xff0c;还具备更高级的安全特性&#xff0c;如用户身份验证和加密通信。在网络安全中&#xf…...

构建智能医疗未来:人工智能在线上问诊系统开发中的应用

随着人工智能技术的飞速发展&#xff0c;医疗领域也正在逐步迎来一场革命性的变革。其中&#xff0c;人工智能在在线上问诊系统开发中的应用&#xff0c;正为医疗产业带来全新的可能性。本文将深入探讨如何利用代码构建智能医疗未来&#xff0c;以提升线上问诊系统的效率、准确…...

css3-grid:grid 布局 / 基础使用

一、理解 grid 二、理解 css grid 布局 CSS Grid布局是一个二维的布局系统&#xff0c;它允许我们通过定义网格和网格中每个元素的位置和尺寸来进行页面布局。CSS Grid是一个非常强大的布局系统&#xff0c;它不仅可以用于构建网格布局&#xff0c;还可以用于定位元素&#xf…...

如何在windows电脑安装多个tomcat服务器和乱码问题

前提条件安装jdk 以17版本为例&#xff0c;将jdk8卸载干净 1.首先进入tomcat官网下载 tomcat网址 这里下载tomcat10为例子 1.1 这里选择方式一 下载解压版 2.解压后拷贝三份 分别命名为 8081、 8082、 8083 3.分别对每个tomcat执行以下操作 3.1 找到tomcat所在webapps文…...

flutter:webview_flutter的简单使用

前言 最近在研究如何在应用程序中嵌入Web视图&#xff0c;发现有两个库不错。 一个是官方维护、一个是第三方维护。因为没说特别的需求&#xff0c;就使用了官方库&#xff0c;实现一些简单功能是完全ok的 基本使用 官方文档 https://pub-web.flutter-io.cn/packages/webv…...

Ansys Zemax | 手机镜头设计 - 第 1 部分:光学设计

本文是 3 篇系列文章的一部分&#xff0c;该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;从概念、设计到制造和结构变形的分析。本文是三部分系列的第一部分&#xff0c;将专注于OpticStudio中镜头模组的设计、分析和可制造性评估。&#xff08;联系我们获取文章附件…...

jvm从入门到精通

jvm 1.jvm与java体系结构​​​​​​​...

[NLP]LLM 训练时GPU显存耗用量估计

以LLM中最常见的Adam fp16混合精度训练为例&#xff0c;分析其显存占用有以下四个部分&#xff1a; GPT-2含有1.5B个参数&#xff0c;如果用fp16格式&#xff0c;只需要1.5G*2Byte3GB显存, 但是模型状态实际上需要耗费1.5B*1624GB. 比如说有一个模型参数量是1M&#xff0c;在…...

Unity引擎使用InteriorCubeMap采样制作假室内效果

Unity引擎制作假室内效果 大家好&#xff0c;我是阿赵。   这次来介绍一种使用CubeMap做假室内效果的方式。这种技术名叫InteriorCubeMap&#xff0c;是UE引擎自带的节点效果。我这里是在Unity引擎里面的实现。 一、效果展示 这个假室内效果&#xff0c;要动态看才能看出效…...

Gin安装解决国内go 与 热加载

get 方式安装超时问题&#xff0c;国内直接用官网推荐的下面这个命令大概率是安装不成功的 go get -u github.com/gin-gonic/gin 可以在你的项目目录下执行下面几个命令&#xff1a; 比如我的项目在E:\Oproject\zl cmd E:\Oproject\zl>就在目录下执行 go env -w GO111…...

安防监控视频云存储平台EasyCVRH.265转码功能更新:新增分辨率配置

安防视频集中存储EasyCVR视频监控综合管理平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上&#xff0c;视频云存储平台EasyCVR可实现视频实时直播、云端录像、视频云存储、视频存储…...

Linux 创建用户赋予root权限,并限定登录ip

1.创建jms用户 创建组 groupadd jms创建用户 -g 指定分组 useradd -m -d /home/jms jms -g jms -s /bin/bash设置用户密码 passwd jms2.赋予root权限 编辑文件 vim /etc/sudoers添加如下内容 jms ALL(ALL:ALL) NOPASSWD: ALL3.限定登录ip 编辑文件&#xff0c;在末尾添…...

基于令牌级 BERT 嵌入的趋势生成句子级嵌入

一、说明 句子&#xff08;短语或段落&#xff09;级别嵌入通常用作许多 NLP 分类问题的输入&#xff0c;例如&#xff0c;在垃圾邮件检测和问答 &#xff08;QA&#xff09; 系统中。在我上一篇文章发现不同级别的BERT嵌入的趋势中&#xff0c;我讨论了如何生成一个向量表示&a…...

计算机视觉目标检测性能指标

目录 精确率&#xff08;Precision&#xff09;和召回率&#xff08;Recall&#xff09; F1分数&#xff08;F1 Score&#xff09; IoU&#xff08;Intersection over Union&#xff09; P-R曲线&#xff08;Precision-Recall Curve&#xff09;和 AP mAP&#xff08;mean…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...