Reorganized sources, better accuracy for similarities based on features
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
#include "SimilaritySettings.hpp"
|
||||
#include "Track.hpp"
|
||||
#include "TrackList.hpp"
|
||||
#include "TrackFeature.hpp"
|
||||
#include "TrackFeatures.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
@@ -106,11 +106,11 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
|
||||
_session.mapClass<TrackListEntry>("tracklist_entry");
|
||||
_session.mapClass<Release>("release");
|
||||
_session.mapClass<Track>("track");
|
||||
_session.mapClass<TrackFeature>("track_feature");
|
||||
_session.mapClass<TrackFeatureType>("track_feature_type");
|
||||
_session.mapClass<TrackFeatures>("track_features");
|
||||
|
||||
_session.mapClass<ScanSettings>("scan_settings");
|
||||
_session.mapClass<SimilaritySettings>("similarity_settings");
|
||||
_session.mapClass<SimilaritySettingsFeature>("similarity_settings_feature");
|
||||
|
||||
_session.mapClass<AuthInfo>("auth_info");
|
||||
_session.mapClass<AuthInfo::AuthIdentityType>("auth_identity");
|
||||
@@ -142,10 +142,7 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS cluster_name_idx ON cluster(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS cluster_type_name_idx ON cluster_type(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS tracklist_name_idx ON tracklist(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_feature_type_name_idx ON track_feature_type(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_feature_type_idx ON track_feature(type_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_feature_track_idx ON track_feature(track_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_feature_type_track_idx ON track_feature(type_id, track_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_features_track_idx ON track_features(track_id)");
|
||||
}
|
||||
|
||||
_users = new UserDatabase(_session);
|
||||
|
||||
@@ -59,6 +59,7 @@ class Release : public Wt::Dbo::Dbo<Release>
|
||||
bool& moreExpected);
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracks(const std::set<IdType>& clusters = std::set<IdType>()) const;
|
||||
|
||||
// Get the cluster of the tracks that belong to this release
|
||||
// Each clusters are grouped by cluster type, sorted by the number of occurence
|
||||
// size is the max number of cluster per cluster type
|
||||
|
||||
@@ -22,53 +22,42 @@
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "TrackFeature.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
std::set<std::string> defaultTrackFeaturesNames =
|
||||
{
|
||||
"lowlevel.average_loudness",
|
||||
"lowlevel.barkbands_flatness_db.mean",
|
||||
"lowlevel.dissonance.mean",
|
||||
"lowlevel.dynamic_complexity",
|
||||
"lowlevel.hfc.mean", // GOOD
|
||||
"lowlevel.melbands_crest.mean",
|
||||
"lowlevel.melbands_kurtosis.mean",
|
||||
"lowlevel.melbands_skewness.mean",
|
||||
"lowlevel.melbands_spread.mean",
|
||||
"lowlevel.pitch_salience.mean",
|
||||
"lowlevel.pitch_salience.var",
|
||||
"lowlevel.silence_rate_30dB.mean",
|
||||
"lowlevel.silence_rate_60dB.mean",
|
||||
"lowlevel.spectral_centroid.mean",
|
||||
"lowlevel.spectral_complexity.mean",
|
||||
"lowlevel.spectral_decrease.mean",
|
||||
"lowlevel.spectral_energy.mean",
|
||||
"lowlevel.spectral_energyband_high.mean",
|
||||
"lowlevel.spectral_energyband_low.mean",
|
||||
"lowlevel.spectral_energyband_middle_high.mean",
|
||||
"lowlevel.spectral_energyband_middle_low.mean",
|
||||
"lowlevel.spectral_entropy.mean",
|
||||
"lowlevel.spectral_flux.mean",
|
||||
"lowlevel.spectral_kurtosis.mean",
|
||||
"lowlevel.spectral_rms.mean",
|
||||
"lowlevel.spectral_skewness.mean",
|
||||
"lowlevel.spectral_spread.mean",
|
||||
"lowlevel.spectral_strongpeak.mean",
|
||||
"lowlevel.zerocrossingrate.mean",
|
||||
"rhythm.beats_loudness.mean", // BAD
|
||||
"rhythm.bpm",
|
||||
"tonal.chords_changes_rate", // OK
|
||||
"tonal.chords_number_rate", // BAD
|
||||
"tonal.chords_strength.mean", // OK
|
||||
"tonal.hpcp_entropy.mean", // GOOD
|
||||
};
|
||||
|
||||
} // namespace
|
||||
#include "TrackFeatures.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
struct TrackFeatureInfo
|
||||
{
|
||||
std::string name;
|
||||
std::size_t nbDimensions;
|
||||
double weight;
|
||||
};
|
||||
|
||||
static std::vector<TrackFeatureInfo> defaultFeatures =
|
||||
{
|
||||
{ "lowlevel.spectral_contrast_coeffs.median", 6, 1. },
|
||||
{ "lowlevel.erbbands.median", 40, 1. },
|
||||
{ "tonal.hpcp.median", 36, 1. },
|
||||
{ "lowlevel.melbands.median", 40, 1. },
|
||||
{ "lowlevel.barkbands.median", 27, 1. },
|
||||
{ "lowlevel.mfcc.mean", 13, 1. },
|
||||
{ "lowlevel.gfcc.mean", 13, 1. },
|
||||
};
|
||||
|
||||
|
||||
SimilaritySettingsFeature::SimilaritySettingsFeature(Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, std::size_t nbDimensions, double weight)
|
||||
: _name(name),
|
||||
_nbDimensions(nbDimensions),
|
||||
_weight(weight),
|
||||
_settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
SimilaritySettingsFeature::pointer
|
||||
SimilaritySettingsFeature::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, std::size_t nbDimensions, double weight)
|
||||
{
|
||||
return session.add(std::make_unique<SimilaritySettingsFeature>(settings, name, nbDimensions, weight));
|
||||
}
|
||||
|
||||
SimilaritySettings::pointer
|
||||
SimilaritySettings::get(Wt::Dbo::Session& session)
|
||||
@@ -77,54 +66,20 @@ SimilaritySettings::get(Wt::Dbo::Session& session)
|
||||
if (!settings)
|
||||
{
|
||||
settings = session.add(std::make_unique<SimilaritySettings>());
|
||||
settings.modify()->setTrackFeatureTypes(defaultTrackFeaturesNames);
|
||||
|
||||
for (const auto& feature : defaultFeatures)
|
||||
SimilaritySettingsFeature::create(session, settings, feature.name, feature.nbDimensions, feature.weight);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<TrackFeatureType>>
|
||||
SimilaritySettings::getTrackFeatureTypes() const
|
||||
std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>>
|
||||
SimilaritySettings::getFeatures() const
|
||||
{
|
||||
return std::vector<Wt::Dbo::ptr<TrackFeatureType>>(_trackFeatureTypes.begin(), _trackFeatureTypes.end());
|
||||
return std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>>(_features.begin(), _features.end());
|
||||
}
|
||||
|
||||
void
|
||||
SimilaritySettings::setTrackFeatureTypes(const std::set<std::string>& featuresNames)
|
||||
{
|
||||
bool needRescan = false;
|
||||
assert(session());
|
||||
|
||||
// Create any missing feature type
|
||||
for (const auto& featureName : featuresNames)
|
||||
{
|
||||
auto featureType = TrackFeatureType::getByName(*session(), featureName);
|
||||
if (!featureType)
|
||||
{
|
||||
LMS_LOG(DB, INFO) << "Creating feature type " << featureName;
|
||||
featureType = TrackFeatureType::create(*session(), featureName);
|
||||
_trackFeatureTypes.insert(featureType);
|
||||
|
||||
needRescan = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete no longer existing feature type
|
||||
for (auto trackFeatureType : _trackFeatureTypes)
|
||||
{
|
||||
if (std::none_of(featuresNames.begin(), featuresNames.end(),
|
||||
[trackFeatureType](const std::string& name) { return name == trackFeatureType->getName(); }))
|
||||
{
|
||||
LMS_LOG(DB, INFO) << "Deleting track feature type " << trackFeatureType->getName();
|
||||
trackFeatureType.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (needRescan)
|
||||
_scanVersion += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Database
|
||||
|
||||
|
||||
@@ -23,42 +23,75 @@
|
||||
|
||||
namespace Database {
|
||||
|
||||
class TrackFeature;
|
||||
class TrackFeatureType;
|
||||
class SimilaritySettings;
|
||||
|
||||
class SimilaritySettings : public Wt::Dbo::Dbo<SimilaritySettings>
|
||||
class SimilaritySettingsFeature : public Wt::Dbo::Dbo<SimilaritySettingsFeature>
|
||||
{
|
||||
public:
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettings>;
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettingsFeature>;
|
||||
|
||||
static pointer get(Wt::Dbo::Session& session);
|
||||
SimilaritySettingsFeature() = default;
|
||||
SimilaritySettingsFeature(Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, std::size_t nbDimensions, double weight);
|
||||
|
||||
std::size_t getVersion() const { return _scanVersion; }
|
||||
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<SimilaritySettings> settings, const std::string& name, std::size_t nbDimensions, double weight = 1);
|
||||
|
||||
std::vector<Wt::Dbo::ptr<TrackFeatureType>> getTrackFeatureTypes() const;
|
||||
void setTrackFeatureTypes(const std::set<std::string>& featureTypeNames);
|
||||
|
||||
void setNetworkData(std::string data) { _refFeaturesData = data; }
|
||||
const std::string& getNetworkData() const { return _refFeaturesData; }
|
||||
|
||||
void setNormalizationData(std::string data) { _normalizationData = data; }
|
||||
const std::string& getNormalizationData() const { return _normalizationData; }
|
||||
const std::string& getName() const { return _name; } ;
|
||||
std::size_t getNbDimensions() const { return static_cast<std::size_t>(_nbDimensions); }
|
||||
double getWeight() const { return _weight; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _scanVersion, "settings_version");
|
||||
Wt::Dbo::field(a, _normalizationData, "normalization_data");
|
||||
Wt::Dbo::field(a, _refFeaturesData, "ref_features_data");
|
||||
Wt::Dbo::hasMany(a, _trackFeatureTypes, Wt::Dbo::ManyToOne, "similarity_settings");
|
||||
Wt::Dbo::field(a, _name, "name");
|
||||
Wt::Dbo::field(a, _nbDimensions, "dimension_count");
|
||||
Wt::Dbo::field(a, _weight, "weight");
|
||||
|
||||
Wt::Dbo::belongsTo(a, _settings, "similarity_settings", Wt::Dbo::OnDeleteCascade);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
int _nbDimensions;
|
||||
double _weight;
|
||||
|
||||
Wt::Dbo::ptr<SimilaritySettings> _settings;
|
||||
};
|
||||
|
||||
class SimilaritySettings : public Wt::Dbo::Dbo<SimilaritySettings>
|
||||
{
|
||||
public:
|
||||
|
||||
enum class PreferredMethod
|
||||
{
|
||||
Auto,
|
||||
Features,
|
||||
Clusters,
|
||||
};
|
||||
|
||||
using pointer = Wt::Dbo::ptr<SimilaritySettings>;
|
||||
|
||||
// Utils
|
||||
static pointer get(Wt::Dbo::Session& session);
|
||||
|
||||
// Accessors
|
||||
std::size_t getVersion() const { return _settingsVersion; }
|
||||
PreferredMethod getPreferredMethod() const { return _preferredMethod; }
|
||||
std::vector<Wt::Dbo::ptr<SimilaritySettingsFeature>> getFeatures() const;
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _settingsVersion, "settings_version");
|
||||
Wt::Dbo::field(a, _preferredMethod, "preferred_method");
|
||||
|
||||
Wt::Dbo::hasMany(a, _features, Wt::Dbo::ManyToOne, "similarity_settings");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _scanVersion = 0;
|
||||
std::string _normalizationData;
|
||||
std::string _refFeaturesData;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<TrackFeatureType>> _trackFeatureTypes;
|
||||
int _settingsVersion = 0;
|
||||
PreferredMethod _preferredMethod = PreferredMethod::Auto;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<SimilaritySettingsFeature>> _features;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+7
-13
@@ -26,7 +26,7 @@
|
||||
#include "Artist.hpp"
|
||||
#include "Cluster.hpp"
|
||||
#include "Release.hpp"
|
||||
#include "TrackFeature.hpp"
|
||||
#include "TrackFeatures.hpp"
|
||||
#include "SqlQuery.hpp"
|
||||
|
||||
namespace Database {
|
||||
@@ -114,7 +114,7 @@ Track::getAllWithMBIDAndMissingFeatures(Wt::Dbo::Session& session)
|
||||
Wt::Dbo::collection<pointer> res = session.query<pointer>
|
||||
("SELECT t FROM track t")
|
||||
.where("LENGTH(t.mbid) > 0")
|
||||
.where("NOT EXISTS (SELECT * FROM track_feature t_f WHERE t_f.track_id = t.id)");
|
||||
.where("NOT EXISTS (SELECT * FROM track_features t_f WHERE t_f.track_id = t.id)");
|
||||
return std::vector<pointer>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ Track::getAllWithFeatures(Wt::Dbo::Session& session)
|
||||
{
|
||||
Wt::Dbo::collection<pointer> res = session.query<pointer>
|
||||
("SELECT t FROM track t")
|
||||
.where("EXISTS (SELECT * from track_feature t_f WHERE t_f.track_id = t.id)");
|
||||
.where("EXISTS (SELECT * from track_features t_f WHERE t_f.track_id = t.id)");
|
||||
return std::vector<pointer>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ Track::getClusters(void) const
|
||||
bool
|
||||
Track::hasTrackFeatures() const
|
||||
{
|
||||
return !_trackFeatures.empty();
|
||||
return (_trackFeatures.lock() != Database::TrackFeatures::pointer());
|
||||
}
|
||||
|
||||
static
|
||||
@@ -262,16 +262,10 @@ Track::getCopyrightURL() const
|
||||
return _copyrightURL != "" ? boost::make_optional<std::string>(_copyrightURL) : boost::none;
|
||||
}
|
||||
|
||||
Wt::Dbo::ptr<TrackFeature>
|
||||
Track::getTrackFeature(Wt::Dbo::ptr<TrackFeatureType> type) const
|
||||
Wt::Dbo::ptr<TrackFeatures>
|
||||
Track::getTrackFeatures() const
|
||||
{
|
||||
assert(self());
|
||||
assert(IdIsValid(self()->id()));
|
||||
assert(session());
|
||||
|
||||
return session()->find<TrackFeature>()
|
||||
.where("type_id = ?").bind(type.id())
|
||||
.where("track_id = ?").bind(self()->id());
|
||||
return _trackFeatures.lock();
|
||||
}
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>>
|
||||
|
||||
+5
-11
@@ -37,8 +37,7 @@ class Artist;
|
||||
class Cluster;
|
||||
class ClusterType;
|
||||
class Release;
|
||||
class TrackFeature;
|
||||
class TrackFeatureType;
|
||||
class TrackFeatures;
|
||||
class TrackListEntry;
|
||||
class TrackStats;
|
||||
|
||||
@@ -81,7 +80,6 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
|
||||
// Accessors
|
||||
void setScanVersion(std::size_t version) { _scanVersion = version; }
|
||||
void setSimilarityScanVersion(std::size_t version) { _similarityScanVersion = version; }
|
||||
void setTrackNumber(int num) { _trackNumber = num; }
|
||||
void setTotalTrackNumber(int num) { _totalTrackNumber = num; }
|
||||
void setDiscNumber(int num) { _discNumber = num; }
|
||||
@@ -101,10 +99,9 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
void setArtist(Wt::Dbo::ptr<Artist> artist) { _artist = artist; }
|
||||
void setRelease(Wt::Dbo::ptr<Release> release) { _release = release; }
|
||||
void eraseClusters() { _clusters.clear(); }
|
||||
void eraseFeatures() { _trackFeatures.clear(); }
|
||||
void eraseFeatures() { /*_trackFeatures.reset();*/ }
|
||||
|
||||
std::size_t getScanVersion() const { return _scanVersion; }
|
||||
std::size_t getSimilarityScanVersion() const { return _similarityScanVersion; }
|
||||
boost::optional<std::size_t> getTrackNumber() const;
|
||||
boost::optional<std::size_t> getTotalTrackNumber() const;
|
||||
boost::optional<std::size_t> getDiscNumber() const;
|
||||
@@ -124,9 +121,8 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
Wt::Dbo::ptr<Artist> getArtist() const { return _artist; }
|
||||
Wt::Dbo::ptr<Release> getRelease() const { return _release; }
|
||||
std::vector<Wt::Dbo::ptr<Cluster>> getClusters() const;
|
||||
std::vector<Wt::Dbo::ptr<TrackFeature>> getTrackFeatures() const; // ordered by feature's name
|
||||
bool hasTrackFeatures() const;
|
||||
Wt::Dbo::ptr<TrackFeature> getTrackFeature(Wt::Dbo::ptr<TrackFeatureType> type) const;
|
||||
Wt::Dbo::ptr<TrackFeatures> getTrackFeatures() const;
|
||||
|
||||
std::vector<std::vector<Wt::Dbo::ptr<Cluster>>> getClusterGroups(std::vector<Wt::Dbo::ptr<ClusterType>> clusterTypes, std::size_t size) const;
|
||||
|
||||
@@ -134,7 +130,6 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _scanVersion, "scan_version");
|
||||
Wt::Dbo::field(a, _similarityScanVersion, "similarity_version");
|
||||
Wt::Dbo::field(a, _trackNumber, "track_number");
|
||||
Wt::Dbo::field(a, _totalTrackNumber, "total_track_number");
|
||||
Wt::Dbo::field(a, _discNumber, "disc_number");
|
||||
@@ -156,7 +151,7 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
Wt::Dbo::belongsTo(a, _artist, "artist", Wt::Dbo::OnDeleteCascade);
|
||||
Wt::Dbo::hasMany(a, _clusters, Wt::Dbo::ManyToMany, "track_cluster", "", Wt::Dbo::OnDeleteCascade);
|
||||
Wt::Dbo::hasMany(a, _playlistEntries, Wt::Dbo::ManyToOne, "track");
|
||||
Wt::Dbo::hasMany(a, _trackFeatures, Wt::Dbo::ManyToOne, "track");
|
||||
Wt::Dbo::hasOne(a, _trackFeatures);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -166,7 +161,6 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
static const std::size_t _maxCopyrightURLLength = 128;
|
||||
|
||||
int _scanVersion = 0;
|
||||
int _similarityScanVersion = 0;
|
||||
int _trackNumber = 0;
|
||||
int _totalTrackNumber = 0;
|
||||
int _discNumber = 0;
|
||||
@@ -191,7 +185,7 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
Wt::Dbo::ptr<Release> _release;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Cluster>> _clusters;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<TrackListEntry>> _playlistEntries;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<TrackFeature>> _trackFeatures;
|
||||
Wt::Dbo::weak_ptr<TrackFeatures> _trackFeatures;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,58 +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 "TrackFeature.hpp"
|
||||
|
||||
#include "SimilaritySettings.hpp"
|
||||
#include "Track.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
TrackFeatureType::TrackFeatureType(std::string name)
|
||||
: _name(name)
|
||||
{
|
||||
}
|
||||
|
||||
TrackFeatureType::pointer
|
||||
TrackFeatureType::getByName(Wt::Dbo::Session& session, std::string name)
|
||||
{
|
||||
return session.find<TrackFeatureType>().where("name = ?").bind(name);
|
||||
}
|
||||
|
||||
TrackFeatureType::pointer
|
||||
TrackFeatureType::create(Wt::Dbo::Session& session, std::string name)
|
||||
{
|
||||
return session.add(std::make_unique<TrackFeatureType>(name));
|
||||
}
|
||||
|
||||
|
||||
TrackFeature::TrackFeature(Wt::Dbo::ptr<TrackFeatureType> type, Wt::Dbo::ptr<Track> track, double value)
|
||||
: _type(type),
|
||||
_track(track),
|
||||
_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
TrackFeature::pointer
|
||||
TrackFeature::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<TrackFeatureType> type, Wt::Dbo::ptr<Track> track, double value)
|
||||
{
|
||||
return session.add(std::make_unique<TrackFeature>(type, track, value));
|
||||
}
|
||||
|
||||
} // namespace Database
|
||||
@@ -1,97 +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 <string>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
class Track;
|
||||
class SimilaritySettings;
|
||||
|
||||
class TrackFeatureType : public Wt::Dbo::Dbo<TrackFeatureType>
|
||||
{
|
||||
public:
|
||||
using pointer = Wt::Dbo::ptr<TrackFeatureType>;
|
||||
|
||||
TrackFeatureType() = default;
|
||||
TrackFeatureType(std::string name);
|
||||
|
||||
// Find utility
|
||||
static pointer getByName(Wt::Dbo::Session& session, std::string name);
|
||||
|
||||
// Create utility
|
||||
static pointer create(Wt::Dbo::Session& session, std::string name);
|
||||
|
||||
// Accessors
|
||||
const std::string& getName() const { return _name; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _name, "name");
|
||||
Wt::Dbo::belongsTo(a, _similaritySettings, "similarity_settings", Wt::Dbo::OnDeleteCascade);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::string _name;
|
||||
|
||||
Wt::Dbo::ptr<SimilaritySettings> _similaritySettings;
|
||||
};
|
||||
|
||||
class TrackFeature : public Wt::Dbo::Dbo<TrackFeature>
|
||||
{
|
||||
public:
|
||||
|
||||
using pointer = Wt::Dbo::ptr<TrackFeature>;
|
||||
|
||||
TrackFeature() = default;
|
||||
TrackFeature(Wt::Dbo::ptr<TrackFeatureType> type, Wt::Dbo::ptr<Track> track, double value);
|
||||
|
||||
// Create utility
|
||||
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<TrackFeatureType> type, Wt::Dbo::ptr<Track> track, double value);
|
||||
|
||||
Wt::Dbo::ptr<TrackFeatureType> getType() const { return _type; }
|
||||
double getValue() const { return _value; }
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _value, "value");
|
||||
Wt::Dbo::belongsTo(a, _type, "type", Wt::Dbo::OnDeleteCascade);
|
||||
Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Wt::Dbo::ptr<TrackFeatureType> _type;
|
||||
Wt::Dbo::ptr<Track> _track;
|
||||
double _value = 0.;
|
||||
};
|
||||
|
||||
|
||||
} // namespace database
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 "TrackFeatures.hpp"
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "Track.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
TrackFeatures::TrackFeatures(Wt::Dbo::ptr<Track> track, const std::string& jsonEncodedFeatures)
|
||||
: _data(jsonEncodedFeatures),
|
||||
_track(track)
|
||||
{
|
||||
}
|
||||
|
||||
TrackFeatures::pointer
|
||||
TrackFeatures::create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, const std::string& jsonEncodedFeatures)
|
||||
{
|
||||
return session.add(std::make_unique<TrackFeatures>(track, jsonEncodedFeatures));
|
||||
}
|
||||
|
||||
std::vector<double>
|
||||
TrackFeatures::getFeatures(const std::string& featureNode) const
|
||||
{
|
||||
std::vector<double> res;
|
||||
|
||||
std::map<std::string, std::vector<double>> features = { {featureNode, {}} };
|
||||
if (!getFeatures( features ))
|
||||
return res;
|
||||
|
||||
res = std::move(features[featureNode]);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
TrackFeatures::getFeatures(std::map<std::string /*name*/, std::vector<double> /*values*/>& features) const
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::property_tree::ptree root;
|
||||
|
||||
std::istringstream iss(_data);
|
||||
boost::property_tree::read_json(iss, root);
|
||||
|
||||
for (auto& featureNode : features)
|
||||
{
|
||||
auto node = root.get_child(featureNode.first);
|
||||
|
||||
bool hasChildren = false;
|
||||
for (const auto& child : node.get_child(""))
|
||||
{
|
||||
hasChildren = true;
|
||||
featureNode.second.push_back(child.second.get_value<double>());
|
||||
}
|
||||
|
||||
if (!hasChildren)
|
||||
{
|
||||
featureNode.second.push_back(node.get_value<double>());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (boost::property_tree::ptree_error& error)
|
||||
{
|
||||
LMS_LOG(DB, ERROR) << "ptree exception: " << error.what();
|
||||
std::cout << "ptree exception: " << error.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Database
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
namespace Database {
|
||||
|
||||
class Track;
|
||||
|
||||
class TrackFeatures : public Wt::Dbo::Dbo<TrackFeatures>
|
||||
{
|
||||
public:
|
||||
|
||||
using pointer = Wt::Dbo::ptr<TrackFeatures>;
|
||||
|
||||
TrackFeatures() = default;
|
||||
TrackFeatures(Wt::Dbo::ptr<Track> track, const std::string& jsonEncodedFeatures);
|
||||
|
||||
// Create utility
|
||||
static pointer create(Wt::Dbo::Session& session, Wt::Dbo::ptr<Track> track, const std::string& jsonEncodedFeatures);
|
||||
|
||||
std::vector<double> getFeatures(const std::string& featureNode) const;
|
||||
bool getFeatures(std::map<std::string /*featureNode*/, std::vector<double> /*values*/>& featureNodes) const;
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
{
|
||||
Wt::Dbo::field(a, _data, "data");
|
||||
Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::string _data;
|
||||
Wt::Dbo::ptr<Track> _track;
|
||||
};
|
||||
|
||||
|
||||
} // namespace database
|
||||
|
||||
|
||||
Reference in New Issue
Block a user