Compare commits
2 Commits
f020592491
...
d1a2ac6ab9
| Author | SHA1 | Date | |
|---|---|---|---|
| d1a2ac6ab9 | |||
| f5121bc2ad |
272
assets/songs/json/mary.json
Normal file
272
assets/songs/json/mary.json
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"keySignatures": [],
|
||||||
|
"meta": [],
|
||||||
|
"name": "",
|
||||||
|
"ppq": 480,
|
||||||
|
"tempos": [
|
||||||
|
{
|
||||||
|
"bpm": 120,
|
||||||
|
"ticks": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeSignatures": [
|
||||||
|
{
|
||||||
|
"ticks": 0,
|
||||||
|
"timeSignature": [
|
||||||
|
4,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"measures": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tracks": [
|
||||||
|
{
|
||||||
|
"channel": 0,
|
||||||
|
"controlChanges": {
|
||||||
|
"1": [
|
||||||
|
{
|
||||||
|
"number": 1,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"6": [
|
||||||
|
{
|
||||||
|
"number": 6,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.5039370078740157
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 6,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.5039370078740157
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 6,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.09448818897637795
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"7": [
|
||||||
|
{
|
||||||
|
"number": 7,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.7874015748031497
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10": [
|
||||||
|
{
|
||||||
|
"number": 10,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.5039370078740157
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"11": [
|
||||||
|
{
|
||||||
|
"number": 11,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"38": [
|
||||||
|
{
|
||||||
|
"number": 38,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"100": [
|
||||||
|
{
|
||||||
|
"number": 100,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.015748031496062992
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 100,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0.007874015748031496
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 100,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"101": [
|
||||||
|
{
|
||||||
|
"number": 101,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 101,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"number": 101,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"121": [
|
||||||
|
{
|
||||||
|
"number": 121,
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pitchBends": [
|
||||||
|
{
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"instrument": {
|
||||||
|
"family": "piano",
|
||||||
|
"number": 0,
|
||||||
|
"name": "acoustic grand piano"
|
||||||
|
},
|
||||||
|
"name": "",
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 64,
|
||||||
|
"name": "E4",
|
||||||
|
"ticks": 0,
|
||||||
|
"time": 0,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 62,
|
||||||
|
"name": "D4",
|
||||||
|
"ticks": 480,
|
||||||
|
"time": 0.5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 60,
|
||||||
|
"name": "C4",
|
||||||
|
"ticks": 960,
|
||||||
|
"time": 1,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 62,
|
||||||
|
"name": "D4",
|
||||||
|
"ticks": 1440,
|
||||||
|
"time": 1.5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 64,
|
||||||
|
"name": "E4",
|
||||||
|
"ticks": 1920,
|
||||||
|
"time": 2,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 64,
|
||||||
|
"name": "E4",
|
||||||
|
"ticks": 2400,
|
||||||
|
"time": 2.5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 1,
|
||||||
|
"durationTicks": 960,
|
||||||
|
"midi": 64,
|
||||||
|
"name": "E4",
|
||||||
|
"ticks": 2880,
|
||||||
|
"time": 3,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 62,
|
||||||
|
"name": "D4",
|
||||||
|
"ticks": 3840,
|
||||||
|
"time": 4,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 62,
|
||||||
|
"name": "D4",
|
||||||
|
"ticks": 4320,
|
||||||
|
"time": 4.5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 1,
|
||||||
|
"durationTicks": 960,
|
||||||
|
"midi": 62,
|
||||||
|
"name": "D4",
|
||||||
|
"ticks": 4800,
|
||||||
|
"time": 5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 64,
|
||||||
|
"name": "E4",
|
||||||
|
"ticks": 5760,
|
||||||
|
"time": 6,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 0.5,
|
||||||
|
"durationTicks": 480,
|
||||||
|
"midi": 67,
|
||||||
|
"name": "G4",
|
||||||
|
"ticks": 6240,
|
||||||
|
"time": 6.5,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"duration": 1,
|
||||||
|
"durationTicks": 960,
|
||||||
|
"midi": 67,
|
||||||
|
"name": "G4",
|
||||||
|
"ticks": 6720,
|
||||||
|
"time": 7,
|
||||||
|
"velocity": 0.7874015748031497
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endOfTrackTicks": 7680
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -10,7 +10,9 @@ struct Note {
|
|||||||
std::string name;
|
std::string name;
|
||||||
int midi;
|
int midi;
|
||||||
int duration_ticks;
|
int duration_ticks;
|
||||||
|
int duration_ms; // Duration of the note in milliseconds
|
||||||
int ticks;
|
int ticks;
|
||||||
|
int position_ms; // How many milliseconds into the song the note occurs
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instrument {
|
struct Instrument {
|
||||||
@ -26,6 +28,9 @@ struct Track {
|
|||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
int ppq;
|
||||||
|
float bpm;
|
||||||
|
double tempo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Song {
|
struct Song {
|
||||||
@ -33,6 +38,13 @@ struct Song {
|
|||||||
std::vector<Track> tracks;
|
std::vector<Track> tracks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int ticksToMilliseconds(int ticks, double tempo, int ppq) {
|
||||||
|
double microseconds = (ticks * tempo) / ppq;
|
||||||
|
|
||||||
|
// Convert to milliseconds with rounding
|
||||||
|
return static_cast<int>(microseconds / 1000.0 + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
Song parseSong(const rapidjson::Document& doc) {
|
Song parseSong(const rapidjson::Document& doc) {
|
||||||
assert(doc.IsObject());
|
assert(doc.IsObject());
|
||||||
|
|
||||||
@ -42,6 +54,13 @@ Song parseSong(const rapidjson::Document& doc) {
|
|||||||
const auto& h = doc["header"].GetObject();
|
const auto& h = doc["header"].GetObject();
|
||||||
Header header;
|
Header header;
|
||||||
header.name = h["name"].GetString();
|
header.name = h["name"].GetString();
|
||||||
|
header.ppq = h["ppq"].GetInt();
|
||||||
|
printf("header has tempos: %d\n", h.HasMember("tempos"));
|
||||||
|
if (h.HasMember("tempos") && h["tempos"].IsArray()) {
|
||||||
|
const auto& tempos = h["tempos"].GetArray();
|
||||||
|
header.bpm = tempos[0]["bpm"].GetFloat();
|
||||||
|
header.tempo = 60000000.0 / header.bpm;
|
||||||
|
}
|
||||||
song.header = header;
|
song.header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +85,9 @@ Song parseSong(const rapidjson::Document& doc) {
|
|||||||
note.name = n["name"].GetString();
|
note.name = n["name"].GetString();
|
||||||
note.midi = n["midi"].GetInt();
|
note.midi = n["midi"].GetInt();
|
||||||
note.duration_ticks = n["durationTicks"].GetInt();
|
note.duration_ticks = n["durationTicks"].GetInt();
|
||||||
|
note.duration_ms = ticksToMilliseconds(note.duration_ticks, song.header.tempo, song.header.ppq);
|
||||||
note.ticks = n["ticks"].GetInt();
|
note.ticks = n["ticks"].GetInt();
|
||||||
|
note.position_ms = ticksToMilliseconds(note.ticks, song.header.tempo, song.header.ppq);
|
||||||
track.notes.push_back(note);
|
track.notes.push_back(note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,8 +32,11 @@ int main(int argc, char** argv)
|
|||||||
game.add_scene<TitleScreen>("title");
|
game.add_scene<TitleScreen>("title");
|
||||||
game.add_scene<GHHBScene>("ghhb");
|
game.add_scene<GHHBScene>("ghhb");
|
||||||
|
|
||||||
Song& song = song_manager->load_song("tetris", "assets/songs/json/tetris.json");
|
Song& song = song_manager->load_song("mary_had_a_lil_lamb", "assets/songs/json/mary.json");
|
||||||
printf("Song name: %s\n", song.header.name.c_str());
|
printf("Song name: %s\n", song.header.name.c_str());
|
||||||
|
printf("Song bpm: %f\n", song.header.bpm);
|
||||||
|
printf("Song tempo: %f\n", song.header.tempo);
|
||||||
|
printf("First note duration: %d\n", song.tracks[0].notes[0].duration_ms);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user