オーディオサンプルとサウンドレベル

この例では、マイクサンプルとオーディオレベルの描画を示します。

この例の実装はウィジェットに基づいています。Qt Widgets を使ったプログラミング入門を参照してください。以下の章では、Qt Charts API を使ってサンプル対サウンドレベルのグラフにダイナミックデータを表示する方法を説明します。サンプリングの詳細については、Sampling_(signal_processing) を参照してください。

サンプルを実行する

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

オーディオデータの取得

Qt Multimedia モジュールがmain.cpp に含まれているので、ターゲット・プラットフォームのデフォルトのオーディオ・ デバイスを表す新しいQAudioDevice を作成します。また、オーディオ入力デバイスがあるかどうかをチェックし、利用可能な入力オーディオデバイスがない場合はユーザーに知らせます。

    if (inputDevice.isNull()) {
        QMessageBox::warning(nullptr, "audio",
                             "There is no audio input device available.");
        return -1;
    }

オーディオデバイスは、コンストラクタの引数w を使ってウィジェット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軸の "サンプル"

x 軸の最小値から最大値までの範囲を 0 から XYSeriesIODevice::sampleCount に設定します。(xyseriesiodevice.hでは2000として宣言されている)。次にタイトルテキストを設定します。

    auto axisX = new QValueAxis;
    axisX->setRange(0, XYSeriesIODevice::sampleCount);
    axisX->setLabelFormat("%g");
    axisX->setTitleText("Samples");
Y軸の "Audio Level"

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 を使い、QChartviewchartView を垂直レイアウトに追加します。

    m_chart->setTitle("Data from the microphone (" + deviceInfo.description() + ')');

    auto mainLayout = new QVBoxLayout(this);

音声入力データの使用

このセクションでは、マイクのデータをQLineSeries m_series に渡す方法を示します。前回と同様に、これは Qt Multimedia モジュールに依存しています。

まず、QAudioInput コンストラクタに deviceInfo を渡します。

    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 が信号のサンプリングを行います。writeData 関数は、分解能を 4 に固定し、サンプルカウントに基づいてQList m_buffer のサイズを設定し、x 値の増分と y 値を 0 に設定した QPointF で埋めます。

{
    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. 本文書に含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。