/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Data Visualization module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \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}.

    \include examples-run.qdocinc

    \section1 Visualizing Audio Levels

    \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 audiolevels/audiolevels.h 0

    And initialize the microphone listening in the source:

    \snippet 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 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 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 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 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.
*/
