当前位置: 首页 > 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…...

HuggingFace大语言模型实战:如何用Python脚本批量翻译YouTube字幕(含环境配置避坑指南)

HuggingFace大语言模型实战&#xff1a;Python脚本批量翻译YouTube字幕全攻略 当你在YouTube上发现一段精彩的英文技术讲座&#xff0c;或是需要研究某个外语行业报告时&#xff0c;自动翻译工具能大幅提升信息获取效率。本文将带你用HuggingFace生态构建一个本地化翻译工作流&…...

片上网络NOC:可生成RTL源代码与UVM验证环境的实用学习资料

片上网络NOC&#xff0c;可生成RTL源代码&#xff0c;生成uvm验证环境&#xff0c;内含有丰富的文档&#xff0c;带有readme文档&#xff0c;有例子工程&#xff0c;操作简单&#xff0c;是学习工作的好资料最近折腾NoC项目的时候挖到一个宝藏工具包&#xff0c;名字先不透露&a…...

抖音下载器:从零开始,轻松获取无水印视频的完整指南

抖音下载器&#xff1a;从零开始&#xff0c;轻松获取无水印视频的完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallb…...

xiaomusic启动故障终极解决指南:设备认证配置与开源智能家居集成方案

xiaomusic启动故障终极解决指南&#xff1a;设备认证配置与开源智能家居集成方案 【免费下载链接】xiaomusic 使用小爱音箱播放音乐&#xff0c;音乐使用 yt-dlp 下载。 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaomusic 问题定位&#xff1a;识别xiaomusi…...

Agent设计模式学习(基于langchain4j实现)(6) - 组合复杂工作流

一、定义Agent 1.1 CandidateWorkflow 1 public interface CandidateWorkflow { 2 Agent("根据个人履历和职位描述生成主简历&#xff0c;通过反馈循环针对职位描述进行定制&#xff0c;直至达到合格分数") 3 String processCandidate(V("lifeStory&q…...

门店小程序和收银系统有什么区别?

门店小程序和收银系统有什么区别&#xff1f;在门店数字化过程中&#xff0c;很多企业会同时接触到小程序与收银系统&#xff0c;但两者在功能定位和使用场景上存在明显差异。门店小程序和收银系统的本质区别&#xff0c;在于一个偏向“获客与转化入口”&#xff0c;一个偏向“…...

像素史诗智识终端效果展示:自动提取数据关键指标并生成结论段落

像素史诗智识终端效果展示&#xff1a;自动提取数据关键指标并生成结论段落 1. 产品概览&#xff1a;当科研遇上像素冒险 像素史诗智识终端(Pixel Epic Wisdom Terminal)是一款颠覆传统的研究报告辅助工具。它将枯燥的数据分析过程转化为一场充满像素美学的RPG冒险&#xff0…...

HunyuanVideo-Foley创意音效作品展:突破传统声音设计的边界

HunyuanVideo-Foley创意音效作品展&#xff1a;突破传统声音设计的边界 1. 当AI遇见声音艺术 声音设计领域正在经历一场革命。传统Foley音效制作需要大量物理道具和录音设备&#xff0c;而AI技术的引入让声音创作突破了物理限制。HunyuanVideo-Foley作为新一代AI音效生成工具…...

C++实战:高精度阶乘算法的实现与优化

1. 为什么我们需要高精度阶乘算法&#xff1f; 当你第一次学习编程时&#xff0c;可能会用循环或递归来实现阶乘计算。比如用C写个简单的for循环&#xff0c;轻松计算出5! 120。但当你尝试计算20!时&#xff0c;事情就开始变得有趣了——你会发现结果完全不对&#xff0c;甚至…...

别再手动调了!用Visio这个隐藏的字体设置窗口,一键切换泳道图标题横竖排

Visio高效技巧&#xff1a;解锁泳道图标题排版的隐藏技能 每次在Visio中调整泳道图标题方向时&#xff0c;你是否还在反复右键点击、寻找格式选项&#xff1f;其实Visio内置了一个被多数用户忽略的高效设置窗口——"字体"对话框。这个看似普通的设置面板&#xff0c;…...