QSound、QSoundEffect播放WAV音频

本文旨在介绍QSound、QSoundEffect的简单播放音频的方法以及对这两个类的一些基本介绍

最近,接受了一个同事写的代码,发现在播放音乐的地方,会有内存泄露,代码如下:

if (type == "HELLO") {
QSound *sound = new QSound("./radio/hello.wav");
sound->play(); // 执行其他操作
}

这里明显会出现内存泄露,但是如果使用局部变量的话,就会在这个if结束之后销毁掉,那有可能音乐没有播放完就停了的结果。

QSound

因为是第一次接触这个类,秉着不懂的就学的原则,所以我转头去看了帮助文档。

简介&使用方法

QSound类提供了一种播放**.wav格式音乐的方法。

你可以使用
QSound**类的静态函数来播放音乐,之前的代码就可以写成下面这样:

QSound::play("./radio/hello.wav");

但是这种方法只会播放一次,没有办法循环播放。你也可以实例化对象,来设置播放的循环次数。

基本函数

  1. fileName()

    这个函数,用于获取设置的资源文件的文件名。

    QString fileName() const;
  2. loops()

    获取音频循环的次数

    int loops() const;
  3. setLoops()

    设置循环的次数

    void setLoops(int number);
  4. loopsRemaining()

    返回音频剩余的循环次数,如果返回的是QSound::Infinite代表循环播放

    int loosRemaining() const;
  5. isFinished()

    判断当前音频是否播放完成。

    bool isFinished() const;
  6. play()与stop()

    play()和stop()函数分别代表开始和结束当前音频的播放。

    void play();
    void stop();

      但是在使用这个类的时候,我有点困惑,都找不到一个信号用于标志音频播放结束了,那怎么去判断是否结束播放,进而释放资源呢?
    然后在文档中找到了一句话:
      大致的意思就是,如果你想要更多对播放的音频的控制,请去看QSoundEffectQAudioOutput这两个类。下面介绍一下这两个类。

QSoundEffect

简介&基本使用

这个类是用于低延迟的播放未经过压缩的音频(比如WAV文件)。这个类的比较常见的应用就是播放一个提示音;
基本的使用方法如下:

QSoundEffect *soundEffect = new QSoundEffect();
// 设置声音源文件的路径
soundEffect->setSource(QUrl::fromLoaclFile("./radio/hello.wav"));
// 音频循环的次数
soundEffect->setLoopCount(1);
// 音量
soundEffect->setVolume(1);
soundEffect->play(); // 连接信号,当播放完毕时,自动销毁对象。
connect(soundEffect, &QSoundEffect::playingChanged, [soundEffect] () {
if (effect->isPlaying()) {
effect->deleteLater();
}
});

  使用这个类,就可以连接信号playingChanged,来实现在音乐播放完之后自动销毁。

属性及对应的函数

这个类拥有的属性有:

  1. category(种类):QString

      这个属性包含当前QSoundEffect的种类,不同的平台,可以根据不同的category来设置执行不同的音频通道或者允许用户设置不同的音量等级。这个应该类似于Windows下的音量合成器
    设置、读取函数和值发生改变时发射的信号分别为:

    // 读取属性函数
    QString category() const // 设置属性函数
    void setCategory(const QString &category); // 属性改变时发射的信号
    void categoryChanged();
  2. loops(循环次数):int

      这个属性保存了音频的循环次数,当这个的值为0或者1时,音频都只会播放一次。当这个属性的值为QSoundEffect::Infinite为无限循环
      这个属性,可以在音频正在播放的时候进行修改,修改其实就是改变remaining loops的值。
    设置、读取函数和值发生改变时发射的信号分别为:

    // 读取属性函数
    int loopCount() const // 设置属性函数
    void setLoopCount(int loops); // 属性改变时发射的信号
    void loopCountChanged();
  3. loopsRemaining(剩余循环次数):const int

    当前音频剩余的播放次数。
    读取的函数和发生改变时发射的信号为:

    // 读取属性函数
    int loopsRemaining() const; // 属性改变时发射的信号
    void loopsRemainingChanged();
  4. muted(静音):bool

    这个属性提供了一种控制静音的方法。
    设置、读取以及发生改变时发射的信号为:

    // 读取属性函数
    bool isMuted() const; // 设置属性函数
    void setMuted(int loops); // 属性改变时发射的信号
    void mutedChanged();
  5. playing(播放状态):bool

    这个属性标识了当前音频是不是处于播放状态。
    对应的函数为:

    // 读取属性函数
    bool isPlaying() const; // 属性改变时发射的信号
    void playingChanged();
  6. source(资源文件):QUrl

    这个属性保存了声音文件的url。如果想要加载资源文件,这个URL必须存在,并且应用必须有访问指定目录的权限。
    对应的函数为:

    // 读取属性函数
    QUrl source() const; // 设置属性函数
    void setSource(const QUrl &url); // 属性改变时发射的信号
    void sourceChanged();
  7. status(状态): const Status

    这个属性指示了当前QSoundEffect的状态。
    对应的函数为:

    // 读取属性函数
    QSoundEffect::Status status() const; // 属性改变时发射的信号
    void statusChanged();
  8. volume(音量):qreal

    这个属性保存了当前播放的音量,范围是[0.0,1.0]。
    对应的函数为:

    // 读取属性函数
    qreal volume() const; // 设置属性函数
    void setVolume(qreal volume); // 属性改变时发射的信号
    void volumeChanged();

源码探秘

再次回到QSound这个类,由于在帮助文档里对QSound::play这个函数的介绍里,没有说会不会导致内存泄漏,同时也没有一个信号来标识音频播放完成。但是如果使用一个局部变量,在变量销毁时,音频就会停止播放,就会导致问题,于是,带着这些问题,我去看了QSound的源码。
首先,关于play这个静态函数的定义:

void QSound::play(const QString &filename)
{
// Object destruction is generally handled via deleteOnComplete
// Unexpected cases will be handled via parenting of QSound objects to qApp
QSound *sound = new QSound(filename, qApp);
sound->connect(sound->m_soundEffect, &QSoundEffect::playingChanged,
sound, &QSound::deleteOnComplete);
sound->play();
}

发现,它连接了一个槽函数,那就是deleteOnComplte

/*!
\internal
*/
void QSound::deleteOnComplete()
{
if (!m_soundEffect->isPlaying())
deleteLater();
}

  在这里,就可以得出一个结论,play这个静态函数可以放心用,他会在播放结束之后,自动释放。
  QSound其实也是在QSoundEffect上封装了一层,播放音频还是用的QSoundEffect,后面,在看了QSoundEffect之后,发现其底层用的是QAudioOutput,关于QAudioOutput和QAudioInput,挖个坑,我在后面的文章里,结合一个局域网实时语音通话的例子,来进行介绍。

QSound、QSoundEffect播放WAV音频的更多相关文章

  1. 用 Qt 的 QAudioOutput 类播放 WAV 音频文件

    用 Qt 的 QAudioOutput 类播放 WAV 音频文件 最近有一个项目,需要同时控制 4 个声卡播放不同的声音,声音文件很简单就是没有任何压缩的 wav 文件. 如果只是播放 wav 文件, ...

  2. 使用WaveOut API播放WAV音频文件(解决卡顿)

    虽然waveout已经过时,但是其api简单,有些时候也还是需要用到. 其实还是自己上msdn查阅相应api最靠谱,waveout也有提供暂停.设置音量等接口的,这里给个链接,需要的可以自己查找: h ...

  3. S3C2416裸机开发系列19_Fatfs播放录像wav音频文件

    S3C2416裸机开发系列19 Fatfs播放录像wav音频文件 国际象棋男孩    1048272975 多媒体资源,一般都是以文件的形式存储在固化存储器中.Fatfs所支持的fat32为windo ...

  4. 多浏览器播放wav格式的音频文件

    html5的audio标签只在火狐下支持wav格式的音频播放,无法兼容IE和google , 使用audioplayer.js 基本上能支持大部分浏览器播放wav音频文件,经测试IE.火狐.googl ...

  5. Windows Phone 8初学者开发—第21部分:永久保存Wav音频文件

    原文 Windows Phone 8初学者开发—第21部分:永久保存Wav音频文件 第21部分:永久保存Wav音频文件 原文地址:http://channel9.msdn.com/Series/Win ...

  6. Windows Phone 8初学者开发—第20部分:录制Wav音频文件

    原文 Windows Phone 8初学者开发—第20部分:录制Wav音频文件 原文地址:http://channel9.msdn.com/Series/Windows-Phone-8-Develop ...

  7. 1.1.6-学习Opencv与MFC混合编程之---播放WAV音乐和 alpha融合功能

    源代码:http://download.csdn.net/detail/nuptboyzhb/3961698 Alpha融合菜单项 1.      增加alpha融合菜单项,修改相应的属性,建立类向导 ...

  8. C语言解析WAV音频文件

    C语言解析WAV音频文件 代码地址: Github : https://github.com/CasterWx/c-wave-master 目录 前言 了解WAV音频文件 什么是二进制文件 WAV的二 ...

  9. C++播放wav音乐和音效

    1.  #include <mmsystem.h>#pragma comment(lib,"winmm.lib")PlaySound(TEXT("c:\\te ...

  10. 8086汇编语言 调用声卡播放wav文件(sound blaster)

    开更 大概最后做了一个能播放无损音乐(无压缩.不需解码)的播放器 原理是基于dosbox的模拟声卡,通过硬件之间的相互通讯做到的 关于详细内容接下来再讲. 一.从dosbox入手 我们知道cpu可以直 ...

随机推荐

  1. Qt/C++推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

    一.前言说明 推流直播就是把采集阶段封包好的内容传输到服务器的过程.其实就是将现场的视频信号从手机端,电脑端,摄影机端打包传到服务器的过程."推流"对网络要求比较高,如果网络不稳定 ...

  2. [转]fatal: remote error: The unauthenticated git protocol on port 9418 is no longer support问题解决

    背景 因为居家办公,把代码从远程clone下来之后,发现使用npm install一直失败. 提示的错误:fatal: remote error: The unauthenticated git pr ...

  3. PS2021、色环插件Coolorus下载+色环无法拖动问题和没有压感问题的解决

    PS2021+色环插件Coolorus+色环无法拖动问题解决+没有压感问题解决 1.资源下载链接 PS各版本下载: 感谢微博@vposy大佬无私奉献提供的各版本ADOBE软件直装破解: 百度网盘: p ...

  4. SpringBoot集成MinIO8.3.x 依赖冲突解决,至简之招覆盖spring-boot-dependencies的依赖版本声明

    版本声明 SpringBoot 2.6.5 MinIO 8.3.7 报错信息 An attempt was made to call a method that does not exist. The ...

  5. Mysql身份认证过程

    背景 最近有一些hersql的用户希望能支持mysql的caching_sha2_password认证方式,caching_sha2_password与常用的mysql_native_password ...

  6. ETL工具--Sqoop

    1. 概述 Sqoop是apache旗下的一款 "Hadoop和关系数据库之间传输数据"的工具导入数据:将MySQL,Oracle导入数据到Hadoop的HDFS.HIVE.HBA ...

  7. MySQL---锁、变量、存储过程、游标、自定义函数

    一概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制. MySQL各存储引擎使用了三种类型 ...

  8. RocketMQ -- offset管理

    正文首先来明确一下 Offset 的含义, RocketMQ 中, 一 种类型的消息会放到 一 个 Topic 里,为了能够并行, 一般一个 Topic 会有多个 Message Queue (也可以 ...

  9. http 协议请求响应模型

    http 协议请求响应模型(一次请求生命周期或简单的软件分层) 场景: 登录 1.客户端发起请求到api接口层 1.1用户在客户端填写用户名和密码,点击登录,发送请求. 2.api接收到客户端发起的用 ...

  10. layui table表格单元格动态合并,并设置隔行变色

    layui table表格单元格动态合并,并设置隔行变色,此代码只针对嵌套数组只有一层的时候有效,多个数组嵌套还在冥想当中!! 需求描述 我们知道在layui插件官方平台有个可以无限极单元格合并的模块 ...