采用FMOD引擎实现音频波形图

采用FMOD引擎实现音频波形图

因为做老师留的大作业时要做音频波形图接触了FMOD引擎,感觉FMOD功能真的是强大,不过大部分较新的学习资源都是外国的,对英语不好的新手来说也有些困难。我在此分享一下自己的学习成果,希望对大家有写帮助和启发。这也是本人第一次写博客,写得不好请见谅。

  1. 什么是FMOD?
    在使用它之前让我们了解一下什么是FMOD
    百度百科上说的很简单,FMOD是为游戏开发者准备的革命性音频引擎。到底有多厉害呢?百度百科并没有详细说明,你可以进入他们的官网,查看game一栏,如果你是一名单机游戏玩家的话,相信会认出不少3A大作。它的功能有多强大,相信看到这些不用我多说了吧。
  2. FMOD的引擎的下载
    FMOD是免费的,你可以在FMOD的网站上进行下载
    在下载之前你要先注册他们的账户,注册完账户点击下载,他们会给你邮箱发送一封邮件,点击邮件中的链接便可以进行下载。
    FMOD是跨平台的,你可以选择你需要的版本。
  3. 连接FOMD外部库
    下载下来后你只需要将lowlevel下的inc文件夹的头文件和lib文件夹下的外部库导入进项目即可,其他的内容本实验用不到。
    另外说一下本实验我是在linux下用QT来实现的,如果是在windows下使用的可能会有些问题。
  4. 运行效果
    在这里插入图片描述
  5. 主要代码
    MainWindow:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QString>
#include <QFileDialog>
#include <QTimer>
#include "fmod.hpp"
#include "fmod_dsp.h"
#include "fmod_errors.h"
#include "fmod_dsp_effects.h"
#include "curveplot.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    FMOD::System* mSystem=NULL;
    FMOD::Channel* mChannel;
    FMOD::DSP* mDsp;
    FMOD::Sound* mSound;
    FMOD_RESULT mResult;
    FMOD::ChannelGroup *mChannelGroup;
    FMOD_DSP_PARAMETER_FFT *fftparameter;
    QTimer timer;
private slots:
    void onTimer();

    void on_toolButton_clicked();

    void on_toolButton_2_clicked();

    void on_horizontalSlider_sliderMoved(int position);

private:
    Ui::MainWindow *ui;
    CurvePlot *_curvePlot=nullptr;
    QVector<float>wav;
};

#endif // MAINWINDOW_H

//构造函数:
 ui->setupUi(this);
    wav.resize(2048);
    mResult=FMOD::System_Create(&mSystem);
    connect(&timer, SIGNAL(timeout()), SLOT(onTimer()));
    if(mResult!=FMOD_OK)
    {
        qDebug()<<"error:System_Create";
        exit(-1);
    }
    mResult=mSystem->init(32,FMOD_INIT_NORMAL,0);
    if(mResult!=FMOD_OK)
    {
        qDebug()<<"error:System->init";
        exit(-1);
    }
    ui->toolButton->setIcon(QPixmap(":/images/play.png"));
    ui->toolButton_2->setIcon(QPixmap(":/images/file.png"));
    _curvePlot=new CurvePlot(this);
    ui->content->addWidget(_curvePlot);
    _curvePlot->setAdjustVal(0.5);
    _curvePlot->outPut();

//打开文件按钮
 QString filename = QFileDialog::getOpenFileName();
    mResult=mSystem->createSound(filename.toLocal8Bit(),FMOD_LOOP_NORMAL|FMOD_2D,0,&mSound);
    if(mResult!=FMOD_OK)
    {
        qDebug()<<"error:System->createSound";
        exit(-1);
    }
    mResult=mSystem->playSound(mSound,0,false,&mChannel);
    if(mResult!=FMOD_OK)
    {
        qDebug()<<"error:System->playSound";
        exit(-1);
    }
    ui->toolButton->setIcon(QPixmap(":/images/pause.png"));
    mSound->setMode(FMOD_LOOP_OFF);

    mResult=mSystem->createDSPByType(FMOD_DSP_TYPE_FFT,&mDsp);
    mResult=mChannel->addDSP(0,mDsp);

    uint length;
    mSound->getLength(&length,FMOD_TIMEUNIT_MS);
    ui->horizontalSlider->setMaximum(length);
    length/=1000;
    ui->label->setText(QString().sprintf("%02d:%02d ", length/60, length%60));
    mSystem->update();
    timer.start(400);
    
//实时刷新void onTimer()
mDsp->getParameterData(FMOD_DSP_FFT_SPECTRUMDATA,(void **)&fftparameter,0,0,0);
        for(int j=0;j<fftparameter->length;j++)
        {
        	//一倍不太明显,将其放大十倍
            wav[j]=fftparameter->spectrum[0][j]*10;
        }
        _curvePlot->outPut(wav);
    uint pos;
    mChannel->getPosition(&pos,FMOD_TIMEUNIT_MS);
    ui->horizontalSlider->setValue(pos);
    pos/=1000;
    ui->label_2->setText(QString().sprintf(" %02d:%02d", pos/60, pos%60));
    bool isPlay;
    mChannel->isPlaying(&isPlay);
    if(!isPlay)
        timer.stop();

绘制图形部分:

#ifndef CURVEPLOT_H
#define CURVEPLOT_H
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
//边缘
class QMargin
{
public:
    QMargin(int left,int top,int right,int bottom):
        Left(left),Top(top),Right(right),Bottom(bottom){}
    QMargin(int h,int v):
        Left(h),Top(v),Right(h),Bottom(v){}
    QMargin(int d=0):
        Left(d),Top(d),Right(d),Bottom(d){}

    int Left;
    int Top;
    int Right;
    int Bottom;
};
//波形图
class CurvePlot : public QWidget
{
    Q_OBJECT
public:
    explicit CurvePlot(QWidget *parent=0);
    void outPut();
    void outPut(QVector<float> &data);
    void setAdjustVal(float val){iAdjustVal = val;}
    QSize minimumSizeHint() const;

    QMargin Margin;
    QPen pen;
    QBrush Background;

protected:
    void paintEvent(QPaintEvent *paint);
    void resizeEvent(QResizeEvent *);

private:
    void transformPoints(QVector<float> &data, int w, int h, QVector<QPointF> &points);
    QPixmap pixmap;
    float iAdjustVal;
};
#endif // CURVEPLOT_H

    //构造函数
    Margin = QMargin(2);
    Background = QBrush(QColor(Qt::black));
    pen = QPen(QBrush(QColor(Qt::red)), 3);
    iAdjustVal = 0;
    
  //坐标转换
  //void transformPoints(QVector<float> &data, int w, int h, QVector<QPointF> &points)
    //获取极值
    float max=data[0],min=data[0];
    for(int i=1;i<data.size();i++)
    {
        if(max<data[i])
            max=data[i];
        if(min>data[i])
            min=data[i];
    }
    //转化成当前屏幕的内的坐标大小
    max+=iAdjustVal;
    min-=iAdjustVal;
    float diffVal=max-min;
    for(int i=0;i<data.size();i++)
        points.append(QPointF(i*w/data.size(),h-(data[i]-min)/diffVal*h));

//void paintEvent()
QPainter painter(this);
    int w=width()-Margin.Left-Margin.Right;
    int h=height()-Margin.Top-Margin.Bottom;
    painter.drawPixmap(Margin.Left,Margin.Top,w,h,pixmap);

//void outPut()
int w = width() - Margin.Left - Margin.Right;
    int h = height() - Margin.Top - Margin.Bottom;

    pixmap=QPixmap(":/images/timg.jpg");
    pixmap.scaled(w,h);
    QPainter painter(&pixmap);

    painter.setPen(pen);
    painter.drawLine(QPoint(Margin.Left,height()/2),QPoint(Margin.Left+w,height()/2));
    update();

//void minimumSizeHint()
return QSize(Margin.Left+Margin.Right+40,Margin.Top+Margin.Bottom+40);

//void outPut(QVector<float> &data)
int w = width() - Margin.Left - Margin.Right;
    int h = height() - Margin.Top - Margin.Bottom;

    pixmap = QPixmap(":/images/timg.jpg");
    pixmap.scaled(w,h);
    QPainter painter(&pixmap);
    painter.setRenderHints(QPainter::SmoothPixmapTransform);
    //painter.fillRect(QRectF(0, 0, w, h), Background);

    QVector<QPointF> points;
    transformPoints(data, w, h+this->height()*0.3, points);
    painter.setPen(pen);
    for (int i= 0; i< points.size()-1; i++)
        painter.drawLine(points[i], points[i+1]);
    update();

源码下载链接:https://download.csdn.net/download/qq_36166213/10823109

  • 2
    点赞
  • 2
    评论
  • 9
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值