QSoundEffect独立声音播放线程 movetothread方式

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下载

上一篇:安卓蓝牙技术Bluetooth使用流程(Bluetooth详解)


下一篇:Shell-实际业务操作03