Bump Bliss version

Now using 3 tempo values, updated Bliss version.

_Note_: You should rebuild your database after upgrading to this commit.
Next major breaking changes will be handled by dedicated update scripts
to avoid having to rebuild the entire database.
This commit is contained in:
Lucas Verney 2016-07-24 15:31:18 +02:00
parent f1a88818b6
commit 345383e3a5
7 changed files with 72 additions and 21 deletions

View File

@ -5,7 +5,7 @@ Blissify is a wrapper around
[Bliss](https://github.com/Polochon-street/bliss) to compute and store values [Bliss](https://github.com/Polochon-street/bliss) to compute and store values
in an SQLite database. in an SQLite database.
It is done in an attempot to bind Bliss to MPD to be able to play It is done in an attempt to bind Bliss to MPD to be able to play
smooth mixes with MPD, _à la_ Grooveshark radio. smooth mixes with MPD, _à la_ Grooveshark radio.
## Dependencies ## Dependencies

2
bliss

@ -1 +1 @@
Subproject commit 4781124ff177fa1eb649b9b74993a0ae28b1e501 Subproject commit 582b96d6ed217016363c7d7d5b24ee10d179a946

View File

@ -2,5 +2,6 @@
#define CONSTANTS_H #define CONSTANTS_H
#define DEFAULT_STRING_LENGTH 10000 #define DEFAULT_STRING_LENGTH 10000
#define VERSION "0.1"
#endif // CONSTANTS_H #endif // CONSTANTS_H

View File

@ -146,7 +146,7 @@ def main(queue_length):
logging.info("Currently played song is %s." % (current_song,)) logging.info("Currently played song is %s." % (current_song,))
# Get current song coordinates # Get current song coordinates
cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs WHERE filename=?", (current_song,)) cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs WHERE filename=?", (current_song,))
current_song_coords = cur.fetchone() current_song_coords = cur.fetchone()
if current_song_coords is None: if current_song_coords is None:
logging.warning("Current song %s is not in db. You should update the db." % logging.warning("Current song %s is not in db. You should update the db." %
@ -158,7 +158,7 @@ def main(queue_length):
for i in range(queue_length): for i in range(queue_length):
# Get cached distances from db # Get cached distances from db
cur.execute( cur.execute(
"SELECT id, filename, distance, similarity, tempo, amplitude, frequency, attack FROM (SELECT s2.id AS id, s2.filename AS filename, s2.tempo AS tempo, s2.amplitude AS amplitude, s2.frequency AS frequency, s2.attack AS attack, distances.distance AS distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s1.filename=? UNION SELECT s1.id as id, s1.filename AS filename, s1.tempo AS tempo, s1.amplitude AS amplitude, s1.frequency AS frequency, s1.attack AS attack, distances.distance as distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s2.filename=?) ORDER BY distance ASC", "SELECT id, filename, distance, similarity, tempo1, tempo2, tempo3, amplitude, frequency, attack FROM (SELECT s2.id AS id, s2.filename AS filename, s2.tempo1 AS tempo1, s2.tempo2 AS tempo2, s2.tempo3 AS tempo3, s2.amplitude AS amplitude, s2.frequency AS frequency, s2.attack AS attack, distances.distance AS distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s1.filename=? UNION SELECT s1.id as id, s1.filename AS filename, s1.tempo1 AS tempo1, s1.tempo2 AS tempo2, s1.tempo3 AS tempo3, s1.amplitude AS amplitude, s1.frequency AS frequency, s1.attack AS attack, distances.distance as distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s2.filename=?) ORDER BY distance ASC",
(current_song_coords["filename"], current_song_coords["filename"])) (current_song_coords["filename"], current_song_coords["filename"]))
cached_distances = [row cached_distances = [row
for row in cur.fetchall() for row in cur.fetchall()
@ -181,7 +181,7 @@ def main(queue_length):
# Get all other songs coordinates # Get all other songs coordinates
closest_song = None closest_song = None
cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs") cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs")
for tmp_song_data in cur.fetchall(): for tmp_song_data in cur.fetchall():
if(tmp_song_data["filename"] == current_song_coords["filename"] or if(tmp_song_data["filename"] == current_song_coords["filename"] or
tmp_song_data["filename"] in cached_distances_songs or tmp_song_data["filename"] in cached_distances_songs or
@ -191,24 +191,32 @@ def main(queue_length):
continue continue
# Compute distance # Compute distance
distance = math.sqrt( distance = math.sqrt(
(current_song_coords["tempo"] - tmp_song_data["tempo"])**2 + (current_song_coords["tempo1"] - tmp_song_data["tempo1"])**2 +
(current_song_coords["tempo2"] - tmp_song_data["tempo2"])**2 +
(current_song_coords["tempo3"] - tmp_song_data["tempo3"])**2 +
(current_song_coords["amplitude"] - tmp_song_data["amplitude"])**2 + (current_song_coords["amplitude"] - tmp_song_data["amplitude"])**2 +
(current_song_coords["frequency"] - tmp_song_data["frequency"])**2 + (current_song_coords["frequency"] - tmp_song_data["frequency"])**2 +
(current_song_coords["attack"] - tmp_song_data["attack"])**2 (current_song_coords["attack"] - tmp_song_data["attack"])**2
) )
similarity = ( similarity = (
(current_song_coords["tempo"] * tmp_song_data["tempo"] + (current_song_coords["tempo1"] * tmp_song_data["tempo1"] +
current_song_coords["tempo2"] * tmp_song_data["tempo2"] +
current_song_coords["tempo3"] * tmp_song_data["tempo3"] +
current_song_coords["amplitude"] * tmp_song_data["amplitude"] + current_song_coords["amplitude"] * tmp_song_data["amplitude"] +
current_song_coords["frequency"] * tmp_song_data["frequency"] + current_song_coords["frequency"] * tmp_song_data["frequency"] +
current_song_coords["attack"] * tmp_song_data["attack"]) / current_song_coords["attack"] * tmp_song_data["attack"]) /
( (
math.sqrt( math.sqrt(
current_song_coords["tempo"]**2 + current_song_coords["tempo1"]**2 +
current_song_coords["tempo2"]**2 +
current_song_coords["tempo3"]**2 +
current_song_coords["amplitude"]**2 + current_song_coords["amplitude"]**2 +
current_song_coords["frequency"]**2 + current_song_coords["frequency"]**2 +
current_song_coords["attack"]**2) * current_song_coords["attack"]**2) *
math.sqrt( math.sqrt(
tmp_song_data["tempo"]**2 + tmp_song_data["tempo1"]**2 +
tmp_song_data["tempo2"]**2 +
tmp_song_data["tempo3"]**2 +
tmp_song_data["amplitude"]**2 + tmp_song_data["amplitude"]**2 +
tmp_song_data["frequency"]**2 + tmp_song_data["frequency"]**2 +
tmp_song_data["attack"]**2) tmp_song_data["attack"]**2)

View File

@ -25,7 +25,7 @@ def main():
cached_distances = cur.fetchall() cached_distances = cur.fetchall()
# Get all songs # Get all songs
cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs") cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs")
all_songs = cur.fetchall() all_songs = cur.fetchall()
for i in range(len(all_songs)): for i in range(len(all_songs)):
@ -42,24 +42,32 @@ def main():
continue continue
# Compute distance # Compute distance
distance = math.sqrt( distance = math.sqrt(
(song1["tempo"] - song2["tempo"])**2 + (song1["tempo1"] - song2["tempo1"])**2 +
(song1["tempo2"] - song2["tempo2"])**2 +
(song1["tempo3"] - song2["tempo3"])**2 +
(song1["amplitude"] - song2["amplitude"])**2 + (song1["amplitude"] - song2["amplitude"])**2 +
(song1["frequency"] - song2["frequency"])**2 + (song1["frequency"] - song2["frequency"])**2 +
(song1["attack"] - song2["attack"])**2 (song1["attack"] - song2["attack"])**2
) )
similarity = ( similarity = (
(song1["tempo"] * song2["tempo"] + (song1["tempo1"] * song2["tempo1"] +
song1["tempo2"] * song2["tempo2"] +
song1["tempo3"] * song2["tempo3"] +
song1["amplitude"] * song2["amplitude"] + song1["amplitude"] * song2["amplitude"] +
song1["frequency"] * song2["frequency"] + song1["frequency"] * song2["frequency"] +
song1["attack"] * song2["attack"]) / song1["attack"] * song2["attack"]) /
( (
math.sqrt( math.sqrt(
song1["tempo"]**2 + song1["tempo1"]**2 +
song1["tempo2"]**2 +
song1["tempo3"]**2 +
song1["amplitude"]**2 + song1["amplitude"]**2 +
song1["frequency"]**2 + song1["frequency"]**2 +
song1["attack"]**2) * song1["attack"]**2) *
math.sqrt( math.sqrt(
song2["tempo"]**2 + song2["tempo1"]**2 +
song2["tempo2"]**2 +
song2["tempo3"]**2 +
song2["amplitude"]**2 + song2["amplitude"]**2 +
song2["frequency"]**2 + song2["frequency"]**2 +
song2["attack"]**2) song2["attack"]**2)

View File

@ -47,7 +47,9 @@ int _init_db(char *data_folder, char* db_path)
} }
dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS songs( \ dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS songs( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
tempo REAL, \ tempo1 REAL, \
tempo2 REAL, \
tempo3 REAL, \
amplitude REAL, \ amplitude REAL, \
frequency REAL, \ frequency REAL, \
attack REAL, \ attack REAL, \
@ -80,6 +82,22 @@ int _init_db(char *data_folder, char* db_path)
sqlite3_close(dbh); sqlite3_close(dbh);
return 1; return 1;
} }
dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS metadata( \
name TEXT UNIQUE, \
value TEXT)", NULL, NULL, NULL);
if (SQLITE_OK != dberr) {
fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
sqlite3_close(dbh);
return 1;
}
sqlite3_stmt *res;
sqlite3_prepare_v2(dbh,
"INSERT INTO metadata(name, value) VALUES(?, ?)",
-1, &res, 0);
sqlite3_bind_text(res, 1, "version", strlen("version"), SQLITE_STATIC);
sqlite3_bind_text(res, 2, VERSION, strlen(VERSION), SQLITE_STATIC);
sqlite3_step(res);
sqlite3_finalize(res);
sqlite3_close(dbh); sqlite3_close(dbh);
return 0; return 0;
} }
@ -135,7 +153,7 @@ int _parse_music_helper(
} }
// Insert song analysis in database // Insert song analysis in database
dberr = sqlite3_prepare_v2(dbh, dberr = sqlite3_prepare_v2(dbh,
"INSERT INTO songs(tempo, amplitude, frequency, attack, filename) VALUES(?, ?, ?, ?, ?)", "INSERT INTO songs(tempo1, tempo2, tempo3, amplitude, frequency, attack, filename) VALUES(?, ?, ?, ?, ?)",
-1, &res, 0); -1, &res, 0);
if (SQLITE_OK != dberr) { if (SQLITE_OK != dberr) {
fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh)); fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh));
@ -152,11 +170,13 @@ int _parse_music_helper(
// Pass file // Pass file
return 1; return 1;
} }
sqlite3_bind_double(res, 1, song_analysis.force_vector.tempo); sqlite3_bind_double(res, 1, song_analysis.force_vector.tempo1);
sqlite3_bind_double(res, 2, song_analysis.force_vector.amplitude); sqlite3_bind_double(res, 2, song_analysis.force_vector.tempo2);
sqlite3_bind_double(res, 3, song_analysis.force_vector.frequency); sqlite3_bind_double(res, 3, song_analysis.force_vector.tempo3);
sqlite3_bind_double(res, 4, song_analysis.force_vector.attack); sqlite3_bind_double(res, 4, song_analysis.force_vector.amplitude);
sqlite3_bind_text(res, 5, song_uri, strlen(song_uri), SQLITE_STATIC); sqlite3_bind_double(res, 5, song_analysis.force_vector.frequency);
sqlite3_bind_double(res, 6, song_analysis.force_vector.attack);
sqlite3_bind_text(res, 7, song_uri, strlen(song_uri), SQLITE_STATIC);
dberr = sqlite3_step(res); dberr = sqlite3_step(res);
if (SQLITE_DONE != dberr) { if (SQLITE_DONE != dberr) {
// Free song analysis // Free song analysis

View File

@ -42,6 +42,20 @@ int main(int argc, char** argv) {
sqlite3_close(dbh); sqlite3_close(dbh);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
dberr = sqlite3_exec(dbh, "SELECT value FROM metadata WHERE name=version", NULL, NULL, NULL);
if (SQLITE_OK != dberr) {
fprintf(stderr, "Error while fetching data in db: %s\n\n", sqlite3_errmsg(dbh));
sqlite3_close(dbh);
exit(EXIT_FAILURE);
}
sqlite3_stmt *res = NULL;
while (sqlite3_step(res) == SQLITE_ROW) {
const char* version = (char*) sqlite3_column_text(res, 1);
if (strcmp(version, VERSION) != 0) {
fprintf(stderr, "DB is in an older version. Run update script and start again.\n");
exit(EXIT_FAILURE);
}
}
for (int i = 2; i < argc; ++i) { for (int i = 2; i < argc; ++i) {
_parse_music_helper(dbh, base_path, argv[i]); _parse_music_helper(dbh, base_path, argv[i]);