QT多媒体编程(一)——音频编程知识详解及MP3音频播放器Demo

目录

引言

一、QtMultimedia模块简介

主要类和功能

二、QtMultimedia相关类及函数解析

QAudioInput

QAudioOutput

QAudioFormat

QMediaPlayer

QMediaPlaylist

QCamera

三、音频项目实战Demo

UI界面

核心代码

运行结果

四、结论


引言

在数字时代,音频处理成为多媒体应用、实时通信和娱乐产业中不可或缺的一部分。Qt作为一种跨平台的C++应用程序开发框架,提供了强大的多媒体处理能力,特别是其QtMultimedia模块,为开发者提供了丰富的API来处理音频和视频。本文将详细介绍QT音频基础知识,特别是QtMultimedia模块的使用及相关函数解析。

一、QtMultimedia模块简介

QtMultimedia模块是Qt库中的一个重要模块,专门用于处理多媒体内容,如音频和视频。它提供了一组丰富的QML类型和C++类,支持音频和视频的采集、播放、录制和处理。QtMultimedia模块不仅支持基本的音频和视频播放,还提供了编解码、格式转换等高级功能。

cpp 复制代码
// 在.pro文件中加入模块

QT += multimedia

主要类和功能

  • QAudioInput:用于音频数据的采集。开发者可以通过这个类从麦克风等音频输入设备获取原始音频数据。
  • QAudioOutput:用于音频数据的播放。它允许开发者将音频数据输出到扬声器等音频输出设备。
  • QAudioFormat:用于定义音频数据的格式,包括采样率、样本大小、声道数等关键参数。
  • QMediaPlayer:提供音频和视频文件的播放功能,支持多种媒体格式,如MP3、WAV、AVI、MP4等。
  • QMediaPlaylist:允许开发者创建、编辑和播放一个包含多个媒体文件(如音频或视频)的列表。可以轻松地实现连续播放、随机播放或单曲循环等。
  • QCamera:虽然主要用于视频处理,但也涉及音频采集,特别是与视频同步的音频数据。

二、QtMultimedia相关类及函数解析

QAudioInput

功能

QAudioInput类用于音频数据的采集。它提供了一个接口,允许开发者从音频输入设备(如麦克风)获取原始音频数据。

主要方法和属性

  • start():开始音频数据的采集。
  • stop():停止音频数据的采集。
  • bytesReady():返回缓冲区中可读的字节数。
  • read():从缓冲区读取音频数据。
  • notify():设置当有新数据可读时发出的通知。

QAudioOutput

功能

QAudioOutput类用于音频数据的播放。它允许开发者将音频数据输出到音频输出设备(如扬声器)。

主要方法和属性

  • start():开始音频数据的播放。
  • stop():停止音频数据的播放。
  • write():将音频数据写入播放缓冲区。
  • bytesFree():返回播放缓冲区中可用的字节数。
  • periodSize():返回播放缓冲区的周期大小。

QAudioFormat

功能

QAudioFormat类用于定义音频数据的格式。它包含了采样率、样本大小、声道数等关键参数,用于描述音频数据的属性。

主要方法和属性

  • setSampleRate():设置采样率。
  • setChannelCount():设置通道数。
  • setSampleSize():设置样本大小。
  • setCodec():设置音频编码器。
  • setByteOrder():设置字节序。
  • setSampleType():设置样本类型(如有符号整数、无符号整数、浮点数等)。

QMediaPlayer

功能

QMediaPlayer类提供音频和视频文件的播放功能。它支持多种媒体格式,如MP3、WAV、AVI、MP4等,并提供了丰富的API来控制媒体的播放。

主要方法和属性

  • setMedia():设置要播放的媒体文件或媒体内容。
  • play():开始播放媒体。
  • pause():暂停播放媒体。
  • stop():停止播放媒体。
  • volume():获取或设置播放音量。
  • position():获取当前播放位置。
  • duration():获取媒体的总时长。

QMediaPlaylist

功能
QMediaPlaylist类提供了一个管理媒体播放列表的接口。它允许开发者创建、编辑和播放一个包含多个媒体文件(如音频或视频)的列表。通过QMediaPlaylist,可以轻松地实现连续播放、随机播放或单曲循环等功能。

主要方法和属性

  • addMedia(const QMediaContent &content):向播放列表中添加一个媒体文件。QMediaContent是一个包含媒体文件位置(如URL或文件路径)和其他相关信息的类。

  • insertMedia(int index, const QMediaContent &content):在播放列表的指定位置插入一个媒体文件。

  • removeMedia(int index):从播放列表中移除指定位置的媒体文件。

  • moveMedia(int from, int to):在播放列表中移动媒体文件的位置。

  • clear():清空播放列表中的所有媒体文件。

  • setCurrentIndex(int index):设置当前播放的媒体文件在播放列表中的索引。

  • currentIndex():获取当前播放的媒体文件在播放列表中的索引。

  • playbackMode():获取播放列表的播放模式,如顺序播放、随机播放或单曲循环。

  • setPlaybackMode(QMediaPlaylist::PlaybackMode mode):设置播放列表的播放模式。

  • mediaCount():获取播放列表中的媒体文件数量。

  • media(int index):获取播放列表中指定位置的媒体文件信息。

  • next():播放下一个媒体文件。

  • previous():播放上一个媒体文件。

QCamera

功能

QCamera类主要用于视频处理,但也涉及音频采集,特别是与视频同步的音频数据。它提供了访问和控制相机设备的接口。

主要方法和属性(与音频相关):

  • start():开始相机的预览或捕获会话,这可能包括音频采集。
  • stop():停止相机的预览或捕获会话。
  • audioRecorder():获取与相机关联的音频录制器对象,用于控制音频的录制。
  • setAudioEncoderSettings():设置音频编码器的参数。

三、音频项目实战Demo

UI界面

核心代码

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QFileDialog>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    QMediaPlayer *player;
    QMediaPlaylist *playlist;

    QString drtTime;    // 播放时长
    QString pstTime;    // 播放位置

private slots:
    void onstatechanged(QMediaPlayer::State state); // 按钮切换状态
    void onplaylistchanged(int pos);    // 播放列表
    void ondrtchanged(qint64 drt);  // 歌曲总时长
    void onpstchanged(qint64 pos);  // 播放歌曲当前位置

    void on_pushButton_open_clicked();
    void on_pushButton_play_clicked();
    void on_pushButton_pause_clicked();
    void on_pushButton_stop_clicked();
    void on_pushButton_pre_clicked();
    void on_pushButton_next_clicked();
    void on_pushButton_volumn_clicked();
    void on_horizontalSlider_volumn_valueChanged(int value);
    void on_horizontalSlider_speed_valueChanged(int value);
};
#endif // MAINWINDOW_H
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    player = new QMediaPlayer(this);
    playlist = new QMediaPlaylist(this);
    playlist->setPlaybackMode(QMediaPlaylist::Loop);    // 循环播放
    player->setPlaylist(playlist);
    connect(player, SIGNAL(stateChanged(QMediaPlayer::State)),this,SLOT(onstatechanged(QMediaPlayer::State)));

    connect(player, SIGNAL(positionChanged(qint64)),this,SLOT(onpstchanged(qint64)));

    connect(player, SIGNAL(durationChanged(qint64)),this,SLOT(ondrtchanged(qint64)));

    connect(playlist,SIGNAL(currentIndexChanged(int)),this,SLOT(onplaylistchanged(int)));

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::onstatechanged(QMediaPlayer::State state) // 按钮切换状态
{
    ui->pushButton_play->setEnabled(!(state==QMediaPlayer::PlayingState));
    ui->pushButton_pause->setEnabled(state==QMediaPlayer::PlayingState);
    ui->pushButton_stop->setEnabled(state==QMediaPlayer::PlayingState);
}

void MainWindow::onplaylistchanged(int pos)    // 播放列表
{
    ui->listWidget->setCurrentRow(pos);
    QListWidgetItem *item = ui->listWidget->currentItem();
    if(item)
    {
        ui->label_name->setText(item->text());
    }
}

void MainWindow::ondrtchanged(qint64 drt)  // 歌曲总时长、更新变化
{
    ui->horizontalSlider_speed->setMaximum(drt);
    int sec = drt/1000; //总秒
    int min = sec/60;   //分
    sec = sec%60;   //余秒

    drtTime = QString::asprintf("%02d:%02d",min,sec);
    ui->label_time->setText(drtTime);
}

void MainWindow::onpstchanged(qint64 pos)  // 播放歌曲当前位置
{
    if(ui->horizontalSlider_speed->isSliderDown())
        return;
    ui->horizontalSlider_speed->setSliderPosition(pos);
    int sec = pos/1000; //总秒
    int min = sec/60;   //分
    sec = sec%60;   //余秒

    pstTime = QString::asprintf("%02d:%02d",min,sec);
    ui->label_speed->setText(pstTime);
}

void MainWindow::on_pushButton_open_clicked()
{
    // 添加歌曲文件
    QString currentpath = QDir::currentPath();
    QString dlgtitle = "请选择音频文件";
    QString strfilter = "所有文件(*.*);;音频文件(*.mp3 *.wav);;mp3文件(*.mp3);;wav文件(*.wav)";

    QStringList filelist = QFileDialog::getOpenFileNames(this,dlgtitle,currentpath,strfilter);

    if(filelist.count() < 1)
        return;

    for (int i = 0; i < filelist.count(); ++i) {
        QString afile = filelist.at(i);
        playlist->addMedia(QUrl::fromLocalFile(afile)); // 添加文件
        QFileInfo fileinfo(afile);  // 获取文件信息
        ui->listWidget->addItem("正在播放:"+fileinfo.fileName()); // 将文件名称添加到listwidget控件上
        if(player->state() != QMediaPlayer::PlayingState)
            playlist->setCurrentIndex(0);   // 默认添加进来第一首播放
        player->play();
    }
}

void MainWindow::on_pushButton_play_clicked()
{
    if(playlist->currentIndex() < 0)    // 没选择歌曲默认播放第一首歌
        playlist->setCurrentIndex(0);
    player->play();
}

void MainWindow::on_pushButton_pause_clicked()
{
    player->pause();
}

void MainWindow::on_pushButton_stop_clicked()
{
    player->stop();
}

void MainWindow::on_pushButton_pre_clicked()
{
    playlist->previous();
}

void MainWindow::on_pushButton_next_clicked()
{
    playlist->next();
}

void MainWindow::on_pushButton_volumn_clicked()
{
    // 控制静音状态
    bool mutex = player->isMuted();
    player->setMuted(!mutex);
    if(mutex)
    {
        ui->pushButton_volumn->setIcon(QIcon(":/images/1.PNG"));
    }
    else
        ui->pushButton_volumn->setIcon(QIcon(":/images/2.PNG"));
}

void MainWindow::on_horizontalSlider_volumn_valueChanged(int value)
{
    player->setVolume(value);
}

void MainWindow::on_horizontalSlider_speed_valueChanged(int value)
{
    player->setPosition(value);
}

运行结果

经过测试后,按钮暂停,停止,上一曲,下一曲和静音,音量和进度条等功能都可以实现。

四、结论

QtMultimedia模块为开发者提供了强大的音频处理能力,通过QAudioInput、QAudioOutput等类,可以轻松实现音频的采集、播放和处理。了解音频处理的基础概念和QtMultimedia模块的使用,对于开发多媒体应用程序至关重要。希望本文能为开发者们提供一些有用的参考和帮助。

传送门:QT多媒体编程(二)------视频编程知识详解及mp4视频播放器Demo

相关推荐
WangYaolove13146 分钟前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python
我是黄大仙27 分钟前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书
曾经的三心草27 分钟前
Mysql之约束与事件
android·数据库·mysql·事件·约束
WuMingf_34 分钟前
redis
数据库·redis
张某布响丸辣42 分钟前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
tumu_C1 小时前
C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型
c++·开源
杜若南星1 小时前
保研考研机试攻略(满分篇):第二章——满分之路上(1)
数据结构·c++·经验分享·笔记·考研·算法·贪心算法
Neophyte06081 小时前
C++算法练习-day40——617.合并二叉树
开发语言·c++·算法
云空2 小时前
《InsCode AI IDE:编程新时代的引领者》
java·javascript·c++·ide·人工智能·python·php