Files
DrumMachine/widgets/scratchwidget.cpp

147 lines
3.3 KiB
C++
Raw Permalink Normal View History

2020-04-27 22:59:30 +02:00
#include "scratchwidget.h"
#include <QPainter>
2020-04-27 23:39:49 +02:00
#include <QRect>
2020-04-28 00:06:50 +02:00
#include <QMouseEvent>
2020-04-27 23:39:49 +02:00
#include <QDebug>
2020-04-27 22:59:30 +02:00
2022-12-27 21:19:21 +01:00
#include "audioformat.h"
2020-04-27 22:59:30 +02:00
#include "graphrenderer.h"
ScratchWidget::ScratchWidget(QWidget *parent) :
2022-12-27 21:19:21 +01:00
QWidget{parent},
m_framesPerBeat{frameRate/4}
2020-04-27 22:59:30 +02:00
{
2020-04-28 00:06:50 +02:00
connect(&m_timer, &QTimer::timeout, this, &ScratchWidget::timeout);
m_timer.setSingleShot(true);
m_timer.setInterval(100);
2020-04-27 22:59:30 +02:00
}
void ScratchWidget::paintEvent(QPaintEvent *event)
{
2022-12-27 23:43:09 +01:00
Q_UNUSED(event)
2020-04-27 22:59:30 +02:00
QPainter painter;
painter.begin(this);
painter.setPen({});
painter.setBrush(palette().window());
painter.drawRect(rect());
2020-04-29 19:48:41 +02:00
if (m_buffer.isValid() && m_position < m_buffer.frameCount() - m_framesPerBeat)
2020-04-27 23:39:49 +02:00
{
{
QPen pen{Qt::blue};
pen.setWidth(3);
painter.setPen(pen);
}
const auto doit = [&](int offset)
{
2020-04-29 19:48:41 +02:00
int x = ((width()/2)-(float(m_position % m_framesPerBeat) / m_framesPerBeat * m_beatWidth)) + (m_beatWidth*offset);
const auto pixmap = getPixmap((m_position/m_framesPerBeat)+offset);
2020-04-27 23:39:49 +02:00
if (!pixmap.isNull())
painter.drawPixmap(x, 0, pixmap);
};
doit(-2);
doit(-1);
doit(0);
doit(1);
doit(2);
}
2020-04-27 22:59:30 +02:00
{
QPen pen{Qt::red};
pen.setWidth(3);
painter.setPen(pen);
}
painter.drawLine(width()/2, 0, width()/2, height());
painter.end();
}
void ScratchWidget::mousePressEvent(QMouseEvent *event)
{
2020-04-28 00:06:50 +02:00
if (event->button() == Qt::LeftButton)
{
m_scratching = true;
m_mouseX = event->x();
m_timestamp = QDateTime::currentDateTime();
setMouseTracking(true);
2020-04-28 00:26:40 +02:00
emit scratchBegin();
2020-04-29 19:48:41 +02:00
emit scratchSpeed(0.f);
2020-04-28 00:06:50 +02:00
}
2020-04-27 22:59:30 +02:00
}
void ScratchWidget::mouseReleaseEvent(QMouseEvent *event)
{
2020-04-28 00:06:50 +02:00
if (event->button() == Qt::LeftButton)
{
m_timer.stop();
emit scratchSpeed(1.f);
m_scratching = false;
setMouseTracking(false);
2020-04-28 00:26:40 +02:00
emit scratchEnd();
2020-04-28 00:06:50 +02:00
}
2020-04-27 22:59:30 +02:00
}
void ScratchWidget::mouseMoveEvent(QMouseEvent *event)
{
2020-04-28 00:06:50 +02:00
if (m_scratching)
{
const auto now = QDateTime::currentDateTime();
2020-04-27 22:59:30 +02:00
2020-04-28 00:06:50 +02:00
int dx = m_mouseX - event->x();
int dt = m_timestamp.msecsTo(now);
2020-04-29 19:48:41 +02:00
emit scratchSpeed(float(dx) / dt * m_framesPerBeat / m_beatWidth / 50);
2020-04-28 00:06:50 +02:00
m_mouseX = event->x();
m_timestamp = now;
m_timer.start();
}
}
void ScratchWidget::timeout()
{
emit scratchSpeed(0.f);
2020-04-27 22:59:30 +02:00
}
2020-04-27 23:39:49 +02:00
QPixmap ScratchWidget::getPixmap(int index)
{
{
const auto pixmap = m_graphCache[index];
if (pixmap)
return *pixmap;
}
2020-04-29 19:48:41 +02:00
if (!m_buffer.isValid() || index < 0 || index >= m_buffer.frameCount()/m_framesPerBeat)
2020-04-27 23:39:49 +02:00
{
qWarning() << index;
return {};
}
2020-04-29 19:48:41 +02:00
const auto *begin = m_buffer.constData<frame_t>() + (index*m_framesPerBeat);
2020-04-27 23:39:49 +02:00
2020-04-30 21:06:17 +02:00
const auto pixmap = new QPixmap{QSize{m_beatWidth, height()}};
2020-04-27 23:39:49 +02:00
2020-04-30 21:06:17 +02:00
{
QPainter painter;
painter.begin(pixmap);
painter.setPen(Qt::blue);
painter.setBrush(palette().base());
painter.drawRect(pixmap->rect());
painter.setPen(QPen{palette().color(QPalette::Text)});
painter.setBrush(palette().text());
GraphRenderer::render(pixmap->rect(), begin, begin+m_framesPerBeat, painter);
}
m_graphCache.insert(index, pixmap);
return *pixmap;
2020-04-27 23:39:49 +02:00
}