Simplified the feature settings
This commit is contained in:
+2
-4
@@ -40,10 +40,8 @@ lms_SOURCES = \
|
||||
$(srcdir)/database/ScanSettings.hpp \
|
||||
$(srcdir)/database/Session.cpp \
|
||||
$(srcdir)/database/Session.hpp \
|
||||
$(srcdir)/database/SessionPool.cpp \
|
||||
$(srcdir)/database/SessionPool.hpp \
|
||||
$(srcdir)/database/SimilaritySettings.cpp \
|
||||
$(srcdir)/database/SimilaritySettings.hpp \
|
||||
$(srcdir)/database/SessionPool.cpp \
|
||||
$(srcdir)/database/SessionPool.hpp \
|
||||
$(srcdir)/database/SqlQuery.cpp \
|
||||
$(srcdir)/database/SqlQuery.hpp \
|
||||
$(srcdir)/database/Track.cpp \
|
||||
|
||||
@@ -34,6 +34,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
public:
|
||||
using pointer = Wt::Dbo::ptr<ScanSettings>;
|
||||
|
||||
// Do not modify values (just add)
|
||||
enum class UpdatePeriod {
|
||||
Never = 0,
|
||||
Daily,
|
||||
@@ -41,6 +42,13 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
Monthly
|
||||
};
|
||||
|
||||
// Do not modify values (just add)
|
||||
enum class SimilarityEngineType
|
||||
{
|
||||
Clusters = 0,
|
||||
Features,
|
||||
};
|
||||
|
||||
static void init(Session& session);
|
||||
|
||||
static pointer get(Session& session);
|
||||
@@ -52,12 +60,14 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
UpdatePeriod getUpdatePeriod() const { return _updatePeriod; }
|
||||
std::vector<Wt::Dbo::ptr<ClusterType>> getClusterTypes() const;
|
||||
std::set<std::filesystem::path> getAudioFileExtensions() const;
|
||||
SimilarityEngineType getSimilarityEngineType() const { return _similarityEngineType; }
|
||||
|
||||
// Setters
|
||||
void setMediaDirectory(std::filesystem::path p);
|
||||
void setUpdateStartTime(Wt::WTime t) { _startTime = t; }
|
||||
void setUpdatePeriod(UpdatePeriod p) { _updatePeriod = p; }
|
||||
void setClusterTypes(Session& session, const std::set<std::string>& clusterTypeNames);
|
||||
void setSimilarityEngineType(SimilarityEngineType type) { _similarityEngineType = type; }
|
||||
void incScanVersion();
|
||||
|
||||
template<class Action>
|
||||
@@ -68,6 +78,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
Wt::Dbo::field(a, _startTime, "start_time");
|
||||
Wt::Dbo::field(a, _updatePeriod, "update_period");
|
||||
Wt::Dbo::field(a, _audioFileExtensions, "audio_file_extensions");
|
||||
Wt::Dbo::field(a, _similarityEngineType,"similarity_engine_type");
|
||||
Wt::Dbo::hasMany(a, _clusterTypes, Wt::Dbo::ManyToOne, "scan_settings");
|
||||
}
|
||||
|
||||
@@ -77,6 +88,7 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
std::string _mediaDirectory;
|
||||
Wt::WTime _startTime = Wt::WTime {0,0,0};
|
||||
UpdatePeriod _updatePeriod {UpdatePeriod::Never};
|
||||
SimilarityEngineType _similarityEngineType {SimilarityEngineType::Clusters};
|
||||
std::string _audioFileExtensions {".mp3 .ogg .oga .aac .m4a .flac .wav .wma .aif .aiff .ape .mpc .shn .opus"};
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<ClusterType>> _clusterTypes;
|
||||
};
|
||||
|
||||
+21
-14
@@ -31,7 +31,6 @@
|
||||
#include "Db.hpp"
|
||||
#include "Release.hpp"
|
||||
#include "ScanSettings.hpp"
|
||||
#include "SimilaritySettings.hpp"
|
||||
#include "Track.hpp"
|
||||
#include "TrackArtistLink.hpp"
|
||||
#include "TrackList.hpp"
|
||||
@@ -40,7 +39,7 @@
|
||||
|
||||
namespace Database {
|
||||
|
||||
#define LMS_DATABASE_VERSION 7
|
||||
#define LMS_DATABASE_VERSION 8
|
||||
|
||||
using Version = std::size_t;
|
||||
|
||||
@@ -101,21 +100,32 @@ Session::doDatabaseMigrationIfNeeded()
|
||||
throw LmsException {outdatedMsg};
|
||||
}
|
||||
|
||||
switch (version)
|
||||
while (version < LMS_DATABASE_VERSION)
|
||||
{
|
||||
case 5:
|
||||
LMS_LOG(DB, INFO) << "Migrating database from version 5...";
|
||||
LMS_LOG(DB, INFO) << "Migrating database from version " << version << "...";
|
||||
|
||||
if (version == 5)
|
||||
{
|
||||
_session.execute("DELETE FROM auth_token"); // format has changed
|
||||
break;
|
||||
case 6:
|
||||
LMS_LOG(DB, INFO) << "Migrating database from version 6...";
|
||||
}
|
||||
else if (version == 6)
|
||||
{
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
ScanSettings::get(*this).modify()->incScanVersion();
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
else if (version == 7)
|
||||
{
|
||||
_session.execute("DROP TABLE similarity_settings");
|
||||
_session.execute("DROP TABLE similarity_settings_feature");
|
||||
_session.execute("ALTER TABLE scan_settings ADD similarity_engine_type INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(ScanSettings::SimilarityEngineType::Clusters)) + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(DB, ERROR) << "Database version " << version << " cannot be handled using migration";
|
||||
throw LmsException { LMS_DATABASE_VERSION > version ? outdatedMsg : "Server binary outdated, please upgrade it to handle this database"};
|
||||
}
|
||||
|
||||
++version;
|
||||
}
|
||||
|
||||
VersionInfo::get(*this).modify()->setVersion(LMS_DATABASE_VERSION);
|
||||
@@ -133,8 +143,6 @@ Session::Session(Db& db)
|
||||
_session.mapClass<ClusterType>("cluster_type");
|
||||
_session.mapClass<Release>("release");
|
||||
_session.mapClass<ScanSettings>("scan_settings");
|
||||
_session.mapClass<SimilaritySettings>("similarity_settings");
|
||||
_session.mapClass<SimilaritySettingsFeature>("similarity_settings_feature");
|
||||
_session.mapClass<Track>("track");
|
||||
_session.mapClass<TrackArtistLink>("track_artist_link");
|
||||
_session.mapClass<TrackFeatures>("track_features");
|
||||
@@ -257,7 +265,6 @@ Session::prepareTables()
|
||||
auto uniqueTransaction {createUniqueTransaction()};
|
||||
|
||||
ScanSettings::init(*this);
|
||||
SimilaritySettings::init(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SimilaritySettings.hpp"
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "Session.hpp"
|
||||
#include "TrackFeatures.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
static const std::map<std::string, double> defaultFeatures =
|
||||
{
|
||||
{ "lowlevel.spectral_contrast_coeffs.median", 1. },
|
||||
{ "lowlevel.erbbands.median", 1. },
|
||||
{ "tonal.hpcp.median", 1. },
|
||||
{ "lowlevel.melbands.median", 1. },
|
||||
{ "lowlevel.barkbands.median", 1. },
|
||||
{ "lowlevel.mfcc.mean", 1. },
|
||||
{ "lowlevel.gfcc.mean", 1. },
|
||||
};
|
||||
|
||||
SimilaritySettingsFeature::SimilaritySettingsFeature(Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, double weight)
|
||||
: _name {name},
|
||||
_weight {weight},
|
||||
_settings {settings}
|
||||
{
|
||||
}
|
||||
|
||||
SimilaritySettingsFeature::pointer
|
||||
SimilaritySettingsFeature::create(Session& session, Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, double weight)
|
||||
{
|
||||
session.checkUniqueLocked();
|
||||
|
||||
SimilaritySettingsFeature::pointer res {session.getDboSession().add(std::make_unique<SimilaritySettingsFeature>(settings, name, weight))};
|
||||
session.getDboSession().flush();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
SimilaritySettings::init(Session& session)
|
||||
{
|
||||
session.checkUniqueLocked();
|
||||
|
||||
pointer settings {session.getDboSession().find<SimilaritySettings>()};
|
||||
if (settings)
|
||||
return;
|
||||
|
||||
settings = session.getDboSession().add(std::make_unique<SimilaritySettings>());
|
||||
for (const auto& [feature, weight] : defaultFeatures)
|
||||
SimilaritySettingsFeature::create(session, settings, feature, weight);
|
||||
}
|
||||
|
||||
|
||||
SimilaritySettings::pointer
|
||||
SimilaritySettings::get(Session& session)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
return session.getDboSession().find<SimilaritySettings>();
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>>
|
||||
SimilaritySettings::getFeatures() const
|
||||
{
|
||||
return std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>>(_features.begin(), _features.end());
|
||||
}
|
||||
|
||||
} // namespace Database
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
|
||||
namespace Database {
|
||||
|
||||
class Session;
|
||||
class SimilaritySettings;
|
||||
|
||||
class SimilaritySettingsFeature : public Wt::Dbo::Dbo<SimilaritySettingsFeature>
|
||||
{
|
||||
public:
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettingsFeature>;
|
||||
|
||||
SimilaritySettingsFeature() = default;
|
||||
SimilaritySettingsFeature(Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, double weight);
|
||||
|
||||
static pointer create(Session& session, Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, double weight = 1);
|
||||
|
||||
const std::string& getName() const { return _name; } ;
|
||||
double getWeight() const { return _weight; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _name, "name");
|
||||
Wt::Dbo::field(a, _weight, "weight");
|
||||
|
||||
Wt::Dbo::belongsTo(a, _settings, "similarity_settings", Wt::Dbo::OnDeleteCascade);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
double _weight {1};
|
||||
|
||||
Wt::Dbo::ptr<SimilaritySettings> _settings;
|
||||
};
|
||||
|
||||
class SimilaritySettings : public Wt::Dbo::Dbo<SimilaritySettings>
|
||||
{
|
||||
public:
|
||||
|
||||
enum class EngineType
|
||||
{
|
||||
Features = 0,
|
||||
Clusters = 1,
|
||||
};
|
||||
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettings>;
|
||||
|
||||
// Utils
|
||||
static void init(Session& session);
|
||||
static pointer get(Session& session);
|
||||
|
||||
// Accessors Read
|
||||
std::size_t getVersion() const { return _settingsVersion; }
|
||||
EngineType getEngineType() const { return _engineType; }
|
||||
std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>> getFeatures() const;
|
||||
|
||||
// Setters
|
||||
void setEngineType(EngineType type) { _engineType = type; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _settingsVersion, "settings_version");
|
||||
Wt::Dbo::field(a, _engineType, "engine_type");
|
||||
|
||||
Wt::Dbo::hasMany(a, _features, Wt::Dbo::ManyToOne, "similarity_settings");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _settingsVersion {};
|
||||
EngineType _engineType {EngineType::Clusters};
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<SimilaritySettingsFeature>> _features;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Database
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "features/SimilarityFeaturesScannerAddon.hpp"
|
||||
#include "cluster/SimilarityClusterSearcher.hpp"
|
||||
|
||||
#include "database/SimilaritySettings.hpp"
|
||||
#include "database/ScanSettings.hpp"
|
||||
#include "database/TrackList.hpp"
|
||||
|
||||
namespace Similarity {
|
||||
@@ -32,10 +32,11 @@ Searcher::Searcher(FeaturesScannerAddon& somAddon)
|
||||
{}
|
||||
|
||||
static
|
||||
Database::SimilaritySettings::EngineType getEngineType(Database::Session& dbSession)
|
||||
Database::ScanSettings::SimilarityEngineType
|
||||
getEngineType(Database::Session& dbSession)
|
||||
{
|
||||
auto transaction {dbSession.createSharedTransaction()};
|
||||
return Database::SimilaritySettings::get(dbSession)->getEngineType();
|
||||
return Database::ScanSettings::get(dbSession)->getSimilarityEngineType();
|
||||
}
|
||||
|
||||
std::vector<Database::IdType>
|
||||
@@ -58,7 +59,7 @@ Searcher::getSimilarTracksFromTrackList(Database::Session& session, Database::Id
|
||||
if (trackIds.empty())
|
||||
return {};
|
||||
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
|
||||
&& somSearcher
|
||||
&& std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return somSearcher->isTrackClassified(trackId); } ))
|
||||
{
|
||||
@@ -74,7 +75,7 @@ Searcher::getSimilarTracks(Database::Session& dbSession, const std::set<Database
|
||||
auto engineType {getEngineType(dbSession)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
|
||||
&& somSearcher
|
||||
&& std::any_of(std::cbegin(trackIds), std::cend(trackIds), [&](Database::IdType trackId) { return somSearcher->isTrackClassified(trackId); } ))
|
||||
{
|
||||
@@ -90,7 +91,7 @@ Searcher::getSimilarReleases(Database::Session& dbSession, Database::IdType rele
|
||||
auto engineType {getEngineType(dbSession)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
|
||||
&& somSearcher
|
||||
&& somSearcher->isReleaseClassified(releaseId))
|
||||
{
|
||||
@@ -106,7 +107,7 @@ Searcher::getSimilarArtists(Database::Session& dbSession, Database::IdType artis
|
||||
auto engineType {getEngineType(dbSession)};
|
||||
auto somSearcher {_somAddon.getSearcher()};
|
||||
|
||||
if (engineType == Database::SimilaritySettings::EngineType::Features
|
||||
if (engineType == Database::ScanSettings::SimilarityEngineType::Features
|
||||
&& somSearcher
|
||||
&& somSearcher->isArtistClassified(artistId))
|
||||
{
|
||||
|
||||
@@ -122,7 +122,60 @@ static const std::unordered_map<FeatureName, FeatureDef> featureDefinitions
|
||||
{ "lowlevel.hfc.min", {1}},
|
||||
{ "lowlevel.hfc.var", {1}},
|
||||
{ "tonal.hpcp.median", {36}},
|
||||
{ "lowlevel.melbands.dmean", {40}},
|
||||
{ "lowlevel.melbands.dmean2", {40}},
|
||||
{ "lowlevel.melbands.dvar", {40}},
|
||||
{ "lowlevel.melbands.dvar2", {40}},
|
||||
{ "lowlevel.melbands.max", {40}},
|
||||
{ "lowlevel.melbands.mean", {40}},
|
||||
{ "lowlevel.melbands.median", {40}},
|
||||
{ "lowlevel.melbands.min", {40}},
|
||||
{ "lowlevel.melbands.var", {40}},
|
||||
{ "lowlevel.melbands_crest.dmean", {1}},
|
||||
{ "lowlevel.melbands_crest.dmean2", {1}},
|
||||
{ "lowlevel.melbands_crest.dvar", {1}},
|
||||
{ "lowlevel.melbands_crest.dvar2", {1}},
|
||||
{ "lowlevel.melbands_crest.max", {1}},
|
||||
{ "lowlevel.melbands_crest.mean", {1}},
|
||||
{ "lowlevel.melbands_crest.median", {1}},
|
||||
{ "lowlevel.melbands_crest.min", {1}},
|
||||
{ "lowlevel.melbands_crest.var", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.dmean", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.dmean2", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.dvar", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.dvar2", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.max", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.mean", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.median", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.min", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.var", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.dmean", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.dmean2", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.dvar", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.dvar2", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.max", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.mean", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.median", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.min", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.var", {1}},
|
||||
{ "lowlevel.melbands_skewness.dmean", {1}},
|
||||
{ "lowlevel.melbands_skewness.dmean2", {1}},
|
||||
{ "lowlevel.melbands_skewness.dvar", {1}},
|
||||
{ "lowlevel.melbands_skewness.dvar2", {1}},
|
||||
{ "lowlevel.melbands_skewness.max", {1}},
|
||||
{ "lowlevel.melbands_skewness.mean", {1}},
|
||||
{ "lowlevel.melbands_skewness.median", {1}},
|
||||
{ "lowlevel.melbands_skewness.min", {1}},
|
||||
{ "lowlevel.melbands_skewness.var", {1}},
|
||||
{ "lowlevel.melbands_spread.dmean", {1}},
|
||||
{ "lowlevel.melbands_spread.dmean2", {1}},
|
||||
{ "lowlevel.melbands_spread.dvar", {1}},
|
||||
{ "lowlevel.melbands_spread.dvar2", {1}},
|
||||
{ "lowlevel.melbands_spread.max", {1}},
|
||||
{ "lowlevel.melbands_spread.mean", {1}},
|
||||
{ "lowlevel.melbands_spread.median", {1}},
|
||||
{ "lowlevel.melbands_spread.min", {1}},
|
||||
{ "lowlevel.melbands_spread.var", {1}},
|
||||
{ "lowlevel.mfcc.mean", {13}},
|
||||
{ "lowlevel.pitch_salience.dmean", {1}},
|
||||
{ "lowlevel.pitch_salience.dmean2", {1}},
|
||||
@@ -133,6 +186,24 @@ static const std::unordered_map<FeatureName, FeatureDef> featureDefinitions
|
||||
{ "lowlevel.pitch_salience.median", {1}},
|
||||
{ "lowlevel.pitch_salience.min", {1}},
|
||||
{ "lowlevel.pitch_salience.var", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.dmean", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.dmean2", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.dvar", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.dvar2", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.max", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.min", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.var", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.dmean", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.dmean2", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.dvar", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.dvar2", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.max", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.min", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.var", {1}},
|
||||
{ "lowlevel.spectral_centroid.dmean", {1}},
|
||||
{ "lowlevel.spectral_centroid.dmean2", {1}},
|
||||
{ "lowlevel.spectral_centroid.dvar", {1}},
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "SimilarityFeaturesScannerAddon.hpp"
|
||||
|
||||
#include "AcousticBrainzUtils.hpp"
|
||||
#include "database/ScanSettings.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "database/SimilaritySettings.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "similarity/features/SimilarityFeaturesCache.hpp"
|
||||
#include "utils/Config.hpp"
|
||||
@@ -29,26 +29,12 @@
|
||||
|
||||
namespace Similarity {
|
||||
|
||||
static
|
||||
FeatureSettingsMap
|
||||
getFeatureSettings(Database::Session& session)
|
||||
{
|
||||
FeatureSettingsMap res;
|
||||
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
for (const auto& feature : Database::SimilaritySettings::get(session)->getFeatures())
|
||||
res[feature->getName()] = {feature->getWeight()};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
hasAtLeastOneTrackWithFeatures(Database::Session& session)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return !Database::Track::getAllIdsWithFeatures(session).empty();
|
||||
return !Database::Track::getAllIdsWithFeatures(session, 1).empty();
|
||||
}
|
||||
|
||||
struct TrackInfo
|
||||
@@ -114,7 +100,7 @@ FeaturesScannerAddon::preScanComplete()
|
||||
{
|
||||
auto transaction {_dbSession.createSharedTransaction()};
|
||||
|
||||
if (Database::SimilaritySettings::get(_dbSession)->getEngineType() != Database::SimilaritySettings::EngineType::Features)
|
||||
if (Database::ScanSettings::get(_dbSession)->getSimilarityEngineType() != Database::ScanSettings::SimilarityEngineType::Features)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO) << "Do not fetch features since the engine type does not make use of them";
|
||||
return;
|
||||
@@ -144,17 +130,17 @@ FeaturesScannerAddon::updateSearcher()
|
||||
{
|
||||
LMS_LOG(SIMILARITY, INFO) << "Updating searcher...";
|
||||
|
||||
if (hasAtLeastOneTrackWithFeatures(_dbSession))
|
||||
if (!hasAtLeastOneTrackWithFeatures(_dbSession))
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO) << "No track suitable for features similarity clustering";
|
||||
LMS_LOG(DBUPDATER, INFO) << "No track found with features!";
|
||||
std::atomic_store(&_searcher, std::shared_ptr<FeaturesSearcher>{});
|
||||
return;
|
||||
}
|
||||
|
||||
Similarity::FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.featureSettingsMap = getFeatureSettings(_dbSession);
|
||||
trainSettings.featureSettingsMap = FeaturesSearcher::getDefaultTrainFeatureSettings();
|
||||
|
||||
auto searcher {std::make_shared<Similarity::FeaturesSearcher>(_dbSession, trainSettings, [&]() { return _stopRequested; })};
|
||||
auto searcher {std::make_shared<FeaturesSearcher>(_dbSession, trainSettings, [&]() { return _stopRequested; })};
|
||||
if (searcher->isValid())
|
||||
{
|
||||
std::atomic_store(&_searcher, searcher);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/SimilaritySettings.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
@@ -35,6 +34,21 @@
|
||||
|
||||
namespace Similarity {
|
||||
|
||||
const FeatureSettingsMap&
|
||||
FeaturesSearcher::getDefaultTrainFeatureSettings()
|
||||
{
|
||||
static FeatureSettingsMap defaultTrainFeatureSettings
|
||||
{
|
||||
{ "lowlevel.spectral_energyband_high.mean", {1}},
|
||||
{ "lowlevel.spectral_rolloff.median", {1}},
|
||||
{ "lowlevel.spectral_contrast_valleys.var", {1}},
|
||||
{ "lowlevel.erbbands.mean", {1}},
|
||||
{ "lowlevel.gfcc.mean", {1}},
|
||||
};
|
||||
|
||||
return defaultTrainFeatureSettings;
|
||||
}
|
||||
|
||||
static
|
||||
std::optional<FeatureValuesMap>
|
||||
getTrackFeatureValues(FeaturesSearcher::FeaturesFetchFunc func, Database::IdType trackId, const std::unordered_set<FeatureName>& featureNames)
|
||||
@@ -128,7 +142,7 @@ FeaturesSearcher::FeaturesSearcher(Database::Session& session,
|
||||
|
||||
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features...";
|
||||
trackIds = Database::Track::getAllIdsWithFeatures(session);
|
||||
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features DONE";
|
||||
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features DONE (found " << trackIds.size() << " tracks)";
|
||||
}
|
||||
|
||||
std::vector<SOM::InputVector> samples;
|
||||
|
||||
@@ -57,6 +57,8 @@ class FeaturesSearcher
|
||||
};
|
||||
FeaturesSearcher(Database::Session& session, const TrainSettings& trainSettings, StopRequestedFunction stopRequested = {});
|
||||
|
||||
static const FeatureSettingsMap& getDefaultTrainFeatureSettings();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
bool isTrackClassified(Database::IdType trackId) const;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <Wt/WTemplateFormView.h>
|
||||
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/SimilaritySettings.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Service.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
@@ -85,7 +84,6 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||
|
||||
const ScanSettings::pointer scanSettings {ScanSettings::get(LmsApp->getDbSession())};
|
||||
const SimilaritySettings::pointer similaritySettings {SimilaritySettings::get(LmsApp->getDbSession())};
|
||||
|
||||
setValue(MediaDirectoryField, scanSettings->getMediaDirectory().string());
|
||||
|
||||
@@ -97,7 +95,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
if (startTimeRow)
|
||||
setValue(UpdateStartTimeField, _updateStartTimeModel->getString(*startTimeRow));
|
||||
|
||||
auto similarityEngineTypeRow {_similarityEngineTypeModel->getRowFromValue(similaritySettings->getEngineType())};
|
||||
auto similarityEngineTypeRow {_similarityEngineTypeModel->getRowFromValue(scanSettings->getSimilarityEngineType())};
|
||||
if (similarityEngineTypeRow)
|
||||
setValue(SimilarityEngineTypeField, _similarityEngineTypeModel->getString(*similarityEngineTypeRow));
|
||||
|
||||
@@ -115,7 +113,6 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
||||
|
||||
ScanSettings::pointer scanSettings {ScanSettings::get(LmsApp->getDbSession())};
|
||||
SimilaritySettings::pointer similaritySettings {SimilaritySettings::get(LmsApp->getDbSession())};
|
||||
|
||||
scanSettings.modify()->setMediaDirectory(valueText(MediaDirectoryField).toUTF8());
|
||||
|
||||
@@ -129,7 +126,7 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
|
||||
auto similarityEngineTypeRow {_similarityEngineTypeModel->getRowFromString(valueText(SimilarityEngineTypeField))};
|
||||
if (similarityEngineTypeRow)
|
||||
similaritySettings.modify()->setEngineType(_similarityEngineTypeModel->getValue(*similarityEngineTypeRow));
|
||||
scanSettings.modify()->setSimilarityEngineType(_similarityEngineTypeModel->getValue(*similarityEngineTypeRow));
|
||||
|
||||
auto clusterTypes {splitString(valueText(TagsField).toUTF8(), " ")};
|
||||
scanSettings.modify()->setClusterTypes(LmsApp->getDbSession(), std::set<std::string>(clusterTypes.begin(), clusterTypes.end()));
|
||||
@@ -158,14 +155,14 @@ class DatabaseSettingsModel : public Wt::WFormModel
|
||||
_updateStartTimeModel->add(time.toString(), time);
|
||||
}
|
||||
|
||||
_similarityEngineTypeModel = std::make_shared<ValueStringModel<SimilaritySettings::EngineType>>();
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.clusters"), SimilaritySettings::EngineType::Clusters);
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.features"), SimilaritySettings::EngineType::Features);
|
||||
_similarityEngineTypeModel = std::make_shared<ValueStringModel<ScanSettings::SimilarityEngineType>>();
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.clusters"), ScanSettings::SimilarityEngineType::Clusters);
|
||||
_similarityEngineTypeModel->add(Wt::WString::tr("Lms.Admin.Database.similarity-engine-type.features"), ScanSettings::SimilarityEngineType::Features);
|
||||
}
|
||||
|
||||
std::shared_ptr<ValueStringModel<ScanSettings::UpdatePeriod>> _updatePeriodModel;
|
||||
std::shared_ptr<ValueStringModel<Wt::WTime>> _updateStartTimeModel;
|
||||
std::shared_ptr<ValueStringModel<SimilaritySettings::EngineType>> _similarityEngineTypeModel;
|
||||
std::shared_ptr<ValueStringModel<ScanSettings::SimilarityEngineType>> _similarityEngineTypeModel;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ test_database_SOURCES = \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
||||
$(top_srcdir)/src/database/Session.cpp \
|
||||
$(top_srcdir)/src/database/SimilaritySettings.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
|
||||
@@ -58,7 +58,7 @@ class GeneticAlgorithm
|
||||
|
||||
void scoreAndSortPopulation(std::vector<ScoredIndividual>& population);
|
||||
Score getTotalScore(const std::vector<ScoredIndividual>& population) const;
|
||||
typename std::vector<ScoredIndividual>::const_iterator pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population);
|
||||
typename std::vector<ScoredIndividual>::const_iterator pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population, Score totalScore);
|
||||
|
||||
Params _params;
|
||||
};
|
||||
@@ -90,23 +90,22 @@ GeneticAlgorithm<Individual>::simulate(const std::vector<Individual>& initialPop
|
||||
{
|
||||
assert(scoredPopulation.size() == initialPopulation.size());
|
||||
std::cout << "Processing generation " << currentGeneration << "..." << std::endl;
|
||||
std::cout << "Need to create " << childrenCountPerGeneration << " new children" << std::endl;
|
||||
|
||||
// breed
|
||||
const Score populationTotalScore {getTotalScore(scoredPopulation)};
|
||||
std::vector<ScoredIndividual> children;
|
||||
children.reserve(childrenCountPerGeneration);
|
||||
|
||||
while (children.size() < childrenCountPerGeneration)
|
||||
{
|
||||
// Select two random parents using their score as weight
|
||||
const auto itParent1 {pickRandomRouletteWheel(scoredPopulation)};
|
||||
const auto itParent2 {pickRandomRouletteWheel(scoredPopulation)};
|
||||
const auto itParent1 {pickRandomRouletteWheel(scoredPopulation, populationTotalScore)};
|
||||
const auto itParent2 {pickRandomRouletteWheel(scoredPopulation, populationTotalScore)};
|
||||
|
||||
if (itParent1 == itParent2)
|
||||
continue;
|
||||
|
||||
std::cout << "Parent1 = " << std::distance(std::cbegin(scoredPopulation), itParent1) << std::endl;
|
||||
std::cout << "Parent2 = " << std::distance(std::cbegin(scoredPopulation), itParent2) << std::endl;
|
||||
|
||||
ScoredIndividual child {_params.breedFunction(itParent1->individual, itParent2->individual)};
|
||||
|
||||
if (getRealRandom(float {}, float {1}) <= _params.mutationProbability)
|
||||
@@ -155,11 +154,9 @@ GeneticAlgorithm<Individual>::getTotalScore(const std::vector<ScoredIndividual>&
|
||||
|
||||
template<typename Individual>
|
||||
typename std::vector<typename GeneticAlgorithm<Individual>::ScoredIndividual>::const_iterator
|
||||
GeneticAlgorithm<Individual>::pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population)
|
||||
GeneticAlgorithm<Individual>::pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population, Score totalScore)
|
||||
{
|
||||
const Score randomScore {getRealRandom(Score {}, getTotalScore(population))};
|
||||
|
||||
std::cout << "Random = " << randomScore << ", total = " << getTotalScore(population) << std::endl;
|
||||
const Score randomScore {getRealRandom(Score {}, totalScore)};
|
||||
|
||||
Score curScore{};
|
||||
for (auto itScoredIndividual {std::cbegin(population)}; itScoredIndividual != std::cend(population); ++itScoredIndividual )
|
||||
|
||||
@@ -76,11 +76,34 @@ const FeatureSettingsMap featuresSettings
|
||||
{ "lowlevel.hfc.median", {1}},
|
||||
{ "lowlevel.hfc.var", {1}},
|
||||
{ "tonal.hpcp.median", {1}},
|
||||
{ "lowlevel.melbands.mean", {1}},
|
||||
{ "lowlevel.melbands.median", {1}},
|
||||
{ "lowlevel.melbands.var", {1}},
|
||||
{ "lowlevel.melbands_crest.mean", {1}},
|
||||
{ "lowlevel.melbands_crest.median", {1}},
|
||||
{ "lowlevel.melbands_crest.var", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.mean", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.median", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.var", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.mean", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.median", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.var", {1}},
|
||||
{ "lowlevel.melbands_skewness.mean", {1}},
|
||||
{ "lowlevel.melbands_skewness.median", {1}},
|
||||
{ "lowlevel.melbands_skewness.var", {1}},
|
||||
{ "lowlevel.melbands_spread.mean", {1}},
|
||||
{ "lowlevel.melbands_spread.median", {1}},
|
||||
{ "lowlevel.melbands_spread.var", {1}},
|
||||
{ "lowlevel.mfcc.mean", {1}},
|
||||
{ "lowlevel.pitch_salience.mean", {1}},
|
||||
{ "lowlevel.pitch_salience.median", {1}},
|
||||
{ "lowlevel.pitch_salience.var", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.var", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.var", {1}},
|
||||
{ "lowlevel.spectral_centroid.mean", {1}},
|
||||
{ "lowlevel.spectral_centroid.median", {1}},
|
||||
{ "lowlevel.spectral_centroid.var", {1}},
|
||||
@@ -261,10 +284,10 @@ computeTrackScore(Database::Session& session, Database::IdType track1Id, Databas
|
||||
|
||||
static
|
||||
SimilarityScore
|
||||
computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings, const FeatureSettingsMap& featuresSettings)
|
||||
computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings)
|
||||
{
|
||||
std::cout << "Compute score of: ";
|
||||
printFeatureSettingsMap(featuresSettings);
|
||||
printFeatureSettingsMap(trainSettings.featureSettingsMap);
|
||||
std::cout << std::endl;
|
||||
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
@@ -272,7 +295,7 @@ computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettin
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIds(session);
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
SimilarityScore score {};
|
||||
@@ -297,6 +320,32 @@ computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettin
|
||||
return score;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
printBadlyClassifiedTracks(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings)
|
||||
{
|
||||
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
for (Database::IdType trackId : trackIds)
|
||||
{
|
||||
constexpr std::size_t nbSimilarTracks {3};
|
||||
for (Database::IdType similarTrackId : searcher.getSimilarTracks({trackId}, nbSimilarTracks))
|
||||
{
|
||||
SimilarityScore trackScore {computeTrackScore(session, trackId, similarTrackId)};
|
||||
if (trackScore == 0)
|
||||
std::cout << "Badly classified tracks: '" << trackToString(session, trackId) << "'\n\twith track '" << trackToString(session, similarTrackId) << "'" <<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
FeatureSettingsMap
|
||||
breedFeatureSettingsMap(const FeatureSettingsMap& a, const FeatureSettingsMap& b)
|
||||
@@ -367,7 +416,7 @@ int main(int argc, char *argv[])
|
||||
// Create some random settings (i.e random population)
|
||||
std::vector<FeatureSettingsMap> initialPopulation;
|
||||
|
||||
constexpr std::size_t populationSize {10};
|
||||
constexpr std::size_t populationSize {200};
|
||||
constexpr std::size_t nbFeatures {5};
|
||||
|
||||
for (std::size_t i {}; i < populationSize; ++i)
|
||||
@@ -383,29 +432,31 @@ int main(int argc, char *argv[])
|
||||
initialPopulation.emplace_back(std::move(settings));
|
||||
}
|
||||
|
||||
FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.iterationCount = 8;
|
||||
trainSettings.sampleCountPerNeuron = 1.5;
|
||||
|
||||
GeneticAlgorithm<FeatureSettingsMap>::Params params;
|
||||
params.nbWorkers = nbWorkers;
|
||||
params.nbGenerations = 5;
|
||||
params.nbGenerations = 1;
|
||||
params.crossoverRatio = 0.78;
|
||||
params.mutationProbability = 0.2;
|
||||
params.breedFunction = breedFeatureSettingsMap;
|
||||
params.mutateFunction = mutateFeatureSettingsMap;
|
||||
params.scoreFunction =
|
||||
[&](const FeatureSettingsMap& settings)
|
||||
[&](const FeatureSettingsMap& featureSettings)
|
||||
{
|
||||
FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.iterationCount = 8;
|
||||
trainSettings.sampleCountPerNeuron = 1.5;
|
||||
trainSettings.featureSettingsMap = settings;
|
||||
FeaturesSearcher::TrainSettings settings {trainSettings};
|
||||
settings.featureSettingsMap = featureSettings;
|
||||
|
||||
Database::SessionPool::ScopedSession scopedSession {sessionPool};
|
||||
return computeSimilarityScore(scopedSession.get(), trainSettings, settings);
|
||||
return computeSimilarityScore(scopedSession.get(), settings);
|
||||
};
|
||||
|
||||
GeneticAlgorithm<FeatureSettingsMap> geneticAlgorithm {params};
|
||||
|
||||
std::cout << "Parameters:\n"
|
||||
<< "\tnb total settings = "<< featuresSettings.size() << "\n"
|
||||
<< "\tnb generations = " << params.nbGenerations << "\n"
|
||||
<< "\tpopulationSize = " << populationSize << "\n"
|
||||
<< "\tnbFeatures = " << nbFeatures << "\n"
|
||||
@@ -417,6 +468,15 @@ int main(int argc, char *argv[])
|
||||
const FeatureSettingsMap selectedSettings {geneticAlgorithm.simulate(initialPopulation)};
|
||||
std::cout << "Simulation complete! Best result:" << std::endl;
|
||||
printFeatureSettingsMap(selectedSettings);
|
||||
|
||||
// print all badly classified tracks
|
||||
{
|
||||
FeaturesSearcher::TrainSettings settings {trainSettings};
|
||||
settings.featureSettingsMap = selectedSettings;
|
||||
|
||||
Database::SessionPool::ScopedSession scopedSession {sessionPool};
|
||||
printBadlyClassifiedTracks(scopedSession.get(), settings);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@ lms_similarity_parameters_SOURCES = \
|
||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
||||
$(top_srcdir)/src/database/Session.cpp \
|
||||
$(top_srcdir)/src/database/SessionPool.cpp \
|
||||
$(top_srcdir)/src/database/SimilaritySettings.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
|
||||
@@ -42,54 +42,6 @@ int main(int argc, char *argv[])
|
||||
// log to stdout
|
||||
ServiceProvider<Logger>::create<StreamLogger>(std::cout);
|
||||
|
||||
const FeatureSettingsMap featuresSettings
|
||||
{
|
||||
/* { "lowlevel.average_loudness", 1 },
|
||||
{ "lowlevel.dynamic_complexity", 1 },
|
||||
{ "lowlevel.spectral_contrast_coeffs.median", {1} },
|
||||
{ "lowlevel.erbbands.median", {1} },
|
||||
{ "tonal.hpcp.median", {1} },
|
||||
{ "lowlevel.melbands.median", {1} },
|
||||
{ "lowlevel.barkbands.median", {1} },
|
||||
{ "lowlevel.mfcc.mean", {1} },
|
||||
{ "lowlevel.gfcc.mean", {1} },
|
||||
*/
|
||||
{ "lowlevel.spectral_kurtosis.median", {1}},
|
||||
{ "lowlevel.spectral_kurtosis.mean", {1}},
|
||||
{ "lowlevel.spectral_complexity.var", {1}},
|
||||
{ "lowlevel.barkbands.median", {1}},
|
||||
{ "lowlevel.barkbands_kurtosis.mean", {1}},
|
||||
/*
|
||||
{"lowlevel.spectral_centroid.dvar2", {1} },
|
||||
{"lowlevel.barkbands.median", {1} },
|
||||
{ "lowlevel.barkbands.dvar", {1} },
|
||||
{ "lowlevel.spectral_complexity.min", {1} },
|
||||
{ "lowlevel.pitch_salience.dmean2", {1} },
|
||||
{ "lowlevel.spectral_contrast_valleys.dmean", {1} },
|
||||
{ "lowlevel.pitch_salience.max", {1} },
|
||||
{ "lowlevel.barkbands.mean", {1} },
|
||||
{ "lowlevel.spectral_complexity.mean", {1} },
|
||||
{ "lowlevel.dissonance.dvar", {1} },
|
||||
*/
|
||||
/*
|
||||
{ "lowlevel.spectral_energy.dvar", {1} },
|
||||
{ "lowlevel.barkbands.min", {1} },
|
||||
{ "lowlevel.spectral_centroid.median", {1} },
|
||||
{"lowlevel.barkbands_kurtosis.median", {1} },
|
||||
{"lowlevel.spectral_energy.median", {1} },
|
||||
{"lowlevel.barkbands.max", {1} },
|
||||
{"lowlevel.barkbands_spread.var", {1} },
|
||||
{"lowlevel.spectral_decrease.var", {1} },
|
||||
{"lowlevel.spectral_contrast_valleys.dmean", {1} },
|
||||
{"lowlevel.barkbands_crest.mean", {1} },
|
||||
{"lowlevel.spectral_entropy.var", {1} },
|
||||
{"lowlevel.barkbands_crest.max", {1} },
|
||||
{"lowlevel.hfc.dvar", {1} },
|
||||
{"lowlevel.barkbands_skewness.dvar2", {1} },
|
||||
{"lowlevel.spectral_centroid.max", {1} },
|
||||
*/
|
||||
};
|
||||
|
||||
std::filesystem::path configFilePath {"/etc/lms.conf"};
|
||||
if (argc >= 2)
|
||||
configFilePath = std::string(argv[1], 0, 256);
|
||||
@@ -102,17 +54,17 @@ int main(int argc, char *argv[])
|
||||
std::cout << "Classifying tracks..." << std::endl;
|
||||
// may be long...
|
||||
struct FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.featureSettingsMap = featuresSettings;
|
||||
trainSettings.featureSettingsMap = FeaturesSearcher::getDefaultTrainFeatureSettings();
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
std::cout << "Classifying tracks DONE" << std::endl;
|
||||
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIds(session);
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
std::cout << "*** Tracks ***" << std::endl;
|
||||
std::cout << "*** Tracks (" << trackIds.size() << ") ***" << std::endl;
|
||||
for (Database::IdType trackId : trackIds)
|
||||
{
|
||||
auto trackToString = [&](Database::IdType trackId)
|
||||
|
||||
@@ -10,7 +10,6 @@ lms_similarity_SOURCES = \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
||||
$(top_srcdir)/src/database/Session.cpp \
|
||||
$(top_srcdir)/src/database/SimilaritySettings.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
|
||||
Reference in New Issue
Block a user