qt quick(qml)实现8bit和16bit的pcm的音频波形

qt quick(qml)实现8bit和16bit的pcm的音频波形

网上看了一些别人实现音频波形绘制的例子,关于qt qml的较少,16bit pcm的也少,所以写此文章记录一下,代码是基于他人的代码进行修改的,并非完全原创,特此声明。
效果图:
在这里插入图片描述

//DataSource.h

#ifndef DATASOURCE_H
#define DATASOURCE_H

#include <QtCore/QObject>
#include <QtCharts/QAbstractSeries>
#include <QtCharts/QXYSeries>
#include <QtCore/QIODevice>

QT_BEGIN_NAMESPACE
class QQuickView;
QT_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE

class DataSource : public QObject
{
    Q_OBJECT
public:
    explicit DataSource(QObject *parent = 0);
    Q_INVOKABLE void setSeries(QAbstractSeries *series);
public slots:
    void append(const QByteArray &audioData);
protected:
    qint64 readData(char *data, qint64 maxSize);
    qint64 writeData_8bit(const char *data, qint64 maxSize);
    qint64 writeData_16bit(const char *data, qint64 maxSize);

private:
    QXYSeries *m_series;
};


#endif // DATASOURCE_H

//DataSource.cpp

#include "DataSource.h"

#include <QtCharts/QXYSeries>
#include <QtCharts/QAreaSeries>
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
#include <QtCore/QtMath>
#include <QTime>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>


QT_CHARTS_USE_NAMESPACE

Q_DECLARE_METATYPE(QAbstractSeries *)
Q_DECLARE_METATYPE(QAbstractAxis *)


DataSource::DataSource( QObject *parent)
{
    qRegisterMetaType<QAbstractSeries *>();
    qRegisterMetaType<QAbstractAxis *>();
}


qint64 DataSource::readData(char *data, qint64 maxSize)
{
    Q_UNUSED(data)
    Q_UNUSED(maxSize)
    return -1;
}

qint64 DataSource::writeData_8bit(const char *data, qint64 maxSize)
{
    if (m_series)
    {
        qint64 range = 2000;
        QVector<QPointF> oldPoints = m_series->pointsVector();
        QVector<QPointF> points;
        int resolution = 4;//每4个取1个数

        if (oldPoints.count() < range)
        {
            points = m_series->pointsVector();
        }
        else
        {
            for (int i = maxSize / resolution; i < oldPoints.count(); i++)
                points.append(QPointF(i - maxSize / resolution, oldPoints.at(i).y()));
        }

        qint64 size = points.count();
        for (int k = 0; k < maxSize / resolution; k++)
            points.append(QPointF(k + size, ((quint8)data[resolution * k] - 128) / 128.0));

        m_series->replace(points);
    }

    return maxSize;
}

qint64 DataSource::writeData_16bit(const char *srcdata, qint64 len)
{
    int maxSize = len / 2;
    short *data = (short *)srcdata;

    if (m_series)
    {
        qint64 range = 2000;//和界面保持 一致
        QVector<QPointF> oldPoints = m_series->pointsVector();
        QVector<QPointF> points;
        int resolution = 4;//每4个取1个数

        if (oldPoints.count() < range)
        {
            //m_series序列的数据未满2000点,
            points = m_series->pointsVector();
        }
        else
        {
            //将原来maxSize至4000的数据点前移,
            for (int i = maxSize / resolution; i < oldPoints.count(); i++)
                points.append(QPointF(i - maxSize / resolution, oldPoints.at(i).y()));
        }

        qint64 size = points.count();
        for (int k = 0; k < maxSize / resolution; k++) //数据块内的数据填充序列的尾部
        {
//            qDebug("%d\n", (quint8)data[resolution * k]);
            points.append(QPointF(k + size, (data[resolution * k]) / 32768.0));
        }

        m_series->replace(points);//最快的方式
    }

    return maxSize;
}

void DataSource::setSeries(QAbstractSeries *series)
{
    m_series = static_cast<QXYSeries *>(series);
}

void DataSource::append(const QByteArray &audioData)
{
//    writeData_8bit(audioData.data(), audioData.size());
    writeData_16bit(audioData.data(), audioData.size());
}

//main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtCharts 2.3
Item {
    visible: true
    width: 640
    height: 480

    ChartView{
        id:chartView
        animationOptions: chartView.NoAnimation
        theme: chartView.ChartThemeBlueIcy
        property bool openGL: true
        property bool openGLSupported: true
        anchors.fill: parent

        Component.onCompleted: {
            dataSource.setSeries(chartView.series(0));
        }

        Component.onDestruction: {
            dataSource.setSeries(0);
        }

        ValueAxis{
            id:axisY1
            min: -1
            max: 1
        }

        ValueAxis{
            id:axisX
            min: 0
            max: 2000
        }

        LineSeries{
            id: lineSeries
            name: "Audio Sample"
            axisX: axisX
            axisY: axisY1
            useOpenGL: chartView.openGL
        }

    }
}

完整代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值