欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt循环播放音乐后程序异常崩溃 (SIGSEGV错误)

程序员文章站 2022-04-22 16:07:52
...

一、出现问题

当我想为我的游戏添加背景音乐并让它循环播放时,我采取的方式是写一个bgmusic类(文章末尾我会给出没有问题的bgmusic的具体实现),它继承自QThread,并重写其中的run方法。至于这个类的使用,就是在需要播放背景音乐的地方直接new出一个对象,调用其start方法即可

普遍的做法(也是我刚开始出错的做法)如下代码所示:

QMediaPlaylist *playlist = new QMediaPlaylist();
playlist->addMedia(QUrl("qrc:/res/bg-Music.mp3")); // 请关注这里,只添加了一个音频
playlist->setPlaybackMode(QMediaPlaylist::Loop);
playerlist->setCurrentIndex(0);
QMediaPlayer *music = new QMediaPlayer();
music->setPlaylist(playlist);
music->play();

但如果直接这样写的话,当程序播放完背景音乐后,程序便会异常崩溃

小Tips:请关注资源的路径写法 ,如下图所示。

Qt循环播放音乐后程序异常崩溃 (SIGSEGV错误)


二、分析问题

经过调试,发现是程序出现段错误,被操作系统异常终止。这个错误是程序中经常出现的一个错误,程序访问了不该访问的地址。
那么,接下来,看qt的官方文档:
Qt循环播放音乐后程序异常崩溃 (SIGSEGV错误)
setMedia 函数会立即返回,不会等待媒体加载完毕。崩溃的原因应该就是有时加载快,完成了播放正常,有时加载慢未完成,播放就崩溃。


三、解决问题

3.1 针对上述普遍的做法的解决方案

保证QMediaPlaylist对象中添加了多于1个的音频对象
更改后的代码如下:

QMediaPlaylist *playlist = new QMediaPlaylist();
playlist->addMedia(QUrl("qrc:/res/bg-Music.mp3"));
playlist->addMedia(QUrl("qrc:/res/bg-Music.mp3")); // 新增加的
playlist->setPlaybackMode(QMediaPlaylist::Loop);
playerlist->setCurrentIndex(0);
QMediaPlayer *music = new QMediaPlayer();
music->setPlaylist(playlist);
music->play();

3.2针对于不使用QMediaPlaylist,而只是用QMediaPlay对象实现循环播放的解决方案

要在你写的类中增加一个槽函数去监听QMediaPlayer::mediaStatusChanged信号


四、具体代码

需要说明的是,我将两种解决方案都写在了同一份代码中,并采用的是方案一,代码中我将方案二注释掉了,读者可以根据需要自行选择。

bgmusic.h

#ifndef BGMUSIC_H
#define BGMUSIC_H

#include <QThread>
#include <QMediaPlayer>
#include <QMediaPlaylist>

class bgmusic : public QThread
{
    Q_OBJECT
    void run() override;
public:
    bgmusic();

private:
    QMediaPlayer* player;
    QMediaPlaylist* playerList;
    void initStatus(QMediaPlayer::MediaStatus status); // 槽函数 监听QMediaPlayer::mediaStatusChanged信号
};

#endif // BGMUSIC_H

bgmusic.cpp

#include "bgmusic.h"

bgmusic::bgmusic()
{
    playerList = new QMediaPlaylist();
    player = new QMediaPlayer();
    playerList->addMedia(QUrl("qrc:/res/LevelWinSound.wav"));
    playerList->addMedia(QUrl("qrc:/res/TapButtonSound.wav")); // 方法一、保证有两个音频(可以相同)被添加
    playerList->setPlaybackMode(QMediaPlaylist::Loop);
    playerList->setCurrentIndex(0);
    player->setPlaylist(playerList);
    player->setVolume(100);
   // connect(player, &QMediaPlayer::mediaStatusChanged,this,&bgmusic::initStatus);// 方法二 槽函数 监听QMediaPlayer::mediaStatusChanged信号   进行连接
}

void bgmusic::run() {
     player->play();
}

void bgmusic::initStatus(QMediaPlayer::MediaStatus status){
    if(status == QMediaPlayer::EndOfMedia)
      {
          // player->setPosition(0);
          // player->play();
      }
}

相关标签: c++ qt