#pragma once #include "rapidjson/document.h" #include "rapidjson/filereadstream.h" #include #include // Added: needed for std::string #include // Added: needed for std::vector #include // Added: needed for assert struct Note { std::string name; int midi; int duration_ticks; int duration_ms; // Duration of the note in milliseconds int ticks; int position_ms; // How many milliseconds into the song the note occurs }; struct Instrument { std::string family; int number; }; struct Track { std::string name; Instrument instrument; std::vector notes; }; struct Header { std::string name; std::string artist; int ppq; float bpm; }; struct Song { Header header; std::vector tracks; }; Song parseSong(const rapidjson::Document& doc) { assert(doc.IsObject()); Song song; if (doc.HasMember("header") && doc["header"].IsObject()) { const auto& h = doc["header"].GetObject(); Header header; header.name = h.HasMember("name") && h["name"].IsString() ? h["name"].GetString() : ""; header.artist = h.HasMember("artist") && h["artist"].IsString() ? h["artist"].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(); } song.header = header; } if (doc.HasMember("tracks") && doc["tracks"].IsArray()) { const auto& a = doc["tracks"].GetArray(); for (auto& t : a) { Track track; track.name = t["name"].GetString(); if (t.HasMember("instrument") && t["instrument"].IsObject()) { // Fixed: added closing parenthesis const auto& i = t["instrument"].GetObject(); Instrument instrument; instrument.family = i["family"].GetString(); instrument.number = i["number"].GetInt(); track.instrument = instrument; } // Fixed: removed extra closing parenthesis if (t.HasMember("notes") && t["notes"].IsArray()) { const auto& notes = t["notes"].GetArray(); for (auto& n : notes) { Note note; note.name = n["name"].GetString(); note.midi = n["midi"].GetInt(); note.duration_ticks = n["durationTicks"].GetInt(); note.duration_ms = n["duration"].GetFloat() * 1000; note.ticks = n["ticks"].GetInt(); note.position_ms = n["time"].GetFloat() * 1000; track.notes.push_back(note); } } song.tracks.push_back(track); } } return song; }