1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#ifndef WAVEFORM_H
52#define WAVEFORM_H
53
54#include <QAudioFormat>
55#include <QPixmap>
56#include <QScopedPointer>
57#include <QWidget>
58
59/**
60 * Widget which displays a section of the audio waveform.
61 *
62 * The waveform is rendered on a set of QPixmaps which form a group of tiles
63 * whose extent covers the widget. As the audio position is updated, these
64 * tiles are scrolled from left to right; when the left-most tile scrolls
65 * outside the widget, it is moved to the right end of the tile array and
66 * painted with the next section of the waveform.
67 */
68class Waveform : public QWidget
69{
70 Q_OBJECT
71
72public:
73 explicit Waveform(QWidget *parent = 0);
74 ~Waveform();
75
76 // QWidget
77 void paintEvent(QPaintEvent *event) override;
78 void resizeEvent(QResizeEvent *event) override;
79
80 void initialize(const QAudioFormat &format, qint64 audioBufferSize, qint64 windowDurationUs);
81 void reset();
82
83 void setAutoUpdatePosition(bool enabled);
84
85public slots:
86 void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer);
87 void audioPositionChanged(qint64 position);
88
89private:
90 static const int NullIndex = -1;
91
92 void deletePixmaps();
93
94 /*
95 * (Re)create all pixmaps, repaint and update the display.
96 * Triggers an update();
97 */
98 void createPixmaps(const QSize &newSize);
99
100 /*
101 * Update window position.
102 * Triggers an update().
103 */
104 void setWindowPosition(qint64 position);
105
106 /*
107 * Base position of tile
108 */
109 qint64 tilePosition(int index) const;
110
111 /*
112 * Structure which identifies a point within a given
113 * tile.
114 */
115 struct TilePoint
116 {
117 TilePoint(int idx = 0, qint64 pos = 0, qint64 pix = 0)
118 : index(idx), positionOffset(pos), pixelOffset(pix)
119 { }
120
121 // Index of tile
122 int index;
123
124 // Number of bytes from start of tile
125 qint64 positionOffset;
126
127 // Number of pixels from left of corresponding pixmap
128 int pixelOffset;
129 };
130
131 /*
132 * Convert position in m_buffer into a tile index and an offset in pixels
133 * into the corresponding pixmap.
134 *
135 * \param position Offset into m_buffer, in bytes
136
137 * If position is outside the tile array, index is NullIndex and
138 * offset is zero.
139 */
140 TilePoint tilePoint(qint64 position) const;
141
142 /*
143 * Convert offset in bytes into a tile into an offset in pixels
144 * within that tile.
145 */
146 int tilePixelOffset(qint64 positionOffset) const;
147
148 /*
149 * Convert offset in bytes into the window into an offset in pixels
150 * within the widget rect().
151 */
152 int windowPixelOffset(qint64 positionOffset) const;
153
154 /*
155 * Paint all tiles which can be painted.
156 * \return true iff update() was called
157 */
158 bool paintTiles();
159
160 /*
161 * Paint the specified tile
162 *
163 * \pre Sufficient data is available to completely paint the tile, i.e.
164 * m_dataLength is greater than the upper bound of the tile.
165 */
166 void paintTile(int index);
167
168 /*
169 * Move the first n tiles to the end of the array, and mark them as not
170 * painted.
171 */
172 void shuffleTiles(int n);
173
174 /*
175 * Reset tile array
176 */
177 void resetTiles(qint64 newStartPos);
178
179private:
180 qint64 m_bufferPosition;
181 qint64 m_bufferLength;
182 QByteArray m_buffer;
183
184 qint64 m_audioPosition;
185 QAudioFormat m_format;
186
187 bool m_active;
188
189 QSize m_pixmapSize;
190 QVector<QPixmap*> m_pixmaps;
191
192 struct Tile {
193 // Pointer into parent m_pixmaps array
194 QPixmap* pixmap;
195
196 // Flag indicating whether this tile has been painted
197 bool painted;
198 };
199
200 QVector<Tile> m_tiles;
201
202 // Length of audio data in bytes depicted by each tile
203 qint64 m_tileLength;
204
205 // Position in bytes of the first tile, relative to m_buffer
206 qint64 m_tileArrayStart;
207
208 qint64 m_windowPosition;
209 qint64 m_windowLength;
210};
211
212#endif // WAVEFORM_H
213

source code of qtmultimedia/examples/multimedia/spectrum/app/waveform.h