Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

preliminary work for SoundTouch BPM detection #6

Open
wants to merge 6 commits into
base: BASS_removed
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ matrix:
packages:
- qt5-default
- qtbase5-dev-tools
- qtmultimedia5-dev
- qt5-qmake
- libtag1-dev
- libsoundtouch-dev
- os: osx
osx_image: xcode8.2
compiler: clang
Expand All @@ -28,6 +30,8 @@ install:
brew install qt5;
brew link --force qt5;
brew install taglib;
brew install sound-touch;
brew link sound-touch;
fi

before_script:
Expand Down
71 changes: 16 additions & 55 deletions src/QUMainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@
#include <QTemporaryFile>
#include <QDebug>

#include <aubio.h>
#include <QMultimedia>


QUMainWindow::QUMainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::QUMainWindow) {
_player = new QMediaPlayer;
_player = new QMediaPlayer;
ui->setupUi(this);

connect( &bpm, SIGNAL( bpmDetected( double ) ),
ui->doubleSpinBox_BPM , SLOT( setValue( double ) ) );

initWindow();
initRibbonBar();

Expand Down Expand Up @@ -979,60 +983,17 @@ void QUMainWindow::handleMP3() {
ui->comboBox_Video->setCurrentIndex(1);
}

// fixme/todo: determine BPM from MP3 with some open source library
uint_t samplerate = 0;
uint_t win_size = 2048; // window size
uint_t hop_size = win_size / 2;
uint_t n_frames = 0;
uint_t read = 0;
smpl_t max_confidence = 0.;
smpl_t current_confidence = 0.;
smpl_t current_bpm = 0;
smpl_t bpm_with_max_confidence = 0;

aubio_source_t *source = new_aubio_source(fileInfo_MP3->absoluteFilePath().toStdString().c_str(), samplerate, hop_size);
if(source) {
samplerate = aubio_source_get_samplerate(source);

// create some vectors
fvec_t *in = new_fvec(hop_size); // input audio buffer
fvec_t *out = new_fvec(1); // output position
// create tempo object
aubio_tempo_t *o = new_aubio_tempo("default", win_size, hop_size, samplerate);
do {
// put some fresh data in input vector
aubio_source_do(source, in, &read);
// execute tempo
aubio_tempo_do(o, in, out);
// do something with the beats
if (out->data[0] != 0) {
current_confidence = aubio_tempo_get_confidence(o);
current_bpm = aubio_tempo_get_bpm(o);
if(current_confidence > max_confidence) {
max_confidence = current_confidence;
bpm_with_max_confidence = current_bpm;
}
//qDebug() << QString("beat at %1 s, frame %2, %3 bpm with confidence %4\n").arg(QString::number(aubio_tempo_get_last_s(o), 'f', 3)).arg(QString::number(aubio_tempo_get_last(o))).arg(QString::number(current_bpm, 'f', 2)).arg(QString::number(current_confidence, 'f', 2));
}
n_frames += read;
} while (read == hop_size);
//qDebug() << QString("read %1 s, %2 frames at %3 Hz (%4 blocks) from %5\n").arg(QString::number(n_frames * 1. / samplerate, 'f', 2)).arg(QString::number(n_frames)).arg(QString::number(samplerate)).arg(QString::number(n_frames / hop_size)).arg(QString(fileInfo_MP3->absoluteFilePath().toStdString().c_str()));
//qDebug() << QString("%1 bpm with confidence %2\n").arg(QString::number(bpm_with_max_confidence)).arg(QString::number(max_confidence));

// clean up memory
del_aubio_tempo(o);
del_fvec(in);
del_fvec(out);
del_aubio_source(source);
} else {
qDebug() << "Error opening audio file to determine BPM.";
aubio_cleanup();
}
//FIXME:Enetheru determine BPM from MP3 with some open source library
QAudioFormat format;
format.setChannelCount( 2 );
format.setCodec( "audio/x-raw" );
format.setSampleType( QAudioFormat::Float );
format.setSampleRate( 48000 );
format.setSampleSize( 32 );

BPMFromMP3 = bpm_with_max_confidence;
//qDebug() << "BPMFromMP3 = " << BPMFromMP3;
BPM = BPMFromMP3*4; // quarter beats per minute
//qDebug() << "BPM = " << BPM;
bpm.setAudioFormat( format );
bpm.setSourceFilename( fileInfo_MP3->filePath() );
bpm.start();


ui->doubleSpinBox_BPM->setValue(BPM);
Expand Down
6 changes: 5 additions & 1 deletion src/QUMainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

#include "taglib.h"
#include "fileref.h"
#include "bpmdetect.h"

#include <QMainWindow>
#include <QTime>
#include <QProgressBar>
#include <QFileInfo>
#include <QMediaPlayer>
#include <QAudioDecoder>
#include <QAudioFormat>

class QURibbonBar;

Expand All @@ -22,7 +25,7 @@ class QUMainWindow: public QMainWindow, private Ui::QUMainWindow {
Q_OBJECT

public:
QUMainWindow(QWidget *parent = 0);
QUMainWindow(QWidget *parent = nullptr);

protected:
virtual void closeEvent(QCloseEvent *event);
Expand Down Expand Up @@ -151,6 +154,7 @@ private slots:
QMap<double, QString> timeLineMap;
void updateOutputLyrics();
QMediaPlayer* _player;
BPMDetect bpm;
};

#endif // QCMAINWINDOW_H
8 changes: 6 additions & 2 deletions src/UltraStar-Creator.pro
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ HEADERS += main.h \
song/QUSongInterface.h \
song/QUSongFile.h \
song/QUSongDatabase.h \
QUStringSupport.h
QUStringSupport.h \
bpmdetect.h

SOURCES += main.cpp \
QUMainWindow.cpp \
Expand All @@ -52,7 +53,8 @@ SOURCES += main.cpp \
song/QUSongLine.cpp \
song/QUSongFile.cpp \
song/QUSongDatabase.cpp \
QUStringSupport.cpp
QUStringSupport.cpp \
bpmdetect.cpp

FORMS += QUMainWindow.ui \
QUAboutDialog.ui \
Expand Down Expand Up @@ -102,6 +104,8 @@ unix:!macx {
CONFIG += link_pkgconfig
PKGCONFIG += taglib

LIBS += -lSoundTouch

QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN/lib\''
}

Expand Down
57 changes: 57 additions & 0 deletions src/bpmdetect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "bpmdetect.h"

#include <QApplication>
#include <QAudioDecoder>
#include <QFileInfo>

BPMDetect::BPMDetect( QObject *parent ) :
QAudioDecoder( parent )
{
connect( this, SIGNAL( bufferReady() ), this, SLOT( on_bufferReady() ) );
connect( this, SIGNAL( finished() ), this, SLOT( on_finished() ) );
}

BPMDetect::~BPMDetect()
{
if( bpm )delete bpm;
}

void
BPMDetect::on_bufferReady()
{
while( bufferAvailable() )
{
auto buf = read();
if( buf.format().sampleType() != QAudioFormat::Float ){
qDebug() << "invalid sampleType";
return;
}
if( bpm == nullptr ){
qDebug() << "creating new BPMDetect using:";
qDebug() << buf.format();
bpm = new soundtouch::BPMDetect(
buf.format().channelCount(),
buf.format().sampleRate() );
}
bpm->inputSamples(
static_cast< float *>( buf.data() ),
buf.sampleCount() / buf.format().channelCount()
);
}
}

void
BPMDetect::on_finished()
{
qDebug() << "on_finished";
auto bpmValue = bpm->getBpm();
delete bpm; bpm = nullptr;

if (bpmValue > 0){
qDebug() << "Detected BPM rate: " << bpmValue;
emit bpmDetected( bpmValue );
}
else qDebug("Couldn't detect BPM rate.");

return;
}
28 changes: 28 additions & 0 deletions src/bpmdetect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef BPMDETECT_H
#define BPMDETECT_H

#include <QAudioDecoder>

#include <soundtouch/BPMDetect.h>


class BPMDetect : public QAudioDecoder
{
Q_OBJECT

public:
explicit BPMDetect( QObject *parent = nullptr);
~BPMDetect();

signals:
void bpmDetected( double value );

public slots:
void on_bufferReady();
void on_finished();

private://state
soundtouch::BPMDetect *bpm = nullptr;
};

#endif // BPMDETECT_H