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. intellij idea 自动生成test单元测试

    1. 创建测试类 打开IDEA,在任意类名,任意接口名上,按ctrl+shift+t选择Create New Test   image 然后根据提示操作(默认即可),点击确认,就在项目的/test/j ...

  2. Qt编写跨平台视频监控系统(64通道占用7%CPU/支持win_linux_mac等)

    一.前言 视频监控组件经历过数十年的迭代,从最初的只简单播放个rtsp视频流,到现在支持各种音频视频文件格式(mp3.wav.mp4.asf.rm.rmvb.mkv等).支持各种视频流格式(rtp.r ...

  3. Qt编写地图综合应用9-行政区划

    一.前言 行政区划在地图应用中非常有用,行政区划是行政区域划分的简称,是国家为了进行分级管理而实行的区域划分,百度地图提供的内置的函数类支持传入行政区划的名称来获取对应的边界点集合,然后根据该集合来绘 ...

  4. [转]gcc的-g,-o,-c,-D,-w,-W,-Wall,-O3等参数的意义

    一.-g -g可执行程序包含调试信息-g为了调试用的加个-g 是为了gdb 用,不然gdb用不到 二.-o -o指定输出文件名-o output_filename,确定输出文件的名称为output_f ...

  5. C#中工作线程处理完数据后将处理结果返回给UI主线程通知主线程操作界面

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. 阿里IM技术分享(九):深度揭密RocketMQ在钉钉IM系统中的应用实践

    本文由钉钉技术专家尹启绣分享,有修订和重新排版. 1.引言 短短的几年时间,钉钉便迅速成为一款国民级应用,发展速度堪称迅猛. IM作为钉钉最核心的功能,每天需要支持海量企业用户的沟通,同时还通过 Pa ...

  7. macos(m1)编译测试深度学习推理框架

    mnn build tnn

  8. [Git][基本原理与命令]

    引言 Git是工作中最常用的版本控制工具,本文中将介绍其常用的命令. 根据作用的不同,可以分为基本命令.撤销命令.合并命令与远程仓库命令,下面将依次介绍这些命令. 基本原理 git 中提供了底层api ...

  9. ls小技巧

    一.ls -rt ls的功能是列出指定路径下的所有文件,但是有时候文件太多,不方便查找哪些是新生成的文件时,可以使用ls -t或ls -rt命令. ls -t ls -rt 那是什么意思呢?这里-t就 ...

  10. BotSharp:又一个.Net重磅AI开源项目,.Net在AI领域开始崛起!

    大家好,我是编程乐趣. 自从大模型爆火以来,.Net不管是官方.还是社区开源项目,都陆续推出很多重磅的项目. 在AI领域,对话即平台(CaaP)是未来的发展方向. 下面介绍一个开源项目,面向AI Bo ...