diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-03-28 15:49:50 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-03-28 15:49:50 -0400 |
commit | 251248adfab36b061eb8fdd08aa54b318462da65 (patch) | |
tree | 4ff1eb792a1e1b442ec2fa6a99e01b28518c5cf4 /generator | |
parent | af49d3435302118d036c512aef1def848fb88089 (diff) | |
download | cadence-251248adfab36b061eb8fdd08aa54b318462da65.tar.gz cadence-251248adfab36b061eb8fdd08aa54b318462da65.tar.bz2 cadence-251248adfab36b061eb8fdd08aa54b318462da65.zip |
Revamped bot with new algorithm
The percentages currently used by the generator are trial-and-error and may be changed in the future. refs #1
Diffstat (limited to 'generator')
-rw-r--r-- | generator/CMakeLists.txt | 2 | ||||
-rw-r--r-- | generator/generator.cpp | 109 | ||||
-rw-r--r-- | generator/mood.cpp | 94 | ||||
-rw-r--r-- | generator/mood.h | 60 | ||||
-rw-r--r-- | generator/schema.sql | 10 |
5 files changed, 94 insertions, 181 deletions
diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt index dffbe0e..8031f6a 100644 --- a/generator/CMakeLists.txt +++ b/generator/CMakeLists.txt | |||
@@ -9,7 +9,7 @@ include_directories( | |||
9 | vendor/json | 9 | vendor/json |
10 | ../vendor/hkutil) | 10 | ../vendor/hkutil) |
11 | 11 | ||
12 | add_executable(generator mood.cpp generator.cpp main.cpp) | 12 | add_executable(generator generator.cpp main.cpp) |
13 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) | 13 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) |
14 | set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) | 14 | set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) |
15 | target_link_libraries(generator ${sqlite3_LIBRARIES}) | 15 | target_link_libraries(generator ${sqlite3_LIBRARIES}) |
diff --git a/generator/generator.cpp b/generator/generator.cpp index 19eba70..4244fd2 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <json.hpp> | 6 | #include <json.hpp> |
7 | #include <hkutil/progress.h> | 7 | #include <hkutil/progress.h> |
8 | #include <hkutil/string.h> | 8 | #include <hkutil/string.h> |
9 | #include "mood.h" | ||
10 | 9 | ||
11 | namespace cadence { | 10 | namespace cadence { |
12 | namespace generator { | 11 | namespace generator { |
@@ -93,7 +92,8 @@ namespace cadence { | |||
93 | DIR* subdir; | 92 | DIR* subdir; |
94 | if ((subdir = opendir(directory.c_str())) == nullptr) | 93 | if ((subdir = opendir(directory.c_str())) == nullptr) |
95 | { | 94 | { |
96 | throw std::invalid_argument("Invalid AcousticBrainz data directory"); | 95 | throw std::invalid_argument( |
96 | "Invalid AcousticBrainz data directory"); | ||
97 | } | 97 | } |
98 | 98 | ||
99 | struct dirent* subent; | 99 | struct dirent* subent; |
@@ -106,7 +106,8 @@ namespace cadence { | |||
106 | DIR* subsubdir; | 106 | DIR* subsubdir; |
107 | if ((subsubdir = opendir(subdirectory.c_str())) == nullptr) | 107 | if ((subsubdir = opendir(subdirectory.c_str())) == nullptr) |
108 | { | 108 | { |
109 | throw std::invalid_argument("Invalid AcousticBrainz data directory"); | 109 | throw std::invalid_argument( |
110 | "Invalid AcousticBrainz data directory"); | ||
110 | } | 111 | } |
111 | 112 | ||
112 | struct dirent* subsubent; | 113 | struct dirent* subsubent; |
@@ -149,27 +150,87 @@ namespace cadence { | |||
149 | 150 | ||
150 | try | 151 | try |
151 | { | 152 | { |
152 | std::vector<mood> moods; | 153 | auto& hl = jsonData["highlevel"]; |
153 | moods.emplace_back(mood::type::danceable, jsonData["highlevel"]["danceability"]["all"]["danceable"]); | 154 | |
154 | moods.emplace_back(mood::type::acoustic, jsonData["highlevel"]["mood_acoustic"]["all"]["acoustic"]); | 155 | double danceable = hl["danceability"]["all"]["danceable"]; |
155 | moods.emplace_back(mood::type::aggressive, jsonData["highlevel"]["mood_aggressive"]["all"]["aggressive"]); | 156 | double acoustic = hl["mood_acoustic"]["all"]["acoustic"]; |
156 | moods.emplace_back(mood::type::electronic, jsonData["highlevel"]["mood_electronic"]["all"]["electronic"]); | 157 | double aggressive = hl["mood_aggressive"]["all"]["aggressive"]; |
157 | moods.emplace_back(mood::type::happy, jsonData["highlevel"]["mood_happy"]["all"]["happy"]); | 158 | double electronic = hl["mood_electronic"]["all"]["electronic"]; |
158 | moods.emplace_back(mood::type::party, jsonData["highlevel"]["mood_party"]["all"]["party"]); | 159 | double happy = hl["mood_happy"]["all"]["happy"]; |
159 | moods.emplace_back(mood::type::relaxed, jsonData["highlevel"]["mood_relaxed"]["all"]["relaxed"]); | 160 | double party = hl["mood_party"]["all"]["party"]; |
160 | moods.emplace_back(mood::type::sad, jsonData["highlevel"]["mood_sad"]["all"]["sad"]); | 161 | double relaxed = hl["mood_relaxed"]["all"]["relaxed"]; |
161 | moods.emplace_back(mood::type::instrumental, jsonData["highlevel"]["voice_instrumental"]["all"]["instrumental"]); | 162 | double sad = hl["mood_sad"]["all"]["sad"]; |
162 | 163 | double instrumental = hl["voice_instrumental"]["all"]["instrumental"]; | |
163 | std::sort(std::begin(moods), std::end(moods), [] (const mood& left, const mood& right) -> bool { | 164 | |
164 | return left.getProbability() > right.getProbability(); | 165 | std::string title = jsonData["metadata"]["tags"]["title"][0]; |
165 | }); | 166 | std::string artist = jsonData["metadata"]["tags"]["artist"][0]; |
166 | 167 | ||
167 | std::list<hatkirby::column> columns; | 168 | uint64_t songId = db_.insertIntoTable( |
168 | columns.emplace_back("title", jsonData["metadata"]["tags"]["title"][0].get<std::string>()); | 169 | "songs", |
169 | columns.emplace_back("artist", jsonData["metadata"]["tags"]["artist"][0].get<std::string>()); | 170 | { |
170 | columns.emplace_back("category", moods.front().getCategory()); | 171 | { "title", title }, |
171 | 172 | { "artist", artist } | |
172 | db_.insertIntoTable("songs", std::move(columns)); | 173 | }); |
174 | |||
175 | std::list<std::string> moods; | ||
176 | |||
177 | // ~38% | ||
178 | if ((party > 0.5) || (danceable > 0.75)) | ||
179 | { | ||
180 | moods.push_back("party"); | ||
181 | } | ||
182 | |||
183 | // ~38% | ||
184 | if ((relaxed > 0.81) || (acoustic > 0.5)) | ||
185 | { | ||
186 | moods.push_back("chill"); | ||
187 | } | ||
188 | |||
189 | // ~42% | ||
190 | if ((aggressive > 0.5) || (electronic > 0.95)) | ||
191 | { | ||
192 | moods.push_back("crazy"); | ||
193 | } | ||
194 | |||
195 | // ~30% | ||
196 | if (happy > 0.5) | ||
197 | { | ||
198 | moods.push_back("happy"); | ||
199 | } | ||
200 | |||
201 | // ~30% | ||
202 | if (sad > 0.5) | ||
203 | { | ||
204 | moods.push_back("sad"); | ||
205 | } | ||
206 | |||
207 | // ~38% | ||
208 | if (instrumental > 0.9) | ||
209 | { | ||
210 | moods.push_back("instrumental"); | ||
211 | } | ||
212 | |||
213 | // ~34% | ||
214 | if (instrumental < 0.2) | ||
215 | { | ||
216 | moods.push_back("vocal"); | ||
217 | } | ||
218 | |||
219 | // ~1% | ||
220 | if (moods.empty()) | ||
221 | { | ||
222 | moods.push_back("unknown"); | ||
223 | } | ||
224 | |||
225 | for (const std::string& mood : moods) | ||
226 | { | ||
227 | db_.insertIntoTable( | ||
228 | "moods", | ||
229 | { | ||
230 | { "song_id", static_cast<int>(songId) }, | ||
231 | { "mood", mood } | ||
232 | }); | ||
233 | } | ||
173 | } catch (const std::domain_error& ex) | 234 | } catch (const std::domain_error& ex) |
174 | { | 235 | { |
175 | // Weird data. Ignore silently. | 236 | // Weird data. Ignore silently. |
diff --git a/generator/mood.cpp b/generator/mood.cpp deleted file mode 100644 index b74211c..0000000 --- a/generator/mood.cpp +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | #include "mood.h" | ||
2 | |||
3 | namespace cadence { | ||
4 | namespace generator { | ||
5 | |||
6 | // The categories are: | ||
7 | // - party (+danceable, -acoustic, +electronic, +party) = ~.21 | ||
8 | // - chill (-danceable, +acoustic, -aggressive, -electronic, -party, +relaxed) = ~.49 | ||
9 | // - crazy (+aggressive, -relaxed) = ~.02 | ||
10 | // - happy (+happy, -sad) = ~.009 | ||
11 | // - sad (-happy, +sad) = ~.02 | ||
12 | // - instrumental (+instrumental) = ~.12 | ||
13 | // - vocal (-instrumental) = ~.10 | ||
14 | |||
15 | mood::mood(type t, double prob) : type_(t) | ||
16 | { | ||
17 | if (prob >= 0.5) | ||
18 | { | ||
19 | probability_ = prob; | ||
20 | positive_ = true; | ||
21 | } else { | ||
22 | probability_ = 1.0 - prob; | ||
23 | positive_ = false; | ||
24 | } | ||
25 | |||
26 | switch (t) | ||
27 | { | ||
28 | case type::danceable: | ||
29 | { | ||
30 | category_ = (positive_ ? "party" : "chill"); | ||
31 | |||
32 | break; | ||
33 | } | ||
34 | |||
35 | case type::acoustic: | ||
36 | { | ||
37 | category_ = (positive_ ? "chill" : "party"); | ||
38 | |||
39 | break; | ||
40 | } | ||
41 | |||
42 | case type::aggressive: | ||
43 | { | ||
44 | category_ = (positive_ ? "crazy" : "chill"); | ||
45 | |||
46 | break; | ||
47 | } | ||
48 | |||
49 | case type::electronic: | ||
50 | { | ||
51 | category_ = (positive_ ? "party" : "chill"); | ||
52 | |||
53 | break; | ||
54 | } | ||
55 | |||
56 | case type::happy: | ||
57 | { | ||
58 | category_ = (positive_ ? "happy" : "sad"); | ||
59 | |||
60 | break; | ||
61 | } | ||
62 | |||
63 | case type::party: | ||
64 | { | ||
65 | category_ = (positive_ ? "party" : "chill"); | ||
66 | |||
67 | break; | ||
68 | } | ||
69 | |||
70 | case type::relaxed: | ||
71 | { | ||
72 | category_ = (positive_ ? "chill" : "crazy"); | ||
73 | |||
74 | break; | ||
75 | } | ||
76 | |||
77 | case type::sad: | ||
78 | { | ||
79 | category_ = (positive_ ? "sad" : "happy"); | ||
80 | |||
81 | break; | ||
82 | } | ||
83 | |||
84 | case type::instrumental: | ||
85 | { | ||
86 | category_ = (positive_ ? "instrumental" : "vocal"); | ||
87 | |||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | }; | ||
94 | }; | ||
diff --git a/generator/mood.h b/generator/mood.h deleted file mode 100644 index c36e5ee..0000000 --- a/generator/mood.h +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | #ifndef MOOD_H_B9A39F40 | ||
2 | #define MOOD_H_B9A39F40 | ||
3 | |||
4 | #include <string> | ||
5 | |||
6 | namespace cadence { | ||
7 | namespace generator { | ||
8 | |||
9 | class mood { | ||
10 | public: | ||
11 | enum class type { | ||
12 | danceable, | ||
13 | acoustic, | ||
14 | aggressive, | ||
15 | electronic, | ||
16 | happy, | ||
17 | party, | ||
18 | relaxed, | ||
19 | sad, | ||
20 | instrumental | ||
21 | }; | ||
22 | |||
23 | // Constructor | ||
24 | |||
25 | mood(type t, double prob); | ||
26 | |||
27 | // Accessors | ||
28 | |||
29 | type getType() const | ||
30 | { | ||
31 | return type_; | ||
32 | } | ||
33 | |||
34 | double getProbability() const | ||
35 | { | ||
36 | return probability_; | ||
37 | } | ||
38 | |||
39 | bool getPositive() const | ||
40 | { | ||
41 | return positive_; | ||
42 | } | ||
43 | |||
44 | std::string getCategory() const | ||
45 | { | ||
46 | return category_; | ||
47 | } | ||
48 | |||
49 | private: | ||
50 | type type_; | ||
51 | double probability_; | ||
52 | bool positive_; | ||
53 | std::string category_; | ||
54 | |||
55 | }; | ||
56 | |||
57 | }; | ||
58 | }; | ||
59 | |||
60 | #endif /* end of include guard: MOOD_H_B9A39F40 */ | ||
diff --git a/generator/schema.sql b/generator/schema.sql index 879ebb3..7d211ba 100644 --- a/generator/schema.sql +++ b/generator/schema.sql | |||
@@ -1,5 +1,11 @@ | |||
1 | CREATE TABLE `songs` ( | 1 | CREATE TABLE `songs` ( |
2 | `song_id` INTEGER PRIMARY KEY, | ||
2 | `title` VARCHAR(255) NOT NULL, | 3 | `title` VARCHAR(255) NOT NULL, |
3 | `artist` VARCHAR(255) NOT NULL, | 4 | `artist` VARCHAR(255) NOT NULL |
4 | `category` VARCHAR(255) NOT NULL | ||
5 | ); | 5 | ); |
6 | |||
7 | CREATE TABLE `moods` ( | ||
8 | `song_id` INTEGER, | ||
9 | `mood` VARCHAR(255), | ||
10 | PRIMARY KEY (`song_id`, `mood`) | ||
11 | ) WITHOUT ROWID; | ||