about summary refs log tree commit diff stats
path: root/generator
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-03-28 15:49:50 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-03-28 15:49:50 -0400
commit251248adfab36b061eb8fdd08aa54b318462da65 (patch)
tree4ff1eb792a1e1b442ec2fa6a99e01b28518c5cf4 /generator
parentaf49d3435302118d036c512aef1def848fb88089 (diff)
downloadcadence-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.txt2
-rw-r--r--generator/generator.cpp109
-rw-r--r--generator/mood.cpp94
-rw-r--r--generator/mood.h60
-rw-r--r--generator/schema.sql10
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
12add_executable(generator mood.cpp generator.cpp main.cpp) 12add_executable(generator generator.cpp main.cpp)
13set_property(TARGET generator PROPERTY CXX_STANDARD 11) 13set_property(TARGET generator PROPERTY CXX_STANDARD 11)
14set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) 14set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON)
15target_link_libraries(generator ${sqlite3_LIBRARIES}) 15target_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
11namespace cadence { 10namespace 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
3namespace 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
6namespace 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 @@
1CREATE TABLE `songs` ( 1CREATE 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
7CREATE TABLE `moods` (
8 `song_id` INTEGER,
9 `mood` VARCHAR(255),
10 PRIMARY KEY (`song_id`, `mood`)
11) WITHOUT ROWID;