音频样本与音量对比
本示例演示了麦克风样本与音频等级的绘制。
此示例的实现基于小部件。有关详细信息,请参阅使用 Qt 小部件编程入门。以下部分介绍了如何使用 Qt Charts API 在样本与音量等级图上显示动态数据。有关采样的更多信息,请参阅采样(信号处理)。
运行示例
要从 Qt Creator 中运行示例,请打开“欢迎”模式并从“示例”中选中示例。有关更多信息,请访问构建和运行示例。
获取音频数据
由于在 main.cpp
中包含了 Qt Multimedia 模块,我们创建了一个新的 QAudioDevice 来表示目标平台的默认音频设备。我们还检查是否有音频输入设备,并通知用户如果没有可用的输入音频设备。
if (inputDevice.isNull()) { QMessageBox::warning(nullptr, "audio", "There is no audio input device available."); return -1; }
然后,使用其构造函数参数 w
将音频设备传递给 Widget w
。然后调用 w.show()
来显示小部件。
Widget w(inputDevice); w.resize(800, 600); w.show();
设置图表
本部分介绍设置图表和坐标轴。
在 widget.cpp
中,重实现的 Widget 构造函数在处理应用程序逻辑时做大量工作。以下是对 QChart、QLineSeries 和 QChartView 对象的声明
: QWidget(parent) , m_chart(new QChart) , m_series(new QLineSeries) { auto chartView = new QChartView(m_chart); m_chart->addSeries(m_series);
m_series 用于 使用音频输入数据。
“样本”坐标轴
我们将 x 轴的最小值和最大值范围设置为 0 到 XYSeriesIODevice::sampleCount(在 xyseriesiodevice.h 中声明为 2000)。然后我们设置了其标题文本。
auto axisX = new QValueAxis; axisX->setRange(0, XYSeriesIODevice::sampleCount); axisX->setLabelFormat("%g"); axisX->setTitleText("Samples");
“音频等级”坐标轴
我们创建了 QValueAxis axisY
,设置了其范围和标题文本。
auto axisY = new QValueAxis; axisY->setRange(-1, 1); axisY->setTitleText("Audio level");
连接坐标轴并设置图表标题
我们将坐标轴连接起来,隐藏了图例,并将图表标题设置为包含使用的麦克风的名称。
m_chart->addAxis(axisX, Qt::AlignBottom); m_series->attachAxis(axisX); m_chart->addAxis(axisY, Qt::AlignLeft); m_series->attachAxis(axisY); m_chart->legend()->hide();
布局图表
在这里,我们使用了一个 QVBoxLayout mainLayout
并将我们的 QChartview chartView
添加到垂直布局中。
m_chart->setTitle("Data from the microphone (" + deviceInfo.description() + ')'); auto mainLayout = new QVBoxLayout(this);
使用音频输入数据
本节展示了麦克风数据如何传递到 QLineSeries m_series
。与之前一样,这依赖于 Qt 多媒体模块。
首先,我们将 deviceInfo 传递给 QAudioInput 构造函数。
mainLayout->addWidget(chartView); m_audioInput = new QAudioInput(deviceInfo, this); QAudioFormat formatAudio;
然后,我们设置我们的 QAudioFormat formatAudio
,其通道数、采样率和采样格式。
formatAudio.setSampleRate(8000); formatAudio.setChannelCount(1);
现在我们可以创建一个 QAudioSource 并设置其缓冲区大小。
formatAudio.setSampleFormat(QAudioFormat::UInt8); m_audioSource = new QAudioSource(deviceInfo, formatAudio);
现在是时候将我们的数据附加到图表上了。为此,我们创建了一个名为 XYSeriesIODevice 的类。有关其实现方式,请参阅 XYSeriesIODevice。
m_audioSource->setBufferSize(200); m_device = new XYSeriesIODevice(m_series, this); m_device->open(QIODevice::WriteOnly);
XYSeriesIODevice
在 xyseriesiodevice.cpp
中实现,XYSeriesIODevice 负责信号采样。具有固定分辨率的 4 的 writeData
函数,根据样本数设置 QList m_buffer
的大小,并用 x 值递增和 y 值设置为 0 的 QPointFs 填充它。
{ 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;
© 2024 The Qt Company Ltd。此处包含的文档贡献归其各自所有者所有。此处提供的文档是根据自由软件基金会发布的 GNU 自由文档许可证版本 1.3 的条款许可的。Qt 及其相关标志是芬兰和/或其他国家的 The Qt Company Ltd. 的商标。所有其他商标均为其各自所有者的财产。