音频样本与音量对比

本示例演示了麦克风样本与音频等级的绘制。

此示例的实现基于小部件。有关详细信息,请参阅使用 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 构造函数在处理应用程序逻辑时做大量工作。以下是对 QChartQLineSeriesQChartView 对象的声明

    : 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;

示例项目 @ code.qt.io

© 2024 The Qt Company Ltd。此处包含的文档贡献归其各自所有者所有。此处提供的文档是根据自由软件基金会发布的 GNU 自由文档许可证版本 1.3 的条款许可的。Qt 及其相关标志是芬兰和/或其他国家的 The Qt Company Ltd. 的商标。所有其他商标均为其各自所有者的财产。