Implemented basic BPM mechanism
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
#include <QTextStream>
|
||||
#include <QUrl>
|
||||
#include <QFileInfo>
|
||||
#include <QButtonGroup>
|
||||
#include <QDebug>
|
||||
|
||||
#include "audiodecoder.h"
|
||||
@ -20,12 +21,36 @@ TrackDeck::TrackDeck(QWidget *parent) :
|
||||
m_ui->setupUi(this);
|
||||
m_ui->progressBar->hide();
|
||||
|
||||
m_loopGroup.addButton(m_ui->pushButtonLoopOff, -1);
|
||||
m_loopGroup.addButton(m_ui->pushButtonLoop1, 1);
|
||||
m_loopGroup.addButton(m_ui->pushButtonLoop2, 2);
|
||||
m_loopGroup.addButton(m_ui->pushButtonLoop4, 4);
|
||||
m_loopGroup.addButton(m_ui->pushButtonLoop8, 8);
|
||||
connect(&m_loopGroup, qOverload<int>(&QButtonGroup::buttonClicked), [&player=m_player,&bpmInput=*m_ui->doubleSpinBoxBpm](int id){
|
||||
const auto position = player.position();
|
||||
|
||||
const auto bpm = bpmInput.value();
|
||||
const auto beatsPerSecond = bpm / 60.;
|
||||
const auto framesPerBeat = frameRate / beatsPerSecond;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 1: player.setLoop(std::make_pair(position, position + (framesPerBeat/4))); break;
|
||||
case 2: player.setLoop(std::make_pair(position, position + (framesPerBeat/2))); break;
|
||||
case 4: player.setLoop(std::make_pair(position, position + framesPerBeat)); break;
|
||||
case 8: player.setLoop(std::make_pair(position, position + (framesPerBeat*2))); break;
|
||||
default: player.setLoop({});
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_ui->pushButtonBpm, &QAbstractButton::pressed, this, &TrackDeck::bpmTap);
|
||||
|
||||
connect(m_ui->pushButtonPlay, &QAbstractButton::pressed, &m_player, &AudioPlayer::togglePlaying);
|
||||
connect(m_ui->pushButtonStop, &QAbstractButton::pressed, &m_player, &AudioPlayer::stop);
|
||||
|
||||
connect(m_ui->verticalSliderVolume, &QAbstractSlider::valueChanged, &m_player, [&player=m_player](int value){ player.setVolume(float(value)/100.f); });
|
||||
|
||||
connect(m_ui->horizontalSliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
connect(m_ui->sliderZoom, &QAbstractSlider::valueChanged, m_ui->scratchWidget, &ScratchWidget::setBeatWidth);
|
||||
connect(m_ui->sliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
connect(m_ui->sliderVolume, &QAbstractSlider::valueChanged, &m_player, [&player=m_player](int value){ player.setVolume(float(value)/100.f); });
|
||||
|
||||
connect(m_ui->previewWidget, &PreviewWidget::positionSelected, &m_player, &AudioPlayer::setPosition);
|
||||
connect(&m_player, &AudioPlayer::positionChanged, m_ui->previewWidget, &PreviewWidget::setPosition);
|
||||
@ -33,6 +58,15 @@ TrackDeck::TrackDeck(QWidget *parent) :
|
||||
connect(m_ui->scratchWidget, &ScratchWidget::scratchEnd, this, &TrackDeck::scratchEnd);
|
||||
connect(&m_player, &AudioPlayer::positionChanged, m_ui->scratchWidget, &ScratchWidget::setPosition);
|
||||
connect(&m_player, &AudioPlayer::playingChanged, this, &TrackDeck::updatePlayButtonText);
|
||||
|
||||
connect(m_ui->sliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::updatePlaybackBpm);
|
||||
connect(m_ui->doubleSpinBoxBpm, &QDoubleSpinBox::valueChanged, this, &TrackDeck::updatePlaybackBpm);
|
||||
|
||||
connect(&m_timer, &QTimer::timeout, this, &TrackDeck::timeout);
|
||||
m_timer.setSingleShot(true);
|
||||
m_timer.setInterval(1000);
|
||||
|
||||
updatePlaybackBpm();
|
||||
}
|
||||
|
||||
TrackDeck::~TrackDeck() = default;
|
||||
@ -141,6 +175,12 @@ void TrackDeck::decodingProgress(int progress, int total)
|
||||
void TrackDeck::decodingFinished(const QAudioBuffer &buffer)
|
||||
{
|
||||
m_player.setBuffer(buffer);
|
||||
|
||||
m_ui->labelTitle->setText(QFileInfo{m_filename}.fileName());
|
||||
|
||||
for (auto *btn : m_loopGroup.buttons())
|
||||
btn->setEnabled(false);
|
||||
|
||||
m_ui->previewWidget->setBuffer(buffer);
|
||||
m_ui->scratchWidget->setBuffer(buffer);
|
||||
m_ui->progressBar->hide();
|
||||
@ -148,8 +188,8 @@ void TrackDeck::decodingFinished(const QAudioBuffer &buffer)
|
||||
|
||||
void TrackDeck::scratchBegin()
|
||||
{
|
||||
disconnect(m_ui->horizontalSliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
m_ui->horizontalSliderSpeed->setEnabled(false);
|
||||
disconnect(m_ui->sliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
m_ui->sliderSpeed->setEnabled(false);
|
||||
connect(m_ui->scratchWidget, &ScratchWidget::scratchSpeed, &m_player, &AudioPlayer::setSpeed);
|
||||
disconnect(&m_player, &AudioPlayer::playingChanged, this, &TrackDeck::updatePlayButtonText);
|
||||
|
||||
@ -169,8 +209,8 @@ void TrackDeck::scratchEnd()
|
||||
m_player.setStopOnEnd(m_stopOnEndBeforeScratch);
|
||||
|
||||
disconnect(m_ui->scratchWidget, &ScratchWidget::scratchSpeed, &m_player, &AudioPlayer::setSpeed);
|
||||
m_ui->horizontalSliderSpeed->setEnabled(true);
|
||||
connect(m_ui->horizontalSliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
m_ui->sliderSpeed->setEnabled(true);
|
||||
connect(m_ui->sliderSpeed, &QAbstractSlider::valueChanged, this, &TrackDeck::speedChanged);
|
||||
connect(&m_player, &AudioPlayer::playingChanged, this, &TrackDeck::updatePlayButtonText);
|
||||
}
|
||||
|
||||
@ -181,5 +221,46 @@ void TrackDeck::speedChanged(int value)
|
||||
|
||||
void TrackDeck::updatePlayButtonText(bool playing)
|
||||
{
|
||||
m_ui->pushButtonPlay->setText(playing ? tr("▮▮") : tr("▶"));
|
||||
m_ui->pushButtonBpm->setEnabled(playing);
|
||||
m_ui->pushButtonPlay->setText(playing ? tr("▮▮") : tr("▶"));
|
||||
}
|
||||
|
||||
void TrackDeck::bpmTap()
|
||||
{
|
||||
const auto position = m_player.position();
|
||||
if (m_bpmTap)
|
||||
{
|
||||
std::get<1>(*m_bpmTap) = position;
|
||||
std::get<2>(*m_bpmTap)++;
|
||||
const auto framesPerBeat = (std::get<1>(*m_bpmTap)-std::get<0>(*m_bpmTap))/std::get<2>(*m_bpmTap);
|
||||
const auto beatsPerSecond = frameRate/framesPerBeat;
|
||||
const auto bpm = 60.*beatsPerSecond;
|
||||
qDebug() << "framesPerBeat =" << framesPerBeat << "beatsPerSecond =" << beatsPerSecond << "bpm =" << bpm;
|
||||
m_ui->doubleSpinBoxBpm->setValue(bpm);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bpmTap = std::make_tuple(position, position, 0);
|
||||
}
|
||||
|
||||
m_ui->pushButtonBpm->setText(QString::number(std::get<2>(*m_bpmTap)));
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
void TrackDeck::timeout()
|
||||
{
|
||||
const auto framesPerBeat = (std::get<1>(*m_bpmTap)-std::get<0>(*m_bpmTap))/std::get<2>(*m_bpmTap);
|
||||
const auto beatsPerSecond = frameRate/framesPerBeat;
|
||||
const auto bpm = 60.*beatsPerSecond;
|
||||
qDebug() << "framesPerBeat =" << framesPerBeat << "beatsPerSecond =" << beatsPerSecond << "bpm =" << bpm;
|
||||
m_ui->pushButtonBpm->setText(tr("BPM tap"));
|
||||
m_ui->doubleSpinBoxBpm->setValue(bpm);
|
||||
for (auto *btn : m_loopGroup.buttons())
|
||||
btn->setEnabled(true);
|
||||
m_bpmTap = {};
|
||||
}
|
||||
|
||||
void TrackDeck::updatePlaybackBpm()
|
||||
{
|
||||
m_ui->labelPlaybackBpm->setText(QString::number(m_ui->doubleSpinBoxBpm->value() * m_ui->sliderSpeed->value() / 100., 'f', 2));
|
||||
}
|
||||
|
Reference in New Issue
Block a user