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')
|
spdlog = spdlog_subproject.get_variable('spdlog_dep')
|
||||||
endif
|
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
|
# Create SampleHiveConfig.hpp based on configuration
|
||||||
config = configure_file(output: 'SampleHiveConfig.hpp',
|
config = configure_file(output: 'SampleHiveConfig.hpp',
|
||||||
configuration: config_data,)
|
configuration: config_data,)
|
||||||
|
|
@ -291,7 +298,7 @@ executable('SampleHive',
|
||||||
cpp_args: [wx_cxx_flags],
|
cpp_args: [wx_cxx_flags],
|
||||||
link_args: [wx_libs, link_args],
|
link_args: [wx_libs, link_args],
|
||||||
include_directories : include_dirs,
|
include_directories : include_dirs,
|
||||||
dependencies: [wx, taglib, sqlite3, yaml, snd, spdlog],
|
dependencies: [wx, taglib, sqlite3, yaml, snd, spdlog, aubio],
|
||||||
install: true,
|
install: true,
|
||||||
install_rpath: prefix / 'lib')
|
install_rpath: prefix / 'lib')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ void cDatabase::CreateTableSamples()
|
||||||
"SAMPLEPACK TEXT NOT NULL,"
|
"SAMPLEPACK TEXT NOT NULL,"
|
||||||
"TYPE TEXT NOT NULL,"
|
"TYPE TEXT NOT NULL,"
|
||||||
"CHANNELS INT NOT NULL,"
|
"CHANNELS INT NOT NULL,"
|
||||||
|
"BPM INT NOT NULL,"
|
||||||
"LENGTH INT NOT NULL,"
|
"LENGTH INT NOT NULL,"
|
||||||
"SAMPLERATE INT NOT NULL,"
|
"SAMPLERATE INT NOT NULL,"
|
||||||
"BITRATE INT NOT NULL,"
|
"BITRATE INT NOT NULL,"
|
||||||
|
|
@ -158,9 +159,9 @@ void cDatabase::InsertIntoSamples(const std::vector<Sample> &samples)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto sql = "INSERT INTO SAMPLES (FAVORITE, FILENAME, \
|
const auto sql = "INSERT INTO SAMPLES (FAVORITE, FILENAME, \
|
||||||
EXTENSION, SAMPLEPACK, TYPE, CHANNELS, LENGTH, \
|
EXTENSION, SAMPLEPACK, TYPE, CHANNELS, BPM, LENGTH, \
|
||||||
SAMPLERATE, BITRATE, PATH, TRASHED, HIVE) \
|
SAMPLERATE, BITRATE, PATH, TRASHED, HIVE) \
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
|
||||||
|
|
||||||
Sqlite3Statement statement(m_pDatabase, sql);
|
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, 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_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, 6, sample.GetChannels()));
|
||||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 7, sample.GetLength()));
|
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 7, sample.GetBPM()));
|
||||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 8, sample.GetSampleRate()));
|
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 8, sample.GetLength()));
|
||||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 9, sample.GetBitrate()));
|
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 9, sample.GetSampleRate()));
|
||||||
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, 10, sample.GetBitrate()));
|
||||||
throw_on_sqlite3_error(sqlite3_bind_int(statement.stmt, 11, sample.GetTrashed()));
|
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 11, path.c_str(), path.size(), SQLITE_STATIC));
|
||||||
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, 12, sample.GetTrashed()));
|
||||||
|
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 13, hive.c_str(), hive.size(), SQLITE_STATIC));
|
||||||
|
|
||||||
sqlite3_step(statement.stmt);
|
sqlite3_step(statement.stmt);
|
||||||
|
|
||||||
|
|
@ -591,7 +593,7 @@ wxVector<wxVector<wxVariant>> cDatabase::LoadSamplesDatabase(wxDataViewTreeCtrl
|
||||||
}
|
}
|
||||||
|
|
||||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, EXTENSION, SAMPLEPACK, \
|
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;");
|
TRASHED, HIVE FROM SAMPLES;");
|
||||||
|
|
||||||
int row = 0;
|
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_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)));
|
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 4)));
|
||||||
int channels = sqlite3_column_int(statement.stmt, 5);
|
int channels = sqlite3_column_int(statement.stmt, 5);
|
||||||
int length = sqlite3_column_int(statement.stmt, 6);
|
int bpm = sqlite3_column_int(statement.stmt, 6);
|
||||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
int length = sqlite3_column_int(statement.stmt, 7);
|
||||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
int sample_rate = sqlite3_column_int(statement.stmt, 8);
|
||||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9)));
|
int bitrate = sqlite3_column_int(statement.stmt, 9);
|
||||||
int trashed = sqlite3_column_int(statement.stmt, 10);
|
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 10)));
|
||||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 11)));
|
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;
|
wxVector<wxVariant> vec;
|
||||||
vec.reserve(12);
|
vec.reserve(12);
|
||||||
|
|
@ -684,7 +688,8 @@ wxVector<wxVector<wxVariant>> cDatabase::LoadSamplesDatabase(wxDataViewTreeCtrl
|
||||||
vec.push_back(sample_pack);
|
vec.push_back(sample_pack);
|
||||||
vec.push_back(sample_type);
|
vec.push_back(sample_type);
|
||||||
vec.push_back(wxString::Format("%d", channels));
|
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", sample_rate));
|
||||||
vec.push_back(wxString::Format("%d", bitrate));
|
vec.push_back(wxString::Format("%d", bitrate));
|
||||||
vec.push_back(path);
|
vec.push_back(path);
|
||||||
|
|
@ -716,7 +721,7 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseBySampleName(const std::st
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, SAMPLEPACK, TYPE, \
|
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 '%' || ? || '%' ;");
|
FROM SAMPLES WHERE FILENAME LIKE '%' || ? || '%' ;");
|
||||||
|
|
||||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 1, sampleName.c_str(), sampleName.size(), SQLITE_STATIC));
|
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_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)));
|
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||||
int channels = sqlite3_column_int(statement.stmt, 4);
|
int channels = sqlite3_column_int(statement.stmt, 4);
|
||||||
int length = sqlite3_column_int(statement.stmt, 5);
|
int bpm = sqlite3_column_int(statement.stmt, 5);
|
||||||
int sample_rate = sqlite3_column_int(statement.stmt, 6);
|
int length = sqlite3_column_int(statement.stmt, 6);
|
||||||
int bitrate = sqlite3_column_int(statement.stmt, 7);
|
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 8))));
|
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;
|
wxVector<wxVariant> vec;
|
||||||
|
|
||||||
|
|
@ -758,7 +765,8 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseBySampleName(const std::st
|
||||||
vec.push_back(sample_pack);
|
vec.push_back(sample_pack);
|
||||||
vec.push_back(sample_type);
|
vec.push_back(sample_type);
|
||||||
vec.push_back(wxString::Format("%d", channels));
|
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", sample_rate));
|
||||||
vec.push_back(wxString::Format("%d", bitrate));
|
vec.push_back(wxString::Format("%d", bitrate));
|
||||||
vec.push_back(path);
|
vec.push_back(path);
|
||||||
|
|
@ -789,7 +797,7 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseByHiveName(const std::stri
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Sqlite3Statement statement(m_pDatabase, "SELECT FAVORITE, FILENAME, SAMPLEPACK, TYPE, \
|
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;");
|
FROM SAMPLES WHERE HIVE = ? AND FAVORITE = 1;");
|
||||||
|
|
||||||
throw_on_sqlite3_error(sqlite3_bind_text(statement.stmt, 1, hiveName.c_str(), hiveName.size(), SQLITE_STATIC));
|
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_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)));
|
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 3)));
|
||||||
int channels = sqlite3_column_int(statement.stmt, 4);
|
int channels = sqlite3_column_int(statement.stmt, 4);
|
||||||
int length = sqlite3_column_int(statement.stmt, 5);
|
int bpm = sqlite3_column_int(statement.stmt, 5);
|
||||||
int sample_rate = sqlite3_column_int(statement.stmt, 6);
|
int length = sqlite3_column_int(statement.stmt, 6);
|
||||||
int bitrate = sqlite3_column_int(statement.stmt, 7);
|
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
||||||
wxString path = wxString(std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 8))));
|
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;
|
wxVector<wxVariant> vec;
|
||||||
|
|
||||||
|
|
@ -827,7 +837,8 @@ wxVector<wxVector<wxVariant>>cDatabase::FilterDatabaseByHiveName(const std::stri
|
||||||
vec.push_back(sample_pack);
|
vec.push_back(sample_pack);
|
||||||
vec.push_back(sample_type);
|
vec.push_back(sample_type);
|
||||||
vec.push_back(wxString::Format("%d", channels));
|
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", sample_rate));
|
||||||
vec.push_back(wxString::Format("%d", bitrate));
|
vec.push_back(wxString::Format("%d", bitrate));
|
||||||
vec.push_back(path);
|
vec.push_back(path);
|
||||||
|
|
@ -969,7 +980,7 @@ wxVector<wxVector<wxVariant>>cDatabase::RestoreFromTrashByFilename(const std::st
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto sql = "SELECT FAVORITE, FILENAME, EXTENSION, SAMPLEPACK, \
|
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 = ?;";
|
TRASHED, HIVE FROM SAMPLES WHERE FILENAME = ?;";
|
||||||
|
|
||||||
Sqlite3Statement statement(m_pDatabase, sql);
|
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_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)));
|
wxString sample_type = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 4)));
|
||||||
int channels = sqlite3_column_int(statement.stmt, 5);
|
int channels = sqlite3_column_int(statement.stmt, 5);
|
||||||
int length = sqlite3_column_int(statement.stmt, 6);
|
int bpm = sqlite3_column_int(statement.stmt, 6);
|
||||||
int sample_rate = sqlite3_column_int(statement.stmt, 7);
|
int length = sqlite3_column_int(statement.stmt, 7);
|
||||||
int bitrate = sqlite3_column_int(statement.stmt, 8);
|
int sample_rate = sqlite3_column_int(statement.stmt, 8);
|
||||||
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 9)));
|
int bitrate = sqlite3_column_int(statement.stmt, 9);
|
||||||
int trashed = sqlite3_column_int(statement.stmt, 10);
|
wxString path = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 10)));
|
||||||
wxString hive_name = std::string(reinterpret_cast<const char*>(sqlite3_column_text(statement.stmt, 11)));
|
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;
|
wxVector<wxVariant> vec;
|
||||||
|
|
||||||
|
|
@ -1010,7 +1023,8 @@ wxVector<wxVector<wxVariant>>cDatabase::RestoreFromTrashByFilename(const std::st
|
||||||
vec.push_back(sample_pack);
|
vec.push_back(sample_pack);
|
||||||
vec.push_back(sample_type);
|
vec.push_back(sample_type);
|
||||||
vec.push_back(wxString::Format("%d", channels));
|
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", sample_rate));
|
||||||
vec.push_back(wxString::Format("%d", bitrate));
|
vec.push_back(wxString::Format("%d", bitrate));
|
||||||
vec.push_back(path);
|
vec.push_back(path);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,13 @@ cListCtrl::cListCtrl(wxWindow* window)
|
||||||
wxDATAVIEW_COL_RESIZABLE |
|
wxDATAVIEW_COL_RESIZABLE |
|
||||||
wxDATAVIEW_COL_SORTABLE |
|
wxDATAVIEW_COL_SORTABLE |
|
||||||
wxDATAVIEW_COL_REORDERABLE);
|
wxDATAVIEW_COL_REORDERABLE);
|
||||||
|
AppendTextColumn(_("BPM"),
|
||||||
|
wxDATAVIEW_CELL_INERT,
|
||||||
|
80,
|
||||||
|
wxALIGN_RIGHT,
|
||||||
|
wxDATAVIEW_COL_RESIZABLE |
|
||||||
|
wxDATAVIEW_COL_SORTABLE |
|
||||||
|
wxDATAVIEW_COL_REORDERABLE);
|
||||||
AppendTextColumn(_("Length"),
|
AppendTextColumn(_("Length"),
|
||||||
wxDATAVIEW_CELL_INERT,
|
wxDATAVIEW_CELL_INERT,
|
||||||
80,
|
80,
|
||||||
|
|
@ -679,10 +686,11 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
||||||
wxDataViewColumn* SamplePackColumn = this->GetColumn(2);
|
wxDataViewColumn* SamplePackColumn = this->GetColumn(2);
|
||||||
wxDataViewColumn* TypeColumn = this->GetColumn(3);
|
wxDataViewColumn* TypeColumn = this->GetColumn(3);
|
||||||
wxDataViewColumn* ChannelsColumn = this->GetColumn(4);
|
wxDataViewColumn* ChannelsColumn = this->GetColumn(4);
|
||||||
wxDataViewColumn* LengthColumn = this->GetColumn(5);
|
wxDataViewColumn* BpmColumn = this->GetColumn(5);
|
||||||
wxDataViewColumn* SampleRateColumn = this->GetColumn(6);
|
wxDataViewColumn* LengthColumn = this->GetColumn(6);
|
||||||
wxDataViewColumn* BitrateColumn = this->GetColumn(7);
|
wxDataViewColumn* SampleRateColumn = this->GetColumn(7);
|
||||||
wxDataViewColumn* PathColumn = this->GetColumn(8);
|
wxDataViewColumn* BitrateColumn = this->GetColumn(8);
|
||||||
|
wxDataViewColumn* PathColumn = this->GetColumn(9);
|
||||||
|
|
||||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnFavorite, _("Favorites"),
|
menu.AppendCheckItem(SampleHive::ID::MN_ColumnFavorite, _("Favorites"),
|
||||||
_("Toggle favorites column"))->Check(FavoriteColumn->IsShown());
|
_("Toggle favorites column"))->Check(FavoriteColumn->IsShown());
|
||||||
|
|
@ -694,6 +702,8 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
||||||
_("Toggle type column"))->Check(TypeColumn->IsShown());
|
_("Toggle type column"))->Check(TypeColumn->IsShown());
|
||||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnChannels, _("Channels"),
|
menu.AppendCheckItem(SampleHive::ID::MN_ColumnChannels, _("Channels"),
|
||||||
_("Toggle channels column"))->Check(ChannelsColumn->IsShown());
|
_("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"),
|
menu.AppendCheckItem(SampleHive::ID::MN_ColumnLength, _("Length"),
|
||||||
_("Toggle length column"))->Check(LengthColumn->IsShown());
|
_("Toggle length column"))->Check(LengthColumn->IsShown());
|
||||||
menu.AppendCheckItem(SampleHive::ID::MN_ColumnSampleRate, _("Sample Rate"),
|
menu.AppendCheckItem(SampleHive::ID::MN_ColumnSampleRate, _("Sample Rate"),
|
||||||
|
|
@ -720,6 +730,9 @@ void cListCtrl::OnShowLibraryColumnHeaderContextMenu(wxDataViewEvent& event)
|
||||||
case SampleHive::ID::MN_ColumnChannels:
|
case SampleHive::ID::MN_ColumnChannels:
|
||||||
ChannelsColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnChannels));
|
ChannelsColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnChannels));
|
||||||
break;
|
break;
|
||||||
|
case SampleHive::ID::MN_ColumnBPM:
|
||||||
|
BpmColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnBPM));
|
||||||
|
break;
|
||||||
case SampleHive::ID::MN_ColumnLength:
|
case SampleHive::ID::MN_ColumnLength:
|
||||||
LengthColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnLength));
|
LengthColumn->SetHidden(!menu.IsChecked(SampleHive::ID::MN_ColumnLength));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -914,6 +914,13 @@ void cMainFrame::PlaySample(const std::string& filepath, const std::string& samp
|
||||||
if (!m_pMediaCtrl->Play())
|
if (!m_pMediaCtrl->Play())
|
||||||
SH_LOG_ERROR("Error! Cannot play sample.");
|
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);
|
PushStatusText(wxString::Format(_("Now playing: %s"), sample), 1);
|
||||||
|
|
||||||
if (!m_pTimer->IsRunning())
|
if (!m_pTimer->IsRunning())
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ class cWaveformViewer : public wxPanel
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
std::pair<double, double> CalculateLoopPoints();
|
std::pair<double, double> CalculateLoopPoints();
|
||||||
|
|
||||||
|
float GetBPM(const std::string& path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
void ResetBitmapDC();
|
void ResetBitmapDC();
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ namespace SampleHive { namespace ID {
|
||||||
MN_ColumnSamplePack,
|
MN_ColumnSamplePack,
|
||||||
MN_ColumnType,
|
MN_ColumnType,
|
||||||
MN_ColumnChannels,
|
MN_ColumnChannels,
|
||||||
|
MN_ColumnBPM,
|
||||||
MN_ColumnLength,
|
MN_ColumnLength,
|
||||||
MN_ColumnSampleRate,
|
MN_ColumnSampleRate,
|
||||||
MN_ColumnBitrate,
|
MN_ColumnBitrate,
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,10 @@ Sample::Sample()
|
||||||
|
|
||||||
///Overloaded Constructor, Creates a sample profile with supplied data. @see Set()
|
///Overloaded Constructor, Creates a sample profile with supplied data. @see Set()
|
||||||
Sample::Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
Sample::Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||||
int sampleRate, int bitrate, const std::string& path, int trashed)
|
int length, int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||||
{
|
{
|
||||||
Set(favorite, filename, fileExtension, samplePack, type,
|
Set(favorite, filename, fileExtension, samplePack, type, channels, bpm, length, sampleRate, bitrate, path, trashed);
|
||||||
channels, length, sampleRate, bitrate, path, trashed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Clears all sample data
|
///Clears all sample data
|
||||||
|
|
@ -48,6 +47,7 @@ void Sample::Clear()
|
||||||
{
|
{
|
||||||
m_Favorite = 0;
|
m_Favorite = 0;
|
||||||
m_Channels = 0;
|
m_Channels = 0;
|
||||||
|
m_BPM = 0;
|
||||||
m_Length = 0;
|
m_Length = 0;
|
||||||
m_SampleRate = 0;
|
m_SampleRate = 0;
|
||||||
m_Bitrate = 0;
|
m_Bitrate = 0;
|
||||||
|
|
@ -60,8 +60,8 @@ void Sample::Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sample::Set(int favorite, const std::string& filename, const std::string& fileExtension,
|
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,
|
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||||
int sampleRate, int bitrate, const std::string& path, int trashed)
|
int length, int sampleRate, int bitrate, const std::string& path, int trashed)
|
||||||
{
|
{
|
||||||
m_Favorite = favorite;
|
m_Favorite = favorite;
|
||||||
m_Filename = filename;
|
m_Filename = filename;
|
||||||
|
|
@ -69,6 +69,7 @@ void Sample::Set(int favorite, const std::string& filename, const std::string& f
|
||||||
m_SamplePack = samplePack;
|
m_SamplePack = samplePack;
|
||||||
m_Type = type;
|
m_Type = type;
|
||||||
m_Channels = channels;
|
m_Channels = channels;
|
||||||
|
m_BPM = bpm;
|
||||||
m_Length = length;
|
m_Length = length;
|
||||||
m_SampleRate = sampleRate;
|
m_SampleRate = sampleRate;
|
||||||
m_Bitrate = bitrate;
|
m_Bitrate = bitrate;
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,14 @@ class Sample
|
||||||
public:
|
public:
|
||||||
Sample();
|
Sample();
|
||||||
Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
Sample(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||||
int sampleRate, int bitrate, const std::string& path, int trashed);
|
int length, int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
int m_Favorite = 0;
|
int m_Favorite = 0;
|
||||||
int m_Channels = 0;
|
int m_Channels = 0;
|
||||||
|
int m_BPM = 0;
|
||||||
int m_Length = 0;
|
int m_Length = 0;
|
||||||
int m_SampleRate = 0;
|
int m_SampleRate = 0;
|
||||||
int m_Bitrate = 0;
|
int m_Bitrate = 0;
|
||||||
|
|
@ -62,6 +63,7 @@ class Sample
|
||||||
// Getters
|
// Getters
|
||||||
int GetFavorite() const { return m_Favorite; }
|
int GetFavorite() const { return m_Favorite; }
|
||||||
int GetChannels() const { return m_Channels; }
|
int GetChannels() const { return m_Channels; }
|
||||||
|
int GetBPM() const { return m_BPM; }
|
||||||
int GetLength() const { return m_Length; }
|
int GetLength() const { return m_Length; }
|
||||||
int GetSampleRate() const { return m_SampleRate; }
|
int GetSampleRate() const { return m_SampleRate; }
|
||||||
int GetBitrate() const { return m_Bitrate; }
|
int GetBitrate() const { return m_Bitrate; }
|
||||||
|
|
@ -75,11 +77,12 @@ class Sample
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Setters
|
// Setters
|
||||||
void Set(int favorite, const std::string& filename, const std::string& fileExtension,
|
void Set(int favorite, const std::string& filename, const std::string& fileExtension,
|
||||||
const std::string& samplePack, const std::string& type, int channels, int length,
|
const std::string& samplePack, const std::string& type, int channels, int bpm,
|
||||||
int sampleRate, int bitrate, const std::string& path, int trashed);
|
int length, int sampleRate, int bitrate, const std::string& path, int trashed);
|
||||||
|
|
||||||
void SetFavorite(int favorite) { m_Favorite = favorite; }
|
void SetFavorite(int favorite) { m_Favorite = favorite; }
|
||||||
void SetChannels(int channels) { m_Channels = channels; }
|
void SetChannels(int channels) { m_Channels = channels; }
|
||||||
|
void SetBPM(int bpm) { m_BPM = bpm; }
|
||||||
void SetLength(int length) { m_Length = length; }
|
void SetLength(int length) { m_Length = length; }
|
||||||
void SetSampleRate(int sampleRate) { m_SampleRate = sampleRate; }
|
void SetSampleRate(int sampleRate) { m_SampleRate = sampleRate; }
|
||||||
void SetBitrate(int bitrate) { m_Bitrate = bitrate; }
|
void SetBitrate(int bitrate) { m_Bitrate = bitrate; }
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "Database/Database.hpp"
|
#include "Database/Database.hpp"
|
||||||
#include "Utility/HiveData.hpp"
|
#include "Utility/HiveData.hpp"
|
||||||
#include "Utility/Log.hpp"
|
#include "Utility/Log.hpp"
|
||||||
|
|
@ -32,6 +34,8 @@
|
||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include <aubio/aubio.h>
|
||||||
|
|
||||||
namespace SampleHive {
|
namespace SampleHive {
|
||||||
|
|
||||||
SampleHive::cUtils::FileInfo SampleHive::cUtils::GetFilenamePathAndExtension(const wxString& selected,
|
SampleHive::cUtils::FileInfo SampleHive::cUtils::GetFilenamePathAndExtension(const wxString& selected,
|
||||||
|
|
@ -75,6 +79,9 @@ namespace SampleHive {
|
||||||
std::string extension;
|
std::string extension;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
||||||
|
float bpm = 0.0f;
|
||||||
|
float key = 0.0f;
|
||||||
|
|
||||||
//Check All Files At Once
|
//Check All Files At Once
|
||||||
wxArrayString sorted_files;
|
wxArrayString sorted_files;
|
||||||
|
|
||||||
|
|
@ -110,6 +117,8 @@ namespace SampleHive {
|
||||||
filename = serializer.DeserializeShowFileExtension() ?
|
filename = serializer.DeserializeShowFileExtension() ?
|
||||||
filename_with_extension : filename_without_extension;
|
filename_with_extension : filename_without_extension;
|
||||||
|
|
||||||
|
bpm = GetBPM(path);
|
||||||
|
|
||||||
Sample sample;
|
Sample sample;
|
||||||
|
|
||||||
sample.SetPath(path);
|
sample.SetPath(path);
|
||||||
|
|
@ -122,11 +131,13 @@ namespace SampleHive {
|
||||||
|
|
||||||
sample.SetSamplePack(artist);
|
sample.SetSamplePack(artist);
|
||||||
sample.SetChannels(tags.GetAudioInfo().channels);
|
sample.SetChannels(tags.GetAudioInfo().channels);
|
||||||
|
sample.SetBPM(static_cast<int>(bpm));
|
||||||
sample.SetLength(tags.GetAudioInfo().length);
|
sample.SetLength(tags.GetAudioInfo().length);
|
||||||
sample.SetSampleRate(tags.GetAudioInfo().sample_rate);
|
sample.SetSampleRate(tags.GetAudioInfo().sample_rate);
|
||||||
sample.SetBitrate(tags.GetAudioInfo().bitrate);
|
sample.SetBitrate(tags.GetAudioInfo().bitrate);
|
||||||
|
|
||||||
wxString length = CalculateAndGetISOStandardTime(sample.GetLength());
|
wxString length = CalculateAndGetISOStandardTime(sample.GetLength());
|
||||||
|
wxString bpm_str = GetBPMString(sample.GetBPM());
|
||||||
|
|
||||||
wxVector<wxVariant> data;
|
wxVector<wxVariant> data;
|
||||||
|
|
||||||
|
|
@ -140,6 +151,7 @@ namespace SampleHive {
|
||||||
data.push_back(sample.GetSamplePack());
|
data.push_back(sample.GetSamplePack());
|
||||||
data.push_back("");
|
data.push_back("");
|
||||||
data.push_back(wxString::Format("%d", sample.GetChannels()));
|
data.push_back(wxString::Format("%d", sample.GetChannels()));
|
||||||
|
data.push_back(bpm_str);
|
||||||
data.push_back(length);
|
data.push_back(length);
|
||||||
data.push_back(wxString::Format("%d", sample.GetSampleRate()));
|
data.push_back(wxString::Format("%d", sample.GetSampleRate()));
|
||||||
data.push_back(wxString::Format("%d", sample.GetBitrate()));
|
data.push_back(wxString::Format("%d", sample.GetBitrate()));
|
||||||
|
|
@ -249,4 +261,72 @@ namespace SampleHive {
|
||||||
return iso_length;
|
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 AddSamples(wxArrayString& files, wxWindow* parent);
|
||||||
void OnAutoImportDir(const wxString& pathToDirectory, wxWindow* parent);
|
void OnAutoImportDir(const wxString& pathToDirectory, wxWindow* parent);
|
||||||
wxString CalculateAndGetISOStandardTime(wxLongLong length);
|
wxString CalculateAndGetISOStandardTime(wxLongLong length);
|
||||||
|
wxString GetBPMString(float bpm);
|
||||||
|
|
||||||
|
float GetBPM(const std::string& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue