diff options
Diffstat (limited to 'demos/spectrum/app/waveform.cpp')
-rw-r--r-- | demos/spectrum/app/waveform.cpp | 120 |
1 files changed, 69 insertions, 51 deletions
diff --git a/demos/spectrum/app/waveform.cpp b/demos/spectrum/app/waveform.cpp index 1f7d315..bd854c0 100644 --- a/demos/spectrum/app/waveform.cpp +++ b/demos/spectrum/app/waveform.cpp @@ -44,12 +44,18 @@ #include <QResizeEvent> #include <QDebug> - -Waveform::Waveform(const QByteArray &buffer, QWidget *parent) +//#define PAINT_EVENT_TRACE +#ifdef PAINT_EVENT_TRACE +# define WAVEFORM_PAINT_DEBUG qDebug() +#else +# define WAVEFORM_PAINT_DEBUG nullDebug() +#endif + +Waveform::Waveform(QWidget *parent) : QWidget(parent) - , m_buffer(buffer) - , m_dataLength(0) - , m_position(0) + , m_bufferPosition(0) + , m_bufferLength(0) + , m_audioPosition(0) , m_active(false) , m_tileLength(0) , m_tileArrayStart(0) @@ -72,19 +78,19 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) painter.fillRect(rect(), Qt::black); if (m_active) { - WAVEFORM_DEBUG << "Waveform::paintEvent" - << "windowPosition" << m_windowPosition - << "windowLength" << m_windowLength; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" + << "windowPosition" << m_windowPosition + << "windowLength" << m_windowLength; qint64 pos = m_windowPosition; const qint64 windowEnd = m_windowPosition + m_windowLength; int destLeft = 0; int destRight = 0; while (pos < windowEnd) { const TilePoint point = tilePoint(pos); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos - << "tileIndex" << point.index - << "positionOffset" << point.positionOffset - << "pixelOffset" << point.pixelOffset; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos + << "tileIndex" << point.index + << "positionOffset" << point.positionOffset + << "pixelOffset" << point.pixelOffset; if (point.index != NullIndex) { const Tile &tile = m_tiles[point.index]; @@ -104,9 +110,9 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) sourceRect.setLeft(point.pixelOffset); sourceRect.setRight(sourceRight); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index - << "source" << point.pixelOffset << sourceRight - << "dest" << destLeft << destRight; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index + << "source" << point.pixelOffset << sourceRight + << "dest" << destLeft << destRight; painter.drawPixmap(destRect, *tile.pixmap, sourceRect); @@ -114,25 +120,25 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) if (point.index < m_tiles.count()) { pos = tilePosition(point.index + 1); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos ->" << pos; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos ->" << pos; } else { // Reached end of tile array - WAVEFORM_DEBUG << "Waveform::paintEvent" << "reached end of tile array"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "reached end of tile array"; break; } } else { // Passed last tile which is painted - WAVEFORM_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted"; break; } } else { // pos is past end of tile array - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array"; break; } } - WAVEFORM_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight; } } @@ -146,7 +152,6 @@ void Waveform::initialize(const QAudioFormat &format, qint64 audioBufferSize, qi { WAVEFORM_DEBUG << "Waveform::initialize" << "audioBufferSize" << audioBufferSize - << "m_buffer.size()" << m_buffer.size() << "windowDurationUs" << windowDurationUs; reset(); @@ -186,8 +191,9 @@ void Waveform::reset() { WAVEFORM_DEBUG << "Waveform::reset"; - m_dataLength = 0; - m_position = 0; + m_bufferPosition = 0; + m_buffer = QByteArray(); + m_audioPosition = 0; m_format = QAudioFormat(); m_active = false; deletePixmaps(); @@ -198,30 +204,31 @@ void Waveform::reset() m_windowLength = 0; } -void Waveform::dataLengthChanged(qint64 length) +void Waveform::bufferChanged(qint64 position, qint64 length, const QByteArray &buffer) { - WAVEFORM_DEBUG << "Waveform::dataLengthChanged" << length; - const qint64 oldLength = m_dataLength; - m_dataLength = length; - - if (m_active) { - if (m_dataLength < oldLength) - positionChanged(m_dataLength); - else - paintTiles(); - } + WAVEFORM_DEBUG << "Waveform::bufferChanged" + << "audioPosition" << m_audioPosition + << "bufferPosition" << position + << "bufferLength" << length; + m_bufferPosition = position; + m_bufferLength = length; + m_buffer = buffer; + paintTiles(); } -void Waveform::positionChanged(qint64 position) +void Waveform::audioPositionChanged(qint64 position) { - WAVEFORM_DEBUG << "Waveform::positionChanged" << position; - - if (position + m_windowLength > m_dataLength) - position = m_dataLength - m_windowLength; - - m_position = position; - - setWindowPosition(position); + WAVEFORM_DEBUG << "Waveform::audioPositionChanged" + << "audioPosition" << position + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength; + + if (position >= m_bufferPosition) { + if (position + m_windowLength > m_bufferPosition + m_bufferLength) + position = qMax(qint64(0), m_bufferPosition + m_bufferLength - m_windowLength); + m_audioPosition = position; + setWindowPosition(position); + } } void Waveform::deletePixmaps() @@ -255,8 +262,6 @@ void Waveform::createPixmaps(const QSize &widgetSize) m_tiles[i].pixmap = m_pixmaps[i]; m_tiles[i].painted = false; } - - paintTiles(); } void Waveform::setWindowPosition(qint64 position) @@ -327,8 +332,9 @@ bool Waveform::paintTiles() for (int i=0; i<m_tiles.count(); ++i) { const Tile &tile = m_tiles[i]; if (!tile.painted) { - const qint64 tileEnd = m_tileArrayStart + (i + 1) * m_tileLength; - if (m_dataLength >= tileEnd) { + const qint64 tileStart = m_tileArrayStart + i * m_tileLength; + const qint64 tileEnd = tileStart + m_tileLength; + if (m_bufferPosition <= tileStart && m_bufferPosition + m_bufferLength >= tileEnd) { paintTile(i); updateRequired = true; } @@ -343,16 +349,23 @@ bool Waveform::paintTiles() void Waveform::paintTile(int index) { - WAVEFORM_DEBUG << "Waveform::paintTile" << "index" << index; - const qint64 tileStart = m_tileArrayStart + index * m_tileLength; - Q_ASSERT(m_dataLength >= tileStart + m_tileLength); + + WAVEFORM_DEBUG << "Waveform::paintTile" + << "index" << index + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength + << "start" << tileStart + << "end" << tileStart + m_tileLength; + + Q_ASSERT(m_bufferPosition <= tileStart); + Q_ASSERT(m_bufferPosition + m_bufferLength >= tileStart + m_tileLength); Tile &tile = m_tiles[index]; Q_ASSERT(!tile.painted); const qint16* base = reinterpret_cast<const qint16*>(m_buffer.constData()); - const qint16* buffer = base + (tileStart / 2); + const qint16* buffer = base + ((tileStart - m_bufferPosition) / 2); const int numSamples = m_tileLength / (2 * m_format.channels()); QPainter painter(tile.pixmap); @@ -376,6 +389,11 @@ void Waveform::paintTile(int index) for (int i=0; i<numSamples; ++i) { const qint16* ptr = buffer + i * m_format.channels(); + + const int offset = reinterpret_cast<const char*>(ptr) - m_buffer.constData(); + Q_ASSERT(offset >= 0); + Q_ASSERT(offset < m_bufferLength); + const qint16 pcmValue = *ptr; const qreal realValue = pcmToReal(pcmValue); |