diff options
Diffstat (limited to 'tools/tracker_compiler.cc')
| -rw-r--r-- | tools/tracker_compiler.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/tools/tracker_compiler.cc b/tools/tracker_compiler.cc new file mode 100644 index 0000000..491aebb --- /dev/null +++ b/tools/tracker_compiler.cc @@ -0,0 +1,159 @@ +#include <cstdio> +#include <fstream> +#include <iostream> +#include <string> +#include <vector> +#include <sstream> +#include <map> + +struct Sample { + std::string name; + float freq, dur, amp, attack, harmonic_decay; + int harmonics; +}; + +struct Event { + float beat; + std::string sample_name; + float volume, pan; +}; + +struct Pattern { + std::string name; + std::vector<Event> events; +}; + +struct Trigger { + float time; + std::string pattern_name; +}; + +int main(int argc, char** argv) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " <input.track> <output.cc>" << std::endl; + return 1; + } + + std::ifstream in(argv[1]); + if (!in.is_open()) { + std::cerr << "Could not open input file: " << argv[1] << std::endl; + return 1; + } + + float bpm = 120.0f; + std::vector<Sample> samples; + std::map<std::string, int> sample_map; + std::vector<Pattern> patterns; + std::map<std::string, int> pattern_map; + std::vector<Trigger> score; + + std::string line; + std::string current_section = ""; + + while (std::getline(in, line)) { + if (line.empty() || line[0] == '#') continue; + + std::stringstream ss(line); + std::string cmd; + ss >> cmd; + + if (cmd == "BPM") { + ss >> bpm; + } else if (cmd == "SAMPLE") { + Sample s; + std::string name; + ss >> name; + if (name.back() == ',') name.pop_back(); + s.name = name; + + // Very simple parsing: freq, dur, amp, attack, harmonics, harmonic_decay + char comma; + ss >> s.freq >> comma >> s.dur >> comma >> s.amp >> comma >> s.attack >> comma >> s.harmonics >> comma >> s.harmonic_decay; + + sample_map[s.name] = samples.size(); + samples.push_back(s); + } else if (cmd == "PATTERN") { + Pattern p; + ss >> p.name; + current_section = "PATTERN:" + p.name; + patterns.push_back(p); + pattern_map[p.name] = patterns.size() - 1; + } else if (cmd == "SCORE") { + current_section = "SCORE"; + } else { + if (current_section.rfind("PATTERN:", 0) == 0) { + // Parse event: beat, sample, vol, pan + Event e; + float beat; + std::stringstream ss2(line); + ss2 >> beat; + char comma; + ss2 >> comma; + std::string sname; + ss2 >> sname; + if (sname.back() == ',') sname.pop_back(); + e.beat = beat; + e.sample_name = sname; + ss2 >> e.volume >> comma >> e.pan; + patterns.back().events.push_back(e); + } else if (current_section == "SCORE") { + Trigger t; + float time; + std::stringstream ss2(line); + ss2 >> time; + char comma; + ss2 >> comma; + std::string pname; + ss2 >> pname; + t.time = time; + t.pattern_name = pname; + score.push_back(t); + } + } + } + + std::ofstream out(argv[2]); + out << "// Generated by tracker_compiler. Do not edit.\n\n"; + out << "#include \"audio/tracker.h\"\n\n"; + + out << "const NoteParams g_tracker_samples[] = {\n"; + for (const auto& s : samples) { + out << " { " << s.freq << "f, " << s.dur << "f, " << s.amp << "f, " << s.attack << "f, 0.0f, 0.0f, 0.0f, " + << s.harmonics << ", " << s.harmonic_decay << "f, 0.0f, 0.0f }, // " << s.name << "\n"; + } + out << "}; +"; + out << "const uint32_t g_tracker_samples_count = " << samples.size() << ";\n\n"; + + for (const auto& p : patterns) { + out << "static const TrackerEvent PATTERN_EVENTS_" << p.name << "[] = {\n"; + for (const auto& e : p.events) { + out << " { " << e.beat << "f, " << sample_map[e.sample_name] << ", " << e.volume << "f, " << e.pan << "f },\n"; + } + out << "}; +"; + } + out << "\n"; + + out << "const TrackerPattern g_tracker_patterns[] = {\n"; + for (const auto& p : patterns) { + out << " { PATTERN_EVENTS_" << p.name << ", " << p.events.size() << ", 4.0f }, // " << p.name << "\n"; + } + out << "}; +"; + out << "const uint32_t g_tracker_patterns_count = " << patterns.size() << ";\n\n"; + + out << "static const TrackerPatternTrigger SCORE_TRIGGERS[] = {\n"; + for (const auto& t : score) { + out << " { " << t.time << "f, " << pattern_map[t.pattern_name] << " },\n"; + } + out << "}; +\n"; + + out << "const TrackerScore g_tracker_score = {\n"; + out << " SCORE_TRIGGERS, " << score.size() << ", " << bpm << "f\n"; + out << "}; +"; + + return 0; +} |
