基于libzplay 实现window下音乐频谱动态显示

在做多媒体开发中我们经常需要做pcm(频谱)显示,这个例子专门使用libzplay库实现音频频谱动态显示,附加波动动画。看一下频谱的效果!


实现步骤:
首先我们需要去libzplay下载这个库,因为我使用了它来采集音频频谱数据。
然后配置pro文件

配置好了就开始写功能实现部分,直接上代码吧!

我写了一个专门读取音频数据的类:

AudioData.h

#ifndef AUDIODATA_H
#define AUDIODATA_H

#include 
//#include 
//#include 
#include 
//#include 
#include 
#include "libzplay.h"
#include 

#include 
#include 
#include 
using namespace libZPlay;

class AudioData : public QObject
{
    Q_OBJECT
public:
    explicit AudioData(QObject *parent = 0);

    Q_INVOKABLE void setSource(QString source);
    Q_INVOKABLE void playMusic();
    Q_INVOKABLE void stopMusic();
    Q_INVOKABLE void pauseMusic();
    Q_INVOKABLE void seekPosition(int ms);
    Q_PROPERTY(int amplitude READ amplitude NOTIFY amplitudeChanged)
    Q_PROPERTY(int position READ position NOTIFY positionChanged)
    Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged)

    //music pcm data
    Q_PROPERTY(QString pcmData READ pcmData NOTIFY pcmDataChanged)

    QString pcmData(){
        QJsonObject root;
        QJsonArray hn;
        for(int i =0;i<257;i++){
            hn.append (pnLeftAmplitude[i]);
        }
        root.insert ("data",hn);
        QJsonDocument doc;
        doc.setObject (root);
        return doc.toJson ();
    }

signals:
    void amplitudeChanged();
    void positionChanged();
    void isPlayingChanged();
    void pcmDataChanged();

public slots:
    void refreshDatas();
private:
    ZPlay *player;
    QTimer timer;
    int  pnHarmonicNumber[512];
    int  pnHarmonicFreq[257];
    int  pnLeftAmplitude[257];
    int  pnRightAmplitude[257];
    int  pnLeftPhase[257];
    int  pnRightPhase[257];
    int mposition=0;
    bool isMusicPlaying;

    int amplitude(){
        return pnRightAmplitude[171];
    }

    int position(){
        return mposition;
    }

    bool isPlaying(){
        return isMusicPlaying;
    }
};
#endif // AUDIODATA_H

AudioData.cpp

#include "audiodata.h"

#include 
#include 
#include 
#include 

AudioData::AudioData(QObject *parent) : QObject(parent)
{
    player=CreateZPlay();

    // set graph type to AREA, left channel on top
    player->SetFFTGraphParam(gpGraphType, gtAreaLeftOnTop);

    // set linear scale
    player->SetFFTGraphParam(gpHorizontalScale, gsLinear);

    timer.setInterval(1);

    connect(&timer,SIGNAL(timeout()),this,SLOT(refreshDatas()));

}
//music source
void AudioData::setSource(QString source){
    const char* msource=source.toLatin1().data();


    // open file
    int result = player->OpenFile(msource, sfAutodetect);
    if(result == 0)
    {
        // display error message
        qDebug()<<"file open failed"<GetError()<Play();
    timer.start();
    isMusicPlaying=true;
    isPlayingChanged();
}
/**
 * @brief AudioData::stopMusic
 */
void AudioData::stopMusic(){
    player->Stop();
    timer.stop();
    isMusicPlaying=false;
    isPlayingChanged();
}
/**
 * @brief AudioData::pauseMusic
 */
void AudioData::pauseMusic(){
    player->Pause();
    timer.stop();
    isMusicPlaying=false;
    isPlayingChanged();
}
/**
 * @brief AudioData::refreshDatas
 */
void AudioData::refreshDatas(){

    // get song length
    TStreamInfo info;
    player->GetStreamInfo(&info);

    // check key press
    if(kbhit())
    {
        int a = getch();
        if(a == 'p' || a == 'P')
            player->Pause();
        else if(a=='q'||a=='Q'){
            player->Stop();
        }
    }

    // get stream status to check if song is still playing
    TStreamStatus status;
    player->GetStatus(&status);
    if(status.fPlay == 0)
        return;

    // get current position
    TStreamTime pos;
    player->GetPosition(&pos);
    this->mposition=pos.ms;
    positionChanged();
    int FFTPoints = player->GetFFTGraphParam(gpFFTPoints);
    player->GetFFTData(FFTPoints,fwTriangular,
                       pnHarmonicNumber,
                       pnHarmonicFreq,
                       pnLeftAmplitude,
                       pnRightAmplitude,
                       pnLeftPhase,
                       pnRightPhase);
    amplitudeChanged();
    pcmDataChanged();
    // draw FFT graph on desktop window

//    player->DrawFFTGraphOnHWND(0, 0, 0, 300, 200);

//    qDebug()<Seek(tfMillisecond,&time,smFromBeginning);
}

main.cpp

#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    AudioData ad;
    engine.rootContext()->setContextProperty("AudioData",&ad);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    property url soundUrl;
//    property var pcmDataM:new Array();
    property var pcmDatastr:AudioData.pcmData

    ListModel{
        id:dataModel
    }

    onPcmDatastrChanged: {
        try{
            if(dataModel.count===0)
                return;
            var jdata=JSON.parse(pcmDatastr).data;
            for(var a=0;a

你可能感兴趣的:(qml,qt,c++)