diff --git a/lib/include/lib/enum/audiofeature.hpp b/lib/include/lib/enum/audiofeature.hpp deleted file mode 100644 index 88fa1060..00000000 --- a/lib/include/lib/enum/audiofeature.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -namespace lib -{ - /** - * Category of audio analysis - */ - enum class audio_feature: unsigned char - { - /** - * Invalid, or missing, value - */ - unknown, - - /** - * Confidence track is acoustic - * @return 0.0 - 1.0 - */ - acousticness, - - /** - * How suitable track is for dancing - * @return 0.0 - 1.0 - */ - danceability, - - /** - * Track's intensity and activity - * @return 0.0 - 1.0 - */ - energy, - - /** - * Prediction of no vocals - * @return 0.0 - 1.0 - */ - instrumentalness, - - /** - * Key track is in - * @return audio_key - */ - key, - - /** - * Detects audience in recording - * @return 0.8> if track is live - */ - liveness, - - /** - * Average volume - * @return -60.0 - 0.0 dB - */ - loudness, - - /** - * Track modality - * @return audio_mode - */ - mode, - - /** - * Presence of spoken words (not vocals) - * @return <0.33 if music, 0.33 - 0.66 if music and speech, 0.66> if speech - */ - speechiness, - - /** - * Tempo - * @return BPM - */ - tempo, - - /** - * Overall time signature - * @return meter - */ - time_signature, - - /** - * How positive/happy the track is - * @return 0.0 - 1.0 - */ - valence, - }; -} diff --git a/lib/include/lib/enum/audiokey.hpp b/lib/include/lib/enum/audiokey.hpp deleted file mode 100644 index 509de1c7..00000000 --- a/lib/include/lib/enum/audiokey.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -namespace lib -{ - /** - * Key of track as pitch - * @note I'm no musician, so I have no idea what this means, or if it's accurate - * @see https://en.wikipedia.org/wiki/Pitch_class - */ - enum class audio_key: char - { - /** C */ - c = 0, - - /** C♯ or D♭ */ - c_sharp = 1, - - /** D */ - d = 2, - - /** D♯ or E♭ */ - d_sharp = 3, - - /** E */ - e = 4, - - /** F */ - f = 5, - - /** F♯ or G♭ */ - f_sharp = 6, - - /** G */ - g = 7, - - /** G♯ or A♭ */ - g_sharp = 8, - - /** A */ - a = 9, - - /** A♯, B♭ */ - a_sharp = 10, - - /** B */ - b = 11, - }; -} diff --git a/lib/include/lib/enum/audiomode.hpp b/lib/include/lib/enum/audiomode.hpp deleted file mode 100644 index c06f7956..00000000 --- a/lib/include/lib/enum/audiomode.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -namespace lib -{ - /** - * Audio mode, indicated by modality - * @note I'm no musician, so I have no idea what this means, or if it's accurate - */ - enum class audio_mode: char - { - /** Minor modality */ - minor = 0, - - /** Major modality */ - major = 1, - }; -} diff --git a/lib/include/lib/spotify/api.hpp b/lib/include/lib/spotify/api.hpp index 967d9a3e..b3f0181a 100644 --- a/lib/include/lib/spotify/api.hpp +++ b/lib/include/lib/spotify/api.hpp @@ -7,7 +7,6 @@ #include "lib/enum/repeatstate.hpp" #include "lib/spotify/album.hpp" #include "lib/spotify/artist.hpp" -#include "lib/spotify/audiofeatures.hpp" #include "lib/spotify/callback.hpp" #include "lib/spotify/episode.hpp" #include "lib/spotify/page.hpp" @@ -315,12 +314,6 @@ namespace lib void track(const std::string &track_id, lib::callback &callback); - void track_audio_features(const std::string &track_id, - lib::callback &callback); - - void track_audio_features(const std::vector &track_ids, - lib::callback> &callback); - //endregion //region User Profile diff --git a/lib/include/lib/spotify/audiofeature.hpp b/lib/include/lib/spotify/audiofeature.hpp deleted file mode 100644 index 2b41ccae..00000000 --- a/lib/include/lib/spotify/audiofeature.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include "lib/enum/audiofeature.hpp" -#include "lib/enum/audiokey.hpp" -#include "lib/enum/audiomode.hpp" -#include "lib/log.hpp" - -#include - -namespace lib -{ - namespace spt - { - class audio_feature - { - public: - /** - * Audio feature with value - * @param feature Category - * @param value Value - */ - audio_feature(lib::audio_feature feature, float value); - - /** Audio feature with key */ - explicit audio_feature(audio_key key); - - /** Audio feature with mode */ - explicit audio_feature(audio_mode mode); - - /** - * Get name of audio feature - */ - auto get_feature_string() const -> std::string; - - /** - * Get audio feature - */ - auto get_feature() const -> lib::audio_feature; - - /** - * Get name of value - */ - auto get_value_string() const -> std::string; - - /** - * Get value - */ - auto get_value() const -> float; - - /** - * Get minimum possible value - */ - auto get_min() const -> float; - - /** - * Get maximum possible value - */ - auto get_max() const -> float; - - /** - * Get value description - */ - auto get_description() const -> std::string; - - private: - lib::audio_feature feature = lib::audio_feature::unknown; - float minimum = 0.F; - float maximum = 1.F; - float value = 0.F; - std::string name; - - auto acousticness() const -> std::string; - auto danceability() const -> std::string; - auto energy() const -> std::string; - auto instrumentalness() const -> std::string; - auto liveness() const -> std::string; - auto loudness(float &min, float &max) const -> std::string; - auto speechiness() const -> std::string; - auto tempo(float &max) const -> std::string; - auto valence() const -> std::string; - auto time_signature(float &max) const -> std::string; - - static auto to_string(audio_key key) -> std::string; - static auto to_string(audio_mode mode) -> std::string; - }; - } -} diff --git a/lib/include/lib/spotify/audiofeatures.hpp b/lib/include/lib/spotify/audiofeatures.hpp deleted file mode 100644 index 6083b76e..00000000 --- a/lib/include/lib/spotify/audiofeatures.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "lib/format.hpp" -#include "lib/strings.hpp" -#include "lib/enum/audiokey.hpp" -#include "lib/enum/audiomode.hpp" -#include "lib/spotify/audiofeature.hpp" -#include "thirdparty/json.hpp" - -#include -#include -#include - -namespace lib -{ - namespace spt - { - /** - * Audio analysis features - */ - class audio_features - { - public: - audio_features() = default; - - auto items() const -> const std::vector &; - - void add(lib::audio_feature feature, float value); - void add(audio_key key); - void add(audio_mode mode); - - static auto to_audio_feature(const std::string &feature) -> lib::audio_feature; - - std::string track_uri; - - private: - std::vector values; - }; - - /** JSON -> Audio features */ - void from_json(const nlohmann::json &j, audio_features &a); - } -} diff --git a/lib/src/spotify/audiofeature.cpp b/lib/src/spotify/audiofeature.cpp deleted file mode 100644 index 4d8a9542..00000000 --- a/lib/src/spotify/audiofeature.cpp +++ /dev/null @@ -1,436 +0,0 @@ -#include "lib/spotify/audiofeature.hpp" - -/* - * The values here are based off the average distribution, not necessarily - * what actually "makes sense". The data used to be available from the - * Web API, but has been removed in the new design. - */ - -lib::spt::audio_feature::audio_feature(lib::audio_feature feature, float value) - : feature(feature), - value(value) -{ - switch (feature) - { - case lib::audio_feature::acousticness: - name = acousticness(); - break; - - case lib::audio_feature::danceability: - name = danceability(); - break; - - case lib::audio_feature::energy: - name = energy(); - break; - - case lib::audio_feature::instrumentalness: - name = instrumentalness(); - break; - - case lib::audio_feature::key: - break; - - case lib::audio_feature::liveness: - name = liveness(); - break; - - case lib::audio_feature::loudness: - name = loudness(minimum, maximum); - break; - - case lib::audio_feature::mode: - break; - - case lib::audio_feature::speechiness: - name = speechiness(); - break; - - case lib::audio_feature::tempo: - name = tempo(maximum); - break; - - case lib::audio_feature::valence: - name = valence(); - break; - - case lib::audio_feature::time_signature: - name = time_signature(maximum); - break; - - default: - lib::log::warn("Invalid value: {}", get_feature_string()); - break; - } -} - -lib::spt::audio_feature::audio_feature(lib::audio_key key) - : feature(lib::audio_feature::key), - value(static_cast(key)), - name(to_string(key)) -{ - // These values don't really make sense here, - // but it looks better - minimum = static_cast(audio_key::c); - maximum = static_cast(audio_key::b); -} - -lib::spt::audio_feature::audio_feature(lib::audio_mode mode) - : feature(lib::audio_feature::mode), - value(static_cast(mode)), - name(to_string(mode)) -{ - // These values don't really make sense here, - // but it looks better - minimum = static_cast(audio_mode::minor); - maximum = static_cast(audio_mode::major); -} - -auto lib::spt::audio_feature::acousticness() const -> std::string -{ - constexpr float no = 0.1F; - constexpr float probably_no = 0.4F; - constexpr float probably_yes = 0.7F; - - if (value <= no) - { - return "Not acoustic"; - } - - if (value <= probably_no) - { - return "Probably not acoustic"; - } - - if (value <= probably_yes) - { - return "Probably acoustic"; - } - - return "Acoustic"; -} - -auto lib::spt::audio_feature::danceability() const -> std::string -{ - constexpr float no_lower = 0.4F; - constexpr float no_higher = 0.85F; - - return value <= no_lower || value >= no_higher - ? "Not suitable" - : "Suitable"; -} - -auto lib::spt::audio_feature::energy() const -> std::string -{ - constexpr float very_low = 0.4F; - constexpr float low = 0.65F; - constexpr float medium = 0.8F; - constexpr float high = 0.95F; - - if (value <= very_low) - { - return "Very low"; - } - - if (value <= low) - { - return "Low"; - } - - if (value <= medium) - { - return "Medium"; - } - - if (value <= high) - { - return "High"; - } - - return "Very high"; -} - -auto lib::spt::audio_feature::instrumentalness() const -> std::string -{ - constexpr float no = 0.05F; - - return value <= no - ? "Not instrumental" - : "Instrumental"; -} - -auto lib::spt::audio_feature::liveness() const -> std::string -{ - constexpr float no = 0.05F; - constexpr float probably_no = 0.15F; - constexpr float probably_yes = 0.4F; - - if (value <= no) - { - return "Not live"; - } - - if (value <= probably_no) - { - return "Probably not live"; - } - - if (value <= probably_yes) - { - return "Probably live"; - } - - return "Live"; -} - -auto lib::spt::audio_feature::loudness(float &min, float &max) const -> std::string -{ - constexpr float min_value = -60.F; - constexpr float max_value = 0.F; - - min = min_value; - max = max_value; - - constexpr float very_quiet = -25.F; - constexpr float quiet = -15.F; - constexpr float loud = -2.5F; - - if (value <= very_quiet) - { - return "Very quiet"; - } - - if (value <= quiet) - { - return "Quiet"; - } - - if (value <= loud) - { - return "Loud"; - } - - return "Very loud"; -} - -auto lib::spt::audio_feature::speechiness() const -> std::string -{ - constexpr float speech = 0.6F; - constexpr float music = 0.8F; - - if (value <= speech) - { - return "Speech"; - } - - if (value >= music) - { - return "Music"; - } - - return "Mixed"; -} - -auto lib::spt::audio_feature::tempo(float &max) const -> std::string -{ - constexpr float max_value = 250.F; - max = max_value; - - constexpr float slow = 60.F; - constexpr float fast = 150.F; - - if (value <= slow) - { - return "Slow"; - } - - if (value >= fast) - { - return "Fast"; - } - - return "Average"; -} - -auto lib::spt::audio_feature::valence() const -> std::string -{ - constexpr float sad = 0.2F; - constexpr float happy = 0.7F; - - if (value <= sad) - { - return "Sad"; - } - - if (value >= happy) - { - return "Happy"; - } - - return "Mixed"; -} - -auto lib::spt::audio_feature::time_signature(float &max) const -> std::string -{ - // Time signature doesn't really have a maximum value? - max = value; - - return lib::fmt::format("{} m", static_cast(value)); -} - -auto lib::spt::audio_feature::get_feature_string() const -> std::string -{ - switch (feature) - { - case lib::audio_feature::unknown: - return "Unknown"; - - case lib::audio_feature::acousticness: - return "Acousticness"; - - case lib::audio_feature::danceability: - return "Danceability"; - - case lib::audio_feature::energy: - return "Energy"; - - case lib::audio_feature::instrumentalness: - return "Instrumentalness"; - - case lib::audio_feature::key: - return "Key"; - - case lib::audio_feature::liveness: - return "Liveness"; - - case lib::audio_feature::loudness: - return "Loudness"; - - case lib::audio_feature::mode: - return "Mode"; - - case lib::audio_feature::speechiness: - return "Speechiness"; - - case lib::audio_feature::tempo: - return "Tempo"; - - case lib::audio_feature::time_signature: - return "Time signature"; - - case lib::audio_feature::valence: - return "Valence"; - - default: - return "Unknown"; - } -} - -auto lib::spt::audio_feature::get_feature() const -> lib::audio_feature -{ - return feature; -} - -auto lib::spt::audio_feature::get_value_string() const -> std::string -{ - return name; -} - -auto lib::spt::audio_feature::get_value() const -> float -{ - return value; -} - -auto lib::spt::audio_feature::get_min() const -> float -{ - return minimum; -} - -auto lib::spt::audio_feature::get_max() const -> float -{ - return maximum; -} - -auto lib::spt::audio_feature::get_description() const -> std::string -{ - if (get_min() == 0.F && get_max() == 1.F) - { - return lib::fmt::format("{}%", get_value() * 100.F); - } - - std::string suffix; - if (feature == lib::audio_feature::loudness) - { - suffix = " dB"; - } - else if (feature == lib::audio_feature::tempo) - { - suffix = " BPM"; - } - else if (feature == lib::audio_feature::time_signature) - { - suffix = " m"; - } - - return lib::fmt::format("{}{}", get_value(), suffix); -} - -auto lib::spt::audio_feature::to_string(lib::audio_key key) -> std::string -{ - switch (key) - { - case lib::audio_key::c: - return "C"; - - case lib::audio_key::c_sharp: - return "C♯, D♭"; - - case lib::audio_key::d: - return "D"; - - case lib::audio_key::d_sharp: - return "D♯, E♭"; - - case lib::audio_key::e: - return "E"; - - case lib::audio_key::f: - return "F"; - - case lib::audio_key::f_sharp: - return "F♯, G♭"; - - case lib::audio_key::g: - return "G"; - - case lib::audio_key::g_sharp: - return "G♯, A♭"; - - case lib::audio_key::a: - return "A"; - - case lib::audio_key::a_sharp: - return "A♯, B♭"; - - case lib::audio_key::b: - return "B"; - - default: - return "?"; - } -} - -auto lib::spt::audio_feature::to_string(lib::audio_mode mode) -> std::string -{ - switch (mode) - { - case lib::audio_mode::minor: - return "Minor"; - - case lib::audio_mode::major: - return "Major"; - - default: - return "Unknown"; - } -} diff --git a/lib/src/spotify/audiofeatures.cpp b/lib/src/spotify/audiofeatures.cpp deleted file mode 100644 index 9aa82532..00000000 --- a/lib/src/spotify/audiofeatures.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "lib/spotify/audiofeatures.hpp" - -auto lib::spt::audio_features::items() const -> const std::vector & -{ - return values; -} - -void lib::spt::audio_features::add(lib::audio_feature feature, float value) -{ - values.emplace_back(feature, value); -} - -void lib::spt::audio_features::add(audio_key key) -{ - values.emplace_back(key); -} - -void lib::spt::audio_features::add(audio_mode mode) -{ - values.emplace_back(mode); -} - -auto lib::spt::audio_features::to_audio_feature(const std::string &feature) -> lib::audio_feature -{ - if (feature == "acousticness") - { - return lib::audio_feature::acousticness; - } - - if (feature == "danceability") - { - return lib::audio_feature::danceability; - } - - if (feature == "energy") - { - return lib::audio_feature::energy; - } - - if (feature == "instrumentalness") - { - return lib::audio_feature::instrumentalness; - } - - if (feature == "key") - { - return lib::audio_feature::key; - } - - if (feature == "liveness") - { - return lib::audio_feature::liveness; - } - - if (feature == "loudness") - { - return lib::audio_feature::loudness; - } - - if (feature == "mode") - { - return lib::audio_feature::mode; - } - - if (feature == "speechiness") - { - return lib::audio_feature::speechiness; - } - - if (feature == "tempo") - { - return lib::audio_feature::tempo; - } - - if (feature == "time_signature") - { - return lib::audio_feature::time_signature; - } - - if (feature == "valence") - { - return lib::audio_feature::valence; - } - - return lib::audio_feature::unknown; -} - -void lib::spt::from_json(const nlohmann::json &j, audio_features &a) -{ - if (!j.is_object()) - { - return; - } - - j.at("uri").get_to(a.track_uri); - - for (const auto &item: j.items()) - { - const auto feature = lib::spt::audio_features::to_audio_feature(item.key()); - if (feature == lib::audio_feature::unknown) - { - continue; - } - - if (feature == lib::audio_feature::key) - { - a.add(item.value().get()); - continue; - } - - if (feature == lib::audio_feature::mode) - { - a.add(item.value().get()); - continue; - } - - a.add(feature, item.value().get()); - } -} diff --git a/lib/src/spotifyapi/tracks.cpp b/lib/src/spotifyapi/tracks.cpp index 96819e60..4eaa03ef 100644 --- a/lib/src/spotifyapi/tracks.cpp +++ b/lib/src/spotifyapi/tracks.cpp @@ -2,28 +2,9 @@ // Currently unavailable: // tracks -// audio-analysis/{id} void lib::spt::api::track(const std::string &track_id, lib::callback &callback) { get(lib::fmt::format("tracks/{}", track_id), callback); } - -void lib::spt::api::track_audio_features(const std::string &track_id, - lib::callback &callback) -{ - get(lib::fmt::format("audio-features/{}", - lib::spt::uri_to_id(track_id)), callback); -} - -void lib::spt::api::track_audio_features(const std::vector &track_ids, - lib::callback> &callback) -{ - get(lib::fmt::format("audio-features?ids={}", - lib::strings::join(track_ids, ",")), - [callback](const nlohmann::json &json) - { - callback(json.at("audio_features")); - }); -}