Add BPM detection using aubio.
This commit is contained in:
parent
c2256d8d2e
commit
66ce190098
|
|
@ -277,6 +277,13 @@ if not spdlog.found()
|
|||
spdlog = spdlog_subproject.get_variable('spdlog_dep')
|
||||
endif
|
||||
|
||||
aubio = dependency('aubio', version: '>=0.4.9', required: false)
|
||||
|
||||
if not aubio.found()
|
||||
aubio_subproject = subproject('aubio')
|
||||
aubio = aubio_subproject.get_variable('aubio_dep')
|
||||
endif
|
||||
|
||||
# Create SampleHiveConfig.hpp based on configuration
|
||||
config = configure_file(output: 'SampleHiveConfig.hpp',
|
||||
configuration: config_data,)
|
||||
|
|
@ -291,7 +298,7 @@ executable('SampleHive',
|
|||
cpp_args: [wx_cxx_flags],
|
||||
link_args: [wx_libs, link_args],
|
||||
include_directories : include_dirs,
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd, spdlog],
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd, spdlog, aubio],
|
||||
install: true,
|
||||
install_rpath: prefix / 'lib')
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ void cDatabase::CreateTableSamples()
|
|||
"SAMPLEPACK TEXT NOT NULL,"
|
||||
"TYPE TEXT NOT NULL,"
|
||||
"CHANNELS INT NOT NULL,"
|
||||
"BPM INT NOT NULL,"
|
||||
"LENGTH INT NOT NULL,"
|
||||
"SAMPLERATE INT NOT NULL,"
|
||||
"BITRATE INT NOT NULL,"
|
||||
|
|
@ -158,9 +159,9 @@ void cDatabase::InsertIntoSamples(const std::vector<Sample> &samples)
|
|||
try
|
||||
{
|
||||
const auto sql = "INSERT INTO SAMPLES (FAVORITE, FILENAME, \
|
||||
EXTENSION, SAMPLEPACK, TYPE, CHANNELS, LENGTH, \
|
||||
EXTENSION, SAMPLEPACK, TYPE, CHANNELS, BPM, LENGTH, \
|
||||
SAMPLERATE, BITRATE, PATH, TRASHED, HIVE) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
|
||||
|
||||
Sqlite3Statement statement(m_pDatabase, sql);
|
||||
|
||||
|
|
@ -192,12 +193,13 @@ void cDatabase::InsertIntoSamples(const std::vector<Sample> &samples)
|
|||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 4, sample_pack.c_str(), sample_pack.size(), SQLITE_STATIC));
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 5, type.c_str(), type.size(), SQLITE_STATIC));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 6, sample.GetChannels()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 7, sample.GetLength()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 8, sample.GetSampleRate()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 9, sample.GetBitrate()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 10, path.c_str(), path.size(), SQLITE_STATIC));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 11, sample.GetTrashed()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 12, hive.c_str(), hive.size(), SQLITE_STATIC));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 7, sample.GetBPM()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 8, sample.GetLength()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 9, sample.GetSampleRate()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 10, sample.GetBitrate()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 11, path.c_str(), path.size(), SQLITE_STATIC));
|
||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 12, sample.GetTrashed()));
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 13, hive.c_str(), hive.size(), SQLITE_STATIC));
|
||||
|
||||
sqlite3_step(statement.stmt);
|
||||
|
||||
|
|
@ -591,7 +593,7 @@ wxVector<wxVector<wxVariant>> cDatabase::LoadSamplesDatabase(wxDataViewTreeCtrl
|
|||
}
|
||||
|
||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, EXTENSION, SAMPLEPACK, \
|
||||
TYPE, CHANNELS, LENGTH, SAMPLERATE, BITRATE, PATH, \
|
||||
TYPE, CHANNELS, BPM, LENGTH, SAMPLERATE, BITRATE, PATH, \
|
||||
TRASHED, HIVE FROM SAMPLES;");
|
||||
|
||||
int row = 0;
|
||||
|
|
@ -604,14 +606,16 @@ wxVector<wxVector<wxVariant>> cDatabase::LoadSamplesDatabase(wxDataViewTreeCtrl
|
|||
wxString sample_pack = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 4)));
|
||||
int channels = sqlite3_column_int(statement.stmt, 5);
|
||||
int length = sqlite3_column_int(statement.stmt, 6);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9)));
|
||||
int trashed = sqlite3_column_int(statement.stmt, 10);
|
||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 11)));
|
||||
int bpm = sqlite3_column_int(statement.stmt, 6);
|
||||
int length = sqlite3_column_int(statement.stmt, 7);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 8);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 9);
|
||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 10)));
|
||||
int trashed = sqlite3_column_int(statement.stmt, 11);
|
||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 12)));
|
||||
|
||||
wxString len = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _length = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _bpm = SampleHive::cUtils::Get().GetBPMString(bpm);
|
||||
|
||||
wxVector<wxVariant> vec;
|
||||
vec.reserve(12);
|
||||
|
|
@ -684,7 +688,8 @@ wxVector<wxVector<wxVariant>> cDatabase::LoadSamplesDatabase(wxDataViewTreeCtrl
|
|||
vec.push_back(sample_pack);
|
||||
vec.push_back(sample_type);
|
||||
vec.push_back(wxString::Format("%d", channels));
|
||||
vec.push_back(len);
|
||||
vec.push_back(_bpm);
|
||||
vec.push_back(_length);
|
||||
vec.push_back(wxString::Format("%d", sample_rate));
|
||||
vec.push_back(wxString::Format("%d", bitrate));
|
||||
vec.push_back(path);
|
||||
|
|
@ -716,7 +721,7 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseBySampleName(const std::st
|
|||
try
|
||||
{
|
||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, SAMPLEPACK, TYPE, \
|
||||
CHANNELS, LENGTH, SAMPLERATE, BITRATE, PATH \
|
||||
CHANNELS, BPM, LENGTH, SAMPLERATE, BITRATE, PATH \
|
||||
FROM SAMPLES WHERE FILENAME LIKE '%' || ? || '%' ;");
|
||||
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 1, sampleName.c_str(), sampleName.size(), SQLITE_STATIC));
|
||||
|
|
@ -732,12 +737,14 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseBySampleName(const std::st
|
|||
wxString sample_pack = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 2))));
|
||||
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||
int channels = sqlite3_column_int(statement.stmt, 4);
|
||||
int length = sqlite3_column_int(statement.stmt, 5);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 6);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 7);
|
||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 8))));
|
||||
int bpm = sqlite3_column_int(statement.stmt, 5);
|
||||
int length = sqlite3_column_int(statement.stmt, 6);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9))));
|
||||
|
||||
wxString len = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _length = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _bpm = SampleHive::cUtils::Get().GetBPMString(bpm);
|
||||
|
||||
wxVector<wxVariant> vec;
|
||||
|
||||
|
|
@ -758,7 +765,8 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseBySampleName(const std::st
|
|||
vec.push_back(sample_pack);
|
||||
vec.push_back(sample_type);
|
||||
vec.push_back(wxString::Format("%d", channels));
|
||||
vec.push_back(len);
|
||||
vec.push_back(_bpm);
|
||||
vec.push_back(_length);
|
||||
vec.push_back(wxString::Format("%d", sample_rate));
|
||||
vec.push_back(wxString::Format("%d", bitrate));
|
||||
vec.push_back(path);
|
||||
|
|
@ -789,7 +797,7 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseByHiveName(const std::stri
|
|||
try
|
||||
{
|
||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, SAMPLEPACK, TYPE, \
|
||||
CHANNELS, LENGTH, SAMPLERATE, BITRATE, PATH \
|
||||
CHANNELS, BPM, LENGTH, SAMPLERATE, BITRATE, PATH \
|
||||
FROM SAMPLES WHERE HIVE = ? AND FAVORITE = 1;");
|
||||
|
||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 1, hiveName.c_str(), hiveName.size(), SQLITE_STATIC));
|
||||
|
|
@ -805,12 +813,14 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseByHiveName(const std::stri
|
|||
wxString sample_pack = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 2))));
|
||||
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||
int channels = sqlite3_column_int(statement.stmt, 4);
|
||||
int length = sqlite3_column_int(statement.stmt, 5);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 6);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 7);
|
||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 8))));
|
||||
int bpm = sqlite3_column_int(statement.stmt, 5);
|
||||
int length = sqlite3_column_int(statement.stmt, 6);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9))));
|
||||
|
||||
wxString len = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _length = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _bpm = SampleHive::cUtils::Get().GetBPMString(bpm);
|
||||
|
||||
wxVector<wxVariant> vec;
|
||||
|
||||
|
|
@ -827,7 +837,8 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseByHiveName(const std::stri
|
|||
vec.push_back(sample_pack);
|
||||
vec.push_back(sample_type);
|
||||
vec.push_back(wxString::Format("%d", channels));
|
||||
vec.push_back(len);
|
||||
vec.push_back(_bpm);
|
||||
vec.push_back(_length);
|
||||
vec.push_back(wxString::Format("%d", sample_rate));
|
||||
vec.push_back(wxString::Format("%d", bitrate));
|
||||
vec.push_back(path);
|
||||
|
|
@ -969,7 +980,7 @@ wxVector<wxVector<wxVariant>>cDatabase::RestoreFromTrashByFilename(const std::st
|
|||
try
|
||||
{
|
||||
const auto sql = "SELECT FAVORITE, FILENAME, EXTENSION, SAMPLEPACK, \
|
||||
TYPE, CHANNELS, LENGTH, SAMPLERATE, BITRATE, PATH, \
|
||||
TYPE, CHANNELS, BPM, LENGTH, SAMPLERATE, BITRATE, PATH, \
|
||||
TRASHED, HIVE FROM SAMPLES WHERE FILENAME = ?;";
|
||||
|
||||
Sqlite3Statement statement(m_pDatabase, sql);
|
||||
|
|
@ -984,14 +995,16 @@ wxVector<wxVector<wxVariant>>cDatabase::RestoreFromTrashByFilename(const std::st
|
|||
wxString sample_pack = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 4)));
|
||||
int channels = sqlite3_column_int(statement.stmt, 5);
|
||||
int length = sqlite3_column_int(statement.stmt, 6);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9)));
|
||||
int trashed = sqlite3_column_int(statement.stmt, 10);
|
||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 11)));
|
||||
int bpm = sqlite3_column_int(statement.stmt, 6);
|
||||
int length = sqlite3_column_int(statement.stmt, 7);
|
||||
int sample_rate = sqlite3_column_int(statement.stmt, 8);
|
||||
int bitrate = sqlite3_column_int(statement.stmt, 9);
|
||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 10)));
|
||||
int trashed = sqlite3_column_int(statement.stmt, 11);
|
||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 12)));
|
||||
|
||||
wxString len = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _length = SampleHive::cUtils::Get().CalculateAndGetISOStandardTime(length);
|
||||
wxString _bpm = SampleHive::cUtils::Get().GetBPMString(bpm);
|
||||
|
||||
wxVector<wxVariant> vec;
|
||||
|
||||
|
|
@ -1010,7 +1023,8 @@ wxVector<wxVector<wxVariant>>cDatabase::RestoreFromTrashByFilename(const std::st
|
|||
vec.push_back(sample_pack);
|
||||
vec.push_back(sample_type);
|
||||
vec.push_back(wxString::Format("%d", channels));
|
||||
vec.push_back(len);
|
||||
vec.push_back(_bpm);
|
||||
vec.push_back(_length);
|
||||
vec.push_back(wxString::Format("%d", sample_rate));
|
||||
vec.push_back(wxString::Format("%d", bitrate));
|
||||
vec.push_back(path);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,13 @@ cListCtrl::cListCtrl(wxWindow* window)
|
|||
wxDATAVIEW_COL_RESIZABLE |
|
||||
wxDATAVIEW_COL_SORTABLE |
|
||||
wxDATAVIEW_COL_REORDERABLE);
|
||||
AppendTextColumn(_("BPM"),
|
||||
wxDATAVIEW_CELL_INERT,
|
||||
80,
|
||||
wxALIGN_RIGHT,
|
||||
wxDATAVIEW_COL_RESIZABLE |
|
||||
wxDATAVIEW_COL_SORTABLE |
|
||||
wxDATAVIEW_COL_REORDERABLE);
|
||||
AppendTextColumn(_("Length"),
|
||||
wxDATAVIEW_CELL_INERT,
|
||||
80,
|
||||
|
|
@ -679,10 +686,11 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
|||
wxDataViewColumn* SamplePackColumn = this->GetColumn(2);
|
||||
wxDataViewColumn* TypeColumn = this->GetColumn(3);
|
||||
wxDataViewColumn* ChannelsColumn = this->GetColumn(4);
|
||||
wxDataViewColumn* LengthColumn = this->GetColumn(5);
|
||||
wxDataViewColumn* SampleRateColumn = this->GetColumn(6);
|
||||
wxDataViewColumn* BitrateColumn = this->GetColumn(7);
|
||||
wxDataViewColumn* PathColumn = this->GetColumn(8);
|
||||
wxDataViewColumn* BpmColumn = this->GetColumn(5);
|
||||
wxDataViewColumn* LengthColumn = this->GetColumn(6);
|
||||
wxDataViewColumn* SampleRateColumn = this->GetColumn(7);
|
||||
wxDataViewColumn* BitrateColumn = this->GetColumn(8);
|
||||
wxDataViewColumn* PathColumn = this->GetColumn(9);
|
||||
|
||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnFavorite, _("Favorites"),
|
||||
_("Toggle favorites column"))->Check(FavoriteColumn->IsShown());
|
||||
|
|
@ -694,6 +702,8 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
|||
_("Toggle type column"))->Check(TypeColumn->IsShown());
|
||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnChannels, _("Channels"),
|
||||
_("Toggle channels column"))->Check(ChannelsColumn->IsShown());
|
||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnBPM, _("BPM"),
|
||||
_("Toggle length column"))->Check(BpmColumn->IsShown());
|
||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnLength, _("Length"),
|
||||
_("Toggle length column"))->Check(LengthColumn->IsShown());
|
||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnSampleRate, _("Sample Rate"),
|
||||
|
|
@ -720,6 +730,9 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
|||
case SampleHive::ID::MN_ColumnChannels:
|
||||
ChannelsColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnChannels));
|
||||
break;
|
||||
case SampleHive::ID::MN_ColumnBPM:
|
||||
BpmColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnBPM));
|
||||
break;
|
||||
case SampleHive::ID::MN_ColumnLength:
|
||||
LengthColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnLength));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -914,6 +914,13 @@ void cMainFrame::PlaySample(const std::string& filepath, const std::string& samp
|
|||
if (!m_pMediaCtrl->Play())
|
||||
SH_LOG_ERROR("Error! Cannot play sample.");
|
||||
|
||||
// ====================================================
|
||||
// TODO: Remove these lines (for debugging only)
|
||||
float bpm = SampleHive::cUtils::Get().GetBPM(filepath);
|
||||
wxString bpm_str = SampleHive::cUtils::Get().GetBPMString(bpm);
|
||||
SH_LOG_DEBUG("BPM: {}, BPM_STR: {}", bpm, bpm_str);
|
||||
// ====================================================
|
||||
|
||||
PushStatusText(wxString::Format(_("Now playing: %s"), sample), 1);
|
||||
|
||||
if (!m_pTimer->IsRunning())
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ class cWaveformViewer : public wxPanel
|
|||
// -------------------------------------------------------------------
|
||||
std::pair<double, double> CalculateLoopPoints();
|
||||
|
||||
float GetBPM(const std::string& path);
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
void ResetBitmapDC();
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ namespace SampleHive { namespace ID {
|
|||
MN_ColumnSamplePack,
|
||||
MN_ColumnType,
|
||||
MN_ColumnChannels,
|
||||
MN_ColumnBPM,
|
||||
MN_ColumnLength,
|
||||
MN_ColumnSampleRate,
|
||||
MN_ColumnBitrate,
|
||||
|
|
|
|||
|
|
@ -36,11 +36,10 @@ Sample::Sample()
|
|||
|
||||
///Overloaded Constructor, Creates a sample profile with supplied data. @see Set()
|
||||
Sample::Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
||||
int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||
int length, int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||
{
|
||||
Set(favorite, filename, fileExtension, samplePack, type,
|
||||
channels, length, sampleRate, bitrate, path, trashed);
|
||||
Set(favorite, filename, fileExtension, samplePack, type, channels, bpm, length, sampleRate, bitrate, path, trashed);
|
||||
}
|
||||
|
||||
///Clears all sample data
|
||||
|
|
@ -48,6 +47,7 @@ void Sample::Clear()
|
|||
{
|
||||
m_Favorite = 0;
|
||||
m_Channels = 0;
|
||||
m_BPM = 0;
|
||||
m_Length = 0;
|
||||
m_SampleRate = 0;
|
||||
m_Bitrate = 0;
|
||||
|
|
@ -60,8 +60,8 @@ void Sample::Clear()
|
|||
}
|
||||
|
||||
void Sample::Set(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
||||
int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||
int length, int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||
{
|
||||
m_Favorite = favorite;
|
||||
m_Filename = filename;
|
||||
|
|
@ -69,6 +69,7 @@ void Sample::Set(int favorite, const std::string& filename, const std::string& f
|
|||
m_SamplePack = samplePack;
|
||||
m_Type = type;
|
||||
m_Channels = channels;
|
||||
m_BPM = bpm;
|
||||
m_Length = length;
|
||||
m_SampleRate = sampleRate;
|
||||
m_Bitrate = bitrate;
|
||||
|
|
|
|||
|
|
@ -40,13 +40,14 @@ class Sample
|
|||
public:
|
||||
Sample();
|
||||
Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
||||
int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||
int length, int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
int m_Favorite = 0;
|
||||
int m_Channels = 0;
|
||||
int m_BPM = 0;
|
||||
int m_Length = 0;
|
||||
int m_SampleRate = 0;
|
||||
int m_Bitrate = 0;
|
||||
|
|
@ -62,6 +63,7 @@ class Sample
|
|||
// Getters
|
||||
int GetFavorite() const { return m_Favorite; }
|
||||
int GetChannels() const { return m_Channels; }
|
||||
int GetBPM() const { return m_BPM; }
|
||||
int GetLength() const { return m_Length; }
|
||||
int GetSampleRate() const { return m_SampleRate; }
|
||||
int GetBitrate() const { return m_Bitrate; }
|
||||
|
|
@ -75,11 +77,12 @@ class Sample
|
|||
// -------------------------------------------------------------------
|
||||
// Setters
|
||||
void Set(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
||||
int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||
int length, int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||
|
||||
void SetFavorite(int favorite) { m_Favorite = favorite; }
|
||||
void SetChannels(int channels) { m_Channels = channels; }
|
||||
void SetBPM(int bpm) { m_BPM = bpm; }
|
||||
void SetLength(int length) { m_Length = length; }
|
||||
void SetSampleRate(int sampleRate) { m_SampleRate = sampleRate; }
|
||||
void SetBitrate(int bitrate) { m_Bitrate = bitrate; }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Database/Database.hpp"
|
||||
#include "Utility/HiveData.hpp"
|
||||
#include "Utility/Log.hpp"
|
||||
|
|
@ -32,6 +34,8 @@
|
|||
#include <wx/progdlg.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <aubio/aubio.h>
|
||||
|
||||
namespace SampleHive {
|
||||
|
||||
SampleHive::cUtils::FileInfo SampleHive::cUtils::GetFilenamePathAndExtension(const wxString& selected,
|
||||
|
|
@ -75,6 +79,9 @@ namespace SampleHive {
|
|||
std::string extension;
|
||||
std::string filename;
|
||||
|
||||
float bpm = 0.0f;
|
||||
float key = 0.0f;
|
||||
|
||||
//Check All Files At Once
|
||||
wxArrayString sorted_files;
|
||||
|
||||
|
|
@ -110,6 +117,8 @@ namespace SampleHive {
|
|||
filename = serializer.DeserializeShowFileExtension() ?
|
||||
filename_with_extension : filename_without_extension;
|
||||
|
||||
bpm = GetBPM(path);
|
||||
|
||||
Sample sample;
|
||||
|
||||
sample.SetPath(path);
|
||||
|
|
@ -122,11 +131,13 @@ namespace SampleHive {
|
|||
|
||||
sample.SetSamplePack(artist);
|
||||
sample.SetChannels(tags.GetAudioInfo().channels);
|
||||
sample.SetBPM(static_cast<int>(bpm));
|
||||
sample.SetLength(tags.GetAudioInfo().length);
|
||||
sample.SetSampleRate(tags.GetAudioInfo().sample_rate);
|
||||
sample.SetBitrate(tags.GetAudioInfo().bitrate);
|
||||
|
||||
wxString length = CalculateAndGetISOStandardTime(sample.GetLength());
|
||||
wxString bpm_str = GetBPMString(sample.GetBPM());
|
||||
|
||||
wxVector<wxVariant> data;
|
||||
|
||||
|
|
@ -140,6 +151,7 @@ namespace SampleHive {
|
|||
data.push_back(sample.GetSamplePack());
|
||||
data.push_back("");
|
||||
data.push_back(wxString::Format("%d", sample.GetChannels()));
|
||||
data.push_back(bpm_str);
|
||||
data.push_back(length);
|
||||
data.push_back(wxString::Format("%d", sample.GetSampleRate()));
|
||||
data.push_back(wxString::Format("%d", sample.GetBitrate()));
|
||||
|
|
@ -249,4 +261,72 @@ namespace SampleHive {
|
|||
return iso_length;
|
||||
}
|
||||
|
||||
wxString cUtils::GetBPMString(float bpm)
|
||||
{
|
||||
return wxString::Format("%d", static_cast<int>(bpm));
|
||||
}
|
||||
|
||||
float cUtils::GetBPM(const std::string& path)
|
||||
{
|
||||
uint_t buff_size = 1024, hop_size = buff_size / 2, frames = 0, samplerate = 0, read = 0;
|
||||
aubio_tempo_t* tempo;
|
||||
fvec_t* in, *out;
|
||||
aubio_source_t* source = new_aubio_source(path.c_str(), samplerate, hop_size);
|
||||
|
||||
float bpm = 0.0f;
|
||||
|
||||
if (!source)
|
||||
return 0.0f;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
if (samplerate == 0)
|
||||
samplerate = aubio_source_get_samplerate(source);
|
||||
|
||||
tempo = new_aubio_tempo("default", buff_size, hop_size, samplerate);
|
||||
|
||||
if (!tempo)
|
||||
return 0.0f;
|
||||
|
||||
in = new_fvec(hop_size);
|
||||
out = new_fvec(1);
|
||||
|
||||
do
|
||||
{
|
||||
// put some fresh data in input vector
|
||||
aubio_source_do(source, in, &read);
|
||||
|
||||
// execute tempo
|
||||
aubio_tempo_do(tempo, in, out);
|
||||
|
||||
// do something with the beats
|
||||
// if (out->data[0] != 0)
|
||||
// {
|
||||
// SH_LOG_DEBUG("Track: {} Beat at {}s, {}s, frame {}, {} bpm with confidence {}",
|
||||
// path, aubio_tempo_get_last_ms(tempo), aubio_tempo_get_last_s(tempo),
|
||||
// aubio_tempo_get_last(tempo), aubio_tempo_get_bpm(tempo),
|
||||
// aubio_tempo_get_confidence(tempo));
|
||||
// }
|
||||
|
||||
frames += read;
|
||||
bpm = aubio_tempo_get_bpm(tempo);
|
||||
}
|
||||
while (read == hop_size);
|
||||
|
||||
// clean up memory
|
||||
del_aubio_tempo(tempo);
|
||||
del_fvec(in);
|
||||
del_fvec(out);
|
||||
del_aubio_source(source);
|
||||
aubio_cleanup();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
SH_LOG_ERROR("Aubio Error! {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
return bpm;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ namespace SampleHive {
|
|||
void AddSamples(wxArrayString& files, wxWindow* parent);
|
||||
void OnAutoImportDir(const wxString& pathToDirectory, wxWindow* parent);
|
||||
wxString CalculateAndGetISOStandardTime(wxLongLong length);
|
||||
wxString GetBPMString(float bpm);
|
||||
|
||||
float GetBPM(const std::string& path);
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue