这个例子很有意思,今天分析了下,在此记录下笔记,方便下次查阅。
这个例子展示了画动态数据(麦克风输入的数据)
界面如下:
关键文件如下:
这里官方给出的解释就没了,后面我自己补充下。
首先要学习两个类,分别是:QAudioInput和QAudioFormat
具体可以查本人的这篇博文-Qt文档阅读笔记-QAudioInput&QAudioFormat解析与实例。
首先在main.cpp中的关键代码:
const QAudioDeviceInfo inputDevice = QAudioDeviceInfo::defaultInputDevice();
if (inputDevice.isNull()) {
QMessageBox::warning(nullptr, "audio",
"There is no audio input device available.");
return -1;
}
这里查询了当前系统中是否设置了麦克风,如果没有,就直接退出了。
在Widget.cpp中配置了QAudioFormat相关属性,如下:
QAudioFormat formatAudio;
formatAudio.setSampleRate(8000);
formatAudio.setChannelCount(1);
formatAudio.setSampleSize(8);
formatAudio.setCodec("audio/pcm");
formatAudio.setByteOrder(QAudioFormat::LittleEndian);
formatAudio.setSampleType(QAudioFormat::UnSignedInt);
| 参数 | 描述 |
| Sample Rate | 每秒音频的Hertz |
| Number of channels | 单声道还是双声道 |
| Sample size | 数据按8位存还是16位存 |
| Sample type | 存储的类型是int还是unsigned int还是float |
| Byte order | 存成大端还是小端 |
最后说下最有意思的类XYSeriesIODevice。对应的
xyseriesiodevice.h:
#ifndef XYSERIESIODEVICE_H
#define XYSERIESIODEVICE_H
#include <QtCore/QIODevice>
#include <QtCore/QPointF>
#include <QtCore/QVector>
#include <QtCharts/QChartGlobal>
QT_CHARTS_BEGIN_NAMESPACE
class QXYSeries;
QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class XYSeriesIODevice : public QIODevice
{
Q_OBJECT
public:
explicit XYSeriesIODevice(QXYSeries *series, QObject *parent = nullptr);
static const int sampleCount = 2000;
protected:
qint64 readData(char *data, qint64 maxSize) override;
qint64 writeData(const char *data, qint64 maxSize) override;
private:
QXYSeries *m_series;
QVector<QPointF> m_buffer;
};
#endif // XYSERIESIODEVICE_H
xyseriesiodevice.cpp:
#include "xyseriesiodevice.h"
#include <QtCharts/QXYSeries>
#include <QDebug>
XYSeriesIODevice::XYSeriesIODevice(QXYSeries *series, QObject *parent) :
QIODevice(parent),
m_series(series)
{
}
qint64 XYSeriesIODevice::readData(char *data, qint64 maxSize)
{
Q_UNUSED(data)
Q_UNUSED(maxSize)
return -1;
}
qint64 XYSeriesIODevice::writeData(const char *data, qint64 maxSize)
{
static const int resolution = 4;
if (m_buffer.isEmpty()) {
m_buffer.reserve(sampleCount);
for (int i = 0; i < sampleCount; ++i)
m_buffer.append(QPointF(i, 0));
}
int start = 0;
const int availableSamples = int(maxSize) / resolution;
if (availableSamples < sampleCount) {
start = sampleCount - availableSamples;
for (int s = 0; s < start; ++s)
m_buffer[s].setY(m_buffer.at(s + availableSamples).y());
}
for (int s = start; s < sampleCount; ++s, data += resolution)
m_buffer[s].setY(qreal(uchar(*data) - 128) / qreal(128));
m_series->replace(m_buffer);
return (sampleCount - start) * resolution;
}
这里最关键的代码是这个:
qint64 XYSeriesIODevice::writeData(const char *data, qint64 maxSize)
{
static const int resolution = 4;
if (m_buffer.isEmpty()) {
m_buffer.reserve(sampleCount);
for (int i = 0; i < sampleCount; ++i)
m_buffer.append(QPointF(i, 0));
}
int start = 0;
const int availableSamples = int(maxSize) / resolution;
if (availableSamples < sampleCount) {
start = sampleCount - availableSamples;
for (int s = 0; s < start; ++s)
m_buffer[s].setY(m_buffer.at(s + availableSamples).y());
}
for (int s = start; s < sampleCount; ++s, data += resolution)
m_buffer[s].setY(qreal(uchar(*data) - 128) / qreal(128));
m_series->replace(m_buffer);
return (sampleCount - start) * resolution;
}
整个曲线x轴长度是:
static const int sampleCount = 2000;
y轴长度:
axisY->setRange(-1, 1);
音频大小是:
formatAudio.setSampleType(QAudioFormat::UnSignedInt);
这个函数data每次会传320个字节过来,换成UnsignedInt就是80个UnsignedInt。
下面这一段是对x轴数据都初始化:
if (m_buffer.isEmpty()) {
m_buffer.reserve(sampleCount);
for (int i = 0; i < sampleCount; ++i)
m_buffer.append(QPointF(i, 0));
}
下面是将数据网x轴左方向移动1920个坐标:
if (availableSamples < sampleCount) {
start = sampleCount - availableSamples;
for (int s = 0; s < start; ++s)
m_buffer[s].setY(m_buffer.at(s + availableSamples).y());
}
将刚刚采集的音频放到最后80坐标里面(1920~2000)
for (int s = start; s < sampleCount; ++s, data += resolution)
m_buffer[s].setY(qreal(uchar(*data) - 128) / qreal(128));
这里-128是为了使得y轴有负数,除以128是因为。
axisY->setRange(-1, 1);
Y轴坐标是-1,到1之间。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://it1995.blog.csdn.net/article/details/125943096
内容来源于网络,如有侵权,请联系作者删除!