demos/spectrum/app/waveform.h
changeset 25 e24348a560a6
child 29 b72c6db6890b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/spectrum/app/waveform.h	Fri Jun 11 14:24:45 2010 +0300
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** - Redistributions of source code must retain the above copyright notice,
+**   this list of conditions and the following disclaimer.
+** - Redistributions in binary form must reproduce the above copyright notice,
+**   this list of conditions and the following disclaimer in the documentation
+**   and/or other materials provided with the distribution.
+** - Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+**   names of its contributors may be used to endorse or promote products
+**   derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+** $QT_END_LICENSE$
+**
+*****************************************************************************/
+
+#ifndef WAVEFORM_H
+#define WAVEFORM_H
+
+#include <QWidget>
+#include <QtMultimedia/QAudioFormat>
+#include <QPixmap>
+#include <QScopedPointer>
+
+class QByteArray;
+
+/**
+ * Widget which displays a section of the audio waveform.
+ *
+ * The waveform is rendered on a set of QPixmaps which form a group of tiles
+ * whose extent covers the widget.  As the audio position is updated, these
+ * tiles are scrolled from left to right; when the left-most tile scrolls
+ * outside the widget, it is moved to the right end of the tile array and
+ * painted with the next section of the waveform.
+ */
+class Waveform : public QWidget {
+    Q_OBJECT
+public:
+    Waveform(const QByteArray &buffer, QWidget *parent = 0);
+    ~Waveform();
+
+    // QWidget
+    void paintEvent(QPaintEvent *event);
+    void resizeEvent(QResizeEvent *event);
+
+    void initialize(const QAudioFormat &format, qint64 audioBufferSize, qint64 windowDurationUs);
+    void reset();
+
+    void setAutoUpdatePosition(bool enabled);
+
+public slots:
+    void dataLengthChanged(qint64 length);
+    void positionChanged(qint64 position);
+
+private:
+    static const int NullIndex = -1;
+
+    void deletePixmaps();
+
+    /*
+     * (Re)create all pixmaps, repaint and update the display.
+     * Triggers an update();
+     */
+    void createPixmaps(const QSize &newSize);
+
+    /*
+     * Update window position.
+     * Triggers an update().
+     */
+    void setWindowPosition(qint64 position);
+
+    /*
+     * Base position of tile
+     */
+    qint64 tilePosition(int index) const;
+
+    /*
+     * Structure which identifies a point within a given
+     * tile.
+     */
+    struct TilePoint
+    {
+        TilePoint(int idx = 0, qint64 pos = 0, qint64 pix = 0)
+        :   index(idx), positionOffset(pos), pixelOffset(pix)
+        { }
+
+        // Index of tile
+        int     index;
+
+        // Number of bytes from start of tile
+        qint64  positionOffset;
+
+        // Number of pixels from left of corresponding pixmap
+        int     pixelOffset;
+    };
+
+    /*
+     * Convert position in m_buffer into a tile index and an offset in pixels
+     * into the corresponding pixmap.
+     *
+     * \param position  Offset into m_buffer, in bytes
+
+     * If position is outside the tile array, index is NullIndex and
+     * offset is zero.
+     */
+    TilePoint tilePoint(qint64 position) const;
+
+    /*
+     * Convert offset in bytes into a tile into an offset in pixels
+     * within that tile.
+     */
+    int tilePixelOffset(qint64 positionOffset) const;
+
+    /*
+     * Convert offset in bytes into the window into an offset in pixels
+     * within the widget rect().
+     */
+    int windowPixelOffset(qint64 positionOffset) const;
+
+    /*
+     * Paint all tiles which can be painted.
+     * \return true iff update() was called
+     */
+    bool paintTiles();
+
+    /*
+     * Paint the specified tile
+     *
+     * \pre Sufficient data is available to completely paint the tile, i.e.
+     *      m_dataLength is greater than the upper bound of the tile.
+     */
+    void paintTile(int index);
+
+    /*
+     * Move the first n tiles to the end of the array, and mark them as not
+     * painted.
+     */
+    void shuffleTiles(int n);
+
+    /*
+     * Reset tile array
+     */
+    void resetTiles(qint64 newStartPos);
+
+private:
+    const QByteArray&       m_buffer;
+    qint64                  m_dataLength;
+    qint64                  m_position;
+    QAudioFormat            m_format;
+
+    bool                    m_active;
+
+    QSize                   m_pixmapSize;
+    QVector<QPixmap*>       m_pixmaps;
+
+    struct Tile {
+        // Pointer into parent m_pixmaps array
+        QPixmap*            pixmap;
+
+        // Flag indicating whether this tile has been painted
+        bool                painted;
+    };
+
+    QVector<Tile>           m_tiles;
+
+    // Length of audio data in bytes depicted by each tile
+    qint64                  m_tileLength;
+
+    // Position in bytes of the first tile, relative to m_buffer
+    qint64                  m_tileArrayStart;
+
+    qint64                  m_windowPosition;
+    qint64                  m_windowLength;
+
+};
+
+#endif // WAVEFORM_H