QSoundEffect独立声音播放线程 movetothread方式
话不多说,先上代码:
- audiothread.h
#ifndef DLTHREAD_H
#define DLTHREAD_H
/**********************************************************************
*@projectName MVRecoTL
*@brief QSoundEffect独立声音播放线程 movetothread方式
*Author: zlozl
*Copyright: zlozl
*Email: zlozl5566@163.com
*QQ: 849414798
*BlogAddress: https://blog.csdn.net/ZLOZL
*GiteeHome: https://gitee.com/zlozl5566
*Version: V1.0.0.1
*Create Date: 2021-01-07
**********************************************************************/
/*[TODO]
* Date: 2021-05-17
* 频繁切换音频,会导致程序异常退出
*
*/
//import Qt
#include <QtCore>
#include <QObject>
#include <QSoundEffect>
#include <QThread>
#include <QSound>
//import zlozl
#include "app.h"
#include "mvpublic.h"
enum VOICE_TYPE{
VOICE_TOOFAR, //太远(请靠近)
VOICE_TOOCLOSE, //太近(请远离)
VOICE_TAKEOFFMASK, //请摘下口罩
VOICE_TAKEOFFGLASSES, //请取下眼镜
VOICE_OPENEYES, //请睁大眼睛
VOICE_BLINKEYES, //请眨眼
VOICE_TAKEOFFHAT, //请脱下帽子
VOICE_HEADUP, //请抬头
VOICE_HEADDOWN, //请低头
VOICE_DONOTLOOKUP, //请勿抬头
VOICE_DONOTBOW, //请勿低头
VOICE_DONOTSHAKE, //请勿摇头
VOICE_LOOKCAMERA, //请正视镜头
VOICE_SCREENCLICK, //屏幕点击音效
VOICE_STARTFACEENROLL, //开始人脸采集
VOICE_STARTIRISENROLL, //开始虹膜采集
VOICE_STARTFINGERENROLL, //开始指纹采集
VOICE_STARTCREDENROLL, //开始证件采集
VOICE_PLACECCRED, //请放置好证件
VOICE_PRESSFINGER, //请按压指纹
VOICE_GUIEDACTION, //请按照动画提示完成相应动作
VOICE_ENROLLOVERTIME, //采集超时
VOICE_RECOOVERTIME, //识别超时
VOICE_ENROLLSUCCESS, //采集成功
VOICE_RECOPSAA, //识别成功
VOICE_VERIFYSIGN, //请核对采集信息后签字
VOICE_VERIFYCOMMIT, //请核对信息后提交
VOICE_COMMITSUCCESS, //提交成功
};
//第三方声音文件
const QString g_third_voiceFileDirName = "/voice/";
//终端自带语音文件
const QString g_mvtl_voiceFileDirName = "/TLVoice/";
class AudioThread : public QObject
{
Q_OBJECT
public:
explicit AudioThread(QObject *parent = nullptr);
~AudioThread();
Q_DISABLE_COPY(AudioThread);
signals:
void doPlay();
void doStop();
public slots:
//自定义语音类型播放,声音播放优先级最高,单次不循环 会覆盖播放
void play(int type);
//自定义语音类型播放,声音播放优先级最低,单次不循环 不会覆盖播放
void play_lowestPriority(int type);
//播放第三方文件夹下语音名称,声音播放优先级最高,单次不循环 会覆盖播放
void play_thirdFiles(const QString &fileName);
//暂停播放
void stop();
void on_sourceChanged();
void on_statusChanged();
private:
int voice_type;
QSoundEffect* m_peffect;
QThread* m_pthread;
//上一次播放的音频
QUrl m_last_url;
QUrl m_third_url;
};
#endif // DLTHREAD_H
- audiothread.cpp
#include "audiothread.h"
#include <QUrl>
AudioThread::AudioThread(QObject *parent) :
QObject(parent)
{
m_pthread = new QThread();
m_peffect = new QSoundEffect();
m_peffect->moveToThread(m_pthread);
connect(m_pthread,&QThread::finished, m_peffect,&QSoundEffect::deleteLater);
connect(m_peffect,&QSoundEffect::destroyed, m_pthread,&QThread::deleteLater);
connect(this, &AudioThread::doPlay, m_peffect, &QSoundEffect::play);
connect(this, &AudioThread::doStop, m_peffect, &QSoundEffect::stop);
connect(m_peffect, &QSoundEffect::sourceChanged, this, &AudioThread::on_sourceChanged);
connect(m_peffect, &QSoundEffect::statusChanged, this, &AudioThread::on_statusChanged);
m_pthread->start();
}
AudioThread::~AudioThread()
{
if(m_pthread->isRunning())
{
qDebug()<<"~AudioThread";
m_pthread->quit();
m_pthread->wait();
}
}
void AudioThread::play(int type)
{
// qDebug()<<"play ThreadID: "<<QThread::currentThreadId();
if(m_peffect->isPlaying()) {
qDebug()<<"effect is playing ThreadID: "<<QThread::currentThreadId();
emit this->doStop();
m_peffect->stop();
// MVPublic::msleep(100);
// qDebug()<<"effect is stoped";
}
voice_type = type;
QString fileName;
switch (voice_type)
{
case VOICE_TOOCLOSE:
{
fileName = "TOOCLOSE.wav";
}
break;
case VOICE_TOOFAR:
{
fileName = "TOOFAR.wav";
}
break;
case VOICE_TAKEOFFMASK:
{
fileName = "TAKEOFFMASK.wav";
}
break;
case VOICE_TAKEOFFGLASSES:
{
fileName = "TAKEOFFGLASSES.wav";
}
break;
case VOICE_OPENEYES:
{
fileName = "OPENEYES.wav";
}
break;
case VOICE_BLINKEYES:
{
fileName = "BLINKEYES.wav";
}
break;
case VOICE_TAKEOFFHAT:
{
fileName = "TAKEOFFHAT.wav";
}
break;
case VOICE_HEADUP:
{
fileName = "HEADUP.wav";
}
break;
case VOICE_HEADDOWN:
{
fileName = "HEADDOWN.wav";
}
break;
case VOICE_DONOTLOOKUP:
{
fileName = "DONOTLOOKUP.wav";
}
break;
case VOICE_DONOTBOW:
{
fileName = "DONOTBOW.wav";
}
break;
case VOICE_DONOTSHAKE:
{
fileName = "DONOTSHAKE.wav";
}
break;
case VOICE_LOOKCAMERA:
{
fileName = "LOOKCAMERA.wav";
}
break;
case VOICE_SCREENCLICK:
{
fileName = "SCREENCLICK.wav";
}
break;
case VOICE_STARTFACEENROLL:
{
fileName = "STARTFACEENROLL.wav";
}
break;
case VOICE_STARTIRISENROLL:
{
fileName = "STARTIRISENROLL.wav";
}
break;
case VOICE_STARTFINGERENROLL:
{
fileName = "STARTFINGERENROLL.wav";
}
break;
case VOICE_STARTCREDENROLL:
{
fileName = "STARTCREDENROLL.wav";
}
break;
case VOICE_PLACECCRED:
{
fileName = "PLACECCRED.wav";
}
break;
case VOICE_PRESSFINGER:
{
fileName = "PRESSFINGER.wav";
}
break;
case VOICE_GUIEDACTION:
{
fileName = "GUIEDACTION.wav";
}
break;
case VOICE_ENROLLOVERTIME:
{
fileName = "ENROLLOVERTIME.wav";
}
break;
case VOICE_RECOOVERTIME:
{
fileName = "RECOOVERTIME.wav";
}
break;
case VOICE_ENROLLSUCCESS:
{
fileName = "ENROLLSUCCESS.wav";
}
break;
case VOICE_RECOPSAA:
{
fileName = "RECOPSAA.wav";
}
break;
case VOICE_VERIFYSIGN:
{
fileName = "VERIFYSIGN.wav";
}
break;
case VOICE_VERIFYCOMMIT:
{
fileName = "VERIFYCOMMIT.wav";
}
break;
case VOICE_COMMITSUCCESS:
{
fileName = "COMMITSUCCESS.wav";
}
break;
default:
{
return;
}
}
/*频繁切换音频,会导致程序异常退出*/
if (m_last_url != QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName)) {
qDebug()<<"play start setSource.....fileName: "<<fileName;
m_last_url = QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName);
m_peffect->setSource(QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName));
emit m_peffect->sourceChanged();
}
m_peffect->setLoopCount(1);
m_peffect->setVolume(1.0f);
emit this->doPlay();
}
void AudioThread::play_lowestPriority(int type)
{
if(m_peffect->isPlaying())
{
//加入延迟避免短暂连续播放
//MVPublic::sleep(10);
//不覆盖播放
return;
}
voice_type = type;
QString fileName;
switch (voice_type)
{
case VOICE_TOOCLOSE:
{
fileName = "TOOCLOSE.wav";
}
break;
case VOICE_TOOFAR:
{
fileName = "TOOFAR.wav";
}
break;
case VOICE_TAKEOFFMASK:
{
fileName = "TAKEOFFMASK.wav";
}
break;
case VOICE_TAKEOFFGLASSES:
{
fileName = "TAKEOFFGLASSES.wav";
}
break;
case VOICE_OPENEYES:
{
fileName = "OPENEYES.wav";
}
break;
case VOICE_BLINKEYES:
{
fileName = "BLINKEYES.wav";
}
break;
case VOICE_TAKEOFFHAT:
{
fileName = "TAKEOFFHAT.wav";
}
break;
case VOICE_HEADUP:
{
fileName = "HEADUP.wav";
}
break;
case VOICE_HEADDOWN:
{
fileName = "HEADDOWN.wav";
}
break;
default:
{
return;
}
}
/*频繁切换音频,会导致程序异常退出*/
if (m_last_url != QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName)) {
qDebug()<<"play_lowestPriority start setSource.....fileName: "<<fileName;
m_last_url = QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName);
m_peffect->setSource(QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName));
emit m_peffect->sourceChanged();
}
m_peffect->setLoopCount(1);
m_peffect->setVolume(1.0f);
emit this->doPlay();
}
void AudioThread::play_thirdFiles(const QString &fileName)
{
if(m_peffect->isPlaying()) {
emit this->doStop();
m_peffect->stop();
}
/*频繁切换音频,会导致程序异常退出*/
if (m_third_url != QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName)) {
qDebug()<<"play_thirdFiles start setSource.....fileName: "<<fileName;
m_third_url = QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName);
m_peffect->setSource(QUrl::fromLocalFile(App::appPath +g_mvtl_voiceFileDirName+fileName));
emit m_peffect->sourceChanged();
}
m_peffect->setLoopCount(1);
m_peffect->setVolume(1.0f);
emit this->doPlay();
}
void AudioThread::stop()
{
emit this->doStop();
}
void AudioThread::on_sourceChanged()
{
qDebug()<<"on_sourceChanged...";
}
void AudioThread::on_statusChanged()
{
qDebug()<<"on_statusChanged...";
}
1. 自定义语音类型播放,声音播放优先级最高,单次不循环 会覆盖播放
2. 自定义语音类型播放,声音播放优先级最低,单次不循环 不会覆盖播放
3. 播放第三方文件夹下语音名称,声音播放优先级最高,单次不循环 会覆盖播放
4. 暂停播放
完整测试代码已经工程都打包好啦。
下载地址:
(1条消息) QQSoundEffect_test.zip-C++文档类资源-CSDN下载