diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-02-13 09:59:52 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-02-13 10:09:17 +0200 |
commit | 88cd10aa7b3559b092cf5575b0a17d002dc100ae (patch) | |
tree | 9d6e7efdec49419558bb4ef4a9bc02ae3cb1cfc4 /examples/datavisualization/audiolevels | |
parent | ecabd51692b476567dc42a745f51996ec665b385 (diff) |
Fix examples installation
Had to add one folder to the examples structure so
installation works correctly.
Change-Id: Ic92dfe9997413a6243abcf5eeba12744ba9e938c
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'examples/datavisualization/audiolevels')
-rw-r--r-- | examples/datavisualization/audiolevels/audiolevels.cpp | 89 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/audiolevels.h | 45 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/audiolevels.pro | 14 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/audiolevelsiodevice.cpp | 103 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/audiolevelsiodevice.h | 44 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/doc/images/audiolevels-example.png | bin | 0 -> 120978 bytes | |||
-rw-r--r-- | examples/datavisualization/audiolevels/doc/src/audiolevels.qdoc | 85 | ||||
-rw-r--r-- | examples/datavisualization/audiolevels/main.cpp | 39 |
8 files changed, 419 insertions, 0 deletions
diff --git a/examples/datavisualization/audiolevels/audiolevels.cpp b/examples/datavisualization/audiolevels/audiolevels.cpp new file mode 100644 index 00000000..18c1342a --- /dev/null +++ b/examples/datavisualization/audiolevels/audiolevels.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "audiolevelsiodevice.h" +#include "audiolevels.h" + +#include <QtDataVisualization/qbardataproxy.h> +#include <QtDataVisualization/qvalue3daxis.h> +#include <QtDataVisualization/q3dscene.h> +#include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qbar3dseries.h> +#include <QtDataVisualization/q3dtheme.h> + +#include <QAudioDeviceInfo> +#include <QAudioInput> + +using namespace QtDataVisualization; + +AudioLevels::AudioLevels(Q3DBars *graph, QObject *parent) + : QObject(parent), + m_graph(graph), + m_device(0), + m_audioInput(0) +{ + // Set up the graph + m_graph->setBarThickness(0.5f); + m_graph->setBarSpacing(QSizeF(0.0, 1.0)); + m_graph->valueAxis()->setRange(-100.0f, 100.0f); + m_graph->valueAxis()->setSegmentCount(20); + m_graph->valueAxis()->setLabelFormat(QStringLiteral("%d%%")); + m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityNone); + m_graph->setSelectionMode(QAbstract3DGraph::SelectionNone); + m_graph->scene()->activeCamera()->setCameraPosition(-25.0f, 10.0f, 190.0f); + m_graph->activeTheme()->setType(Q3DTheme::ThemeIsabelle); + m_graph->activeTheme()->setGridEnabled(true); + m_graph->activeTheme()->setBackgroundEnabled(false); + QFont font = m_graph->activeTheme()->font(); + font.setPointSize(10); + m_graph->activeTheme()->setFont(font); + QBar3DSeries *series = new QBar3DSeries; + series->setMesh(QAbstract3DSeries::MeshBar); + m_graph->addSeries(series); + + //! [0] + QAudioDeviceInfo inputDevice = QAudioDeviceInfo::defaultInputDevice(); + + QAudioFormat formatAudio; + formatAudio.setSampleRate(inputDevice.supportedSampleRates().at(0)); + formatAudio.setChannelCount(inputDevice.supportedChannelCounts().at(0)); + formatAudio.setSampleSize(inputDevice.supportedSampleSizes().at(0)); + formatAudio.setCodec(inputDevice.supportedCodecs().at(0)); + formatAudio.setByteOrder(QAudioFormat::LittleEndian); + formatAudio.setSampleType(QAudioFormat::UnSignedInt); + + m_audioInput = new QAudioInput(inputDevice, formatAudio, this); +#ifdef Q_OS_MAC + // Mac seems to wait for entire buffer to fill before calling writeData, so use smaller buffer + m_audioInput->setBufferSize(256); +#else + m_audioInput->setBufferSize(1024); +#endif + + m_device = new AudioLevelsIODevice(m_graph->seriesList().at(0)->dataProxy(), this); + m_device->open(QIODevice::WriteOnly); + + m_audioInput->start(m_device); + //! [0] +} + +AudioLevels::~AudioLevels() +{ + m_audioInput->stop(); + m_device->close(); +} diff --git a/examples/datavisualization/audiolevels/audiolevels.h b/examples/datavisualization/audiolevels/audiolevels.h new file mode 100644 index 00000000..84d9b4c4 --- /dev/null +++ b/examples/datavisualization/audiolevels/audiolevels.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUDIOLEVELS_H +#define AUDIOLEVELS_H + +#include <QtDataVisualization/q3dbars.h> + +using namespace QtDataVisualization; + +class AudioLevelsIODevice; +class QAudioInput; + +class AudioLevels : public QObject +{ + Q_OBJECT + +public: + AudioLevels(Q3DBars *graph, QObject *parent = 0); + ~AudioLevels(); + +private: + //! [0] + Q3DBars *m_graph; + AudioLevelsIODevice *m_device; + QAudioInput *m_audioInput; + //! [0] +}; + +#endif diff --git a/examples/datavisualization/audiolevels/audiolevels.pro b/examples/datavisualization/audiolevels/audiolevels.pro new file mode 100644 index 00000000..46f01635 --- /dev/null +++ b/examples/datavisualization/audiolevels/audiolevels.pro @@ -0,0 +1,14 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +TARGET = audiolevels + +QT += multimedia + +SOURCES += main.cpp \ + audiolevels.cpp \ + audiolevelsiodevice.cpp + +HEADERS += audiolevels.h \ + audiolevelsiodevice.h diff --git a/examples/datavisualization/audiolevels/audiolevelsiodevice.cpp b/examples/datavisualization/audiolevels/audiolevelsiodevice.cpp new file mode 100644 index 00000000..c0cd70e3 --- /dev/null +++ b/examples/datavisualization/audiolevels/audiolevelsiodevice.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "audiolevelsiodevice.h" +#include <QDebug> + +using namespace QtDataVisualization; + +//! [1] +static const int resolution = 8; +static const int rowSize = 800; +static const int rowCount = 7; // Must be odd number +static const int middleRow = rowCount / 2; +//! [1] + +AudioLevelsIODevice::AudioLevelsIODevice(QBarDataProxy *proxy, QObject *parent) + : QIODevice(parent), + m_proxy(proxy), + m_array(new QBarDataArray) +{ + // We reuse the existing array for maximum performance, so construct the array here + //! [0] + m_array->reserve(rowCount); + for (int i = 0; i < rowCount; i++) + m_array->append(new QBarDataRow(rowSize)); + //! [0] + + qDebug() << "Total of" << (rowSize * rowCount) << "items in the array."; +} + +// Implementation required for this pure virtual function +qint64 AudioLevelsIODevice::readData(char *data, qint64 maxSize) +{ + Q_UNUSED(data) + Q_UNUSED(maxSize) + return -1; +} + +//! [2] +qint64 AudioLevelsIODevice::writeData(const char *data, qint64 maxSize) +{ + // The amount of new data available. + int newDataSize = maxSize / resolution; + + // If we get more data than array size, we need to adjust the start index for new data. + int newDataStartIndex = qMax(0, (newDataSize - rowSize)); + + // Move the old data ahead in the rows (only do first half of rows + middle one now). + // If the amount of new data was larger than row size, skip copying. + if (!newDataStartIndex) { + for (int i = 0; i <= middleRow; i++) { + QBarDataItem *srcPos = m_array->at(i)->data(); + QBarDataItem *dstPos = srcPos + newDataSize; + memmove((void *)dstPos, (void *)srcPos, (rowSize - newDataSize) * sizeof(QBarDataItem)); + } + } + + // Insert data in reverse order, so that newest data is always at the front of the row. + int index = 0; + for (int i = newDataSize - 1; i >= newDataStartIndex; i--) { + // Add 0.01 to the value to avoid gaps in the graph (i.e. zero height bars). + // Also, scale to 0...100 + float value = float(quint8(data[resolution * i]) - 128) / 1.28f + 0.01f; + (*m_array->at(middleRow))[index].setValue(value); + // Insert a fractional value into front half of the rows. + for (int j = 1; j <= middleRow; j++) { + float fractionalValue = value / float(j + 1); + (*m_array->at(middleRow - j))[index].setValue(fractionalValue); + } + index++; + } + + // Copy the front half of rows to the back half for symmetry. + index = 0; + for (int i = rowCount - 1; i > middleRow; i--) { + QBarDataItem *srcPos = m_array->at(index++)->data(); + QBarDataItem *dstPos = m_array->at(i)->data(); + memcpy((void *)dstPos, (void *)srcPos, rowSize * sizeof(QBarDataItem)); + } + + // Reset the proxy array now that data has been updated to trigger a redraw. + m_proxy->resetArray(m_array); + + return maxSize; +} +//! [2] + + diff --git a/examples/datavisualization/audiolevels/audiolevelsiodevice.h b/examples/datavisualization/audiolevels/audiolevelsiodevice.h new file mode 100644 index 00000000..45f17626 --- /dev/null +++ b/examples/datavisualization/audiolevels/audiolevelsiodevice.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef AUDIOLEVELSIODEVICE_H +#define AUDIOLEVELSIODEVICE_H + +#include <QtDataVisualization/qbardataproxy.h> +#include <QIODevice> + +using namespace QtDataVisualization; + +class AudioLevelsIODevice : public QIODevice +{ + Q_OBJECT +public: + explicit AudioLevelsIODevice(QBarDataProxy *proxy, QObject *parent = 0); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + //! [0] + QBarDataProxy *m_proxy; + QBarDataArray *m_array; + //! [0] +}; + +#endif diff --git a/examples/datavisualization/audiolevels/doc/images/audiolevels-example.png b/examples/datavisualization/audiolevels/doc/images/audiolevels-example.png Binary files differnew file mode 100644 index 00000000..ec79eb5a --- /dev/null +++ b/examples/datavisualization/audiolevels/doc/images/audiolevels-example.png diff --git a/examples/datavisualization/audiolevels/doc/src/audiolevels.qdoc b/examples/datavisualization/audiolevels/doc/src/audiolevels.qdoc new file mode 100644 index 00000000..ad87ecc0 --- /dev/null +++ b/examples/datavisualization/audiolevels/doc/src/audiolevels.qdoc @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +/*! + \example audiolevels + \title Audiolevels Example + \ingroup qtdatavisualization_examples + \brief Simple application showing real time audio data. + + The audiolevels example shows how feed real-time dynamic data to a graph using Q3DBars. + + This example reads the audio levels from a microphone and displays those levels + in a bar graph. To increase the load for demonstration purposes, and to make the + graph little fancier, slightly modified data is used to fill multiple rows. + + \image audiolevels-example.png + + The interesting stuff happens in \c AudioLevels and \c AudioLevelsIODevice classes, so we + concentrate on those and skip explaining the basic Q3DBars functionality - for that see + \l{Bars Example}. + + \c AudioLevelsIODevice subclasses QIODevice and is given as input device for QAudioInput + class, so it receives microphone data. + + In the header file for \c AudioLevels class we declare necessary members: + + \snippet ../examples/audiolevels/audiolevels.h 0 + + And initialize the microphone listening in the source: + + \snippet ../examples/audiolevels/audiolevels.cpp 0 + + In the header file for \c AudioLevelsIODevice class we store pointers to the data proxy and + also the data array we give to the proxy, because we reuse the same array to keep memory + reallocations to the minimum: + + \snippet ../examples/audiolevels/audiolevelsiodevice.h 0 + + In the source file we define some static constants to define size of the data array and + the middle row index, as well as the resolution of the visualization. You may need to adjust + these values to get decent performance in low-end devices: + + \snippet ../examples/audiolevels/audiolevelsiodevice.cpp 1 + + The \c resolution constant indicates the sample rate, for example, value 8 means every eighth + byte from audio input is visualized. This is necessary to make the data readable, as it would + otherwise make the graph scroll too fast. + + In the \c AudioLevelsIODevice class constructor we initialize the data array: + + \snippet ../examples/audiolevels/audiolevelsiodevice.cpp 0 + + The \c AudioLevelsIODevice::writeData function is called whenever there is new audio data + available to be visualized. There we move the old data along the rows and insert new + data in the beginning of the rows: + + \snippet ../examples/audiolevels/audiolevelsiodevice.cpp 2 + + We use a couple of techniques here to improve performance. First, we reuse + the existing data array, as this allows us to avoid any extra memory allocations in our + application code. This also means the data array dimensions do not change, which further + improves efficiency in the bar graph renderer. + Secondly, since each row is a QVector of bar data items, which do not allocate any data that needs + deletion, we can utilize \c memmove and \c memcpy functions to quickly move and copy data around. + + \note In the future versions of Qt Data Visualization, QBarDataItem might get extended so that + it does allocate some memory to store other optional bar properties besides the value. + In use cases where those optional properties are used, using \c memmove and \c memcpy could lead to + memory leaks, so use them with care. +*/ diff --git a/examples/datavisualization/audiolevels/main.cpp b/examples/datavisualization/audiolevels/main.cpp new file mode 100644 index 00000000..9dd07b1b --- /dev/null +++ b/examples/datavisualization/audiolevels/main.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "audiolevels.h" + +#include <QGuiApplication> +#include <QAudio> + +using namespace QtDataVisualization; + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + Q3DBars window; + window.setFlags(window.flags() ^ Qt::FramelessWindowHint); + window.resize(800, 500); + window.setTitle("Qt Data Visualization - Microphone audio levels visualizer"); + window.show(); + + AudioLevels audioLevels(&window); + + return app.exec(); +} |