summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/tracker_compiler.cc118
1 files changed, 117 insertions, 1 deletions
diff --git a/tools/tracker_compiler.cc b/tools/tracker_compiler.cc
index b4c72b2..5cecbb8 100644
--- a/tools/tracker_compiler.cc
+++ b/tools/tracker_compiler.cc
@@ -1,3 +1,4 @@
+#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
@@ -12,6 +13,72 @@ enum SampleType {
ASSET
};
+// Convert note name (e.g., "C4", "A#3", "Eb2") to frequency in Hz
+static float note_name_to_freq(const std::string& note_name) {
+ if (note_name.empty())
+ return 0.0f;
+
+ // Parse note (C, C#, D, etc.) and octave
+ const char* str = note_name.c_str();
+ char note_char = str[0];
+ int semitone = 0;
+
+ // Map note name to semitone (C=0, D=2, E=4, F=5, G=7, A=9, B=11)
+ switch (note_char) {
+ case 'C':
+ semitone = 0;
+ break;
+ case 'D':
+ semitone = 2;
+ break;
+ case 'E':
+ semitone = 4;
+ break;
+ case 'F':
+ semitone = 5;
+ break;
+ case 'G':
+ semitone = 7;
+ break;
+ case 'A':
+ semitone = 9;
+ break;
+ case 'B':
+ semitone = 11;
+ break;
+ default:
+ return 0.0f; // Invalid note
+ }
+
+ int idx = 1;
+ // Check for sharp (#) or flat (b)
+ if (str[idx] == '#') {
+ semitone++;
+ idx++;
+ } else if (str[idx] == 'b') {
+ semitone--;
+ idx++;
+ }
+
+ // Parse octave
+ int octave = atoi(&str[idx]);
+
+ // A4 = 440 Hz is our reference (A4 = octave 4, semitone 9)
+ // Formula: freq = 440 * 2^((semitone - 9 + 12*(octave - 4)) / 12)
+ const int midi_note = semitone + 12 * (octave + 1);
+ const int a4_midi = 69; // A4 = MIDI note 69
+ const float freq = 440.0f * powf(2.0f, (midi_note - a4_midi) / 12.0f);
+
+ return freq;
+}
+
+static bool is_note_name(const std::string& name) {
+ if (name.empty())
+ return false;
+ const char first = name[0];
+ return (first >= 'A' && first <= 'G');
+}
+
struct Sample {
std::string name;
SampleType type = GENERATED; // Default to GENERATED
@@ -119,6 +186,22 @@ int main(int argc, char** argv) {
e.beat = beat;
e.sample_name = sname;
ss2 >> e.volume >> comma >> e.pan;
+
+ // Auto-create SAMPLE entry for note names (e.g., "E2", "A4")
+ if (is_note_name(sname) && sample_map.find(sname) == sample_map.end()) {
+ Sample s;
+ s.name = sname;
+ s.type = GENERATED;
+ s.freq = note_name_to_freq(sname);
+ s.dur = 0.5f; // Default note duration
+ s.amp = 1.0f; // Default amplitude
+ s.attack = 0.01f; // Default attack
+ s.harmonics = 3; // Default harmonics
+ s.harmonic_decay = 0.6f; // Default decay
+ sample_map[s.name] = samples.size();
+ samples.push_back(s);
+ }
+
patterns.back().events.push_back(e);
} else if (current_section == "SCORE") {
Trigger t;
@@ -206,9 +289,42 @@ int main(int argc, char** argv) {
fprintf(out_file, "const TrackerScore g_tracker_score = {\n");
fprintf(out_file, " SCORE_TRIGGERS, %zu, %.1ff\n", score.size(), bpm);
- fprintf(out_file, "};\n");
+ fprintf(out_file, "};\n\n");
+
+ // Calculate maximum simultaneous patterns for optimal resource allocation
+ std::map<float, int> time_pattern_count;
+ for (const auto& t : score) {
+ time_pattern_count[t.time]++;
+ }
+
+ int max_simultaneous_patterns = 0;
+ for (const auto& entry : time_pattern_count) {
+ if (entry.second > max_simultaneous_patterns) {
+ max_simultaneous_patterns = entry.second;
+ }
+ }
+
+ // Add safety margin (2x) for overlapping pattern playback
+ const int recommended_voices = max_simultaneous_patterns * 2;
+ const int recommended_spectrograms = max_simultaneous_patterns * 2;
+
+ fprintf(out_file, "// Resource usage analysis:\n");
+ fprintf(out_file, "// Maximum simultaneous pattern triggers: %d\n",
+ max_simultaneous_patterns);
+ fprintf(out_file, "// Recommended MAX_VOICES: %d (current: see synth.h)\n",
+ recommended_voices);
+ fprintf(out_file,
+ "// Recommended MAX_SPECTROGRAMS: %d (current: see synth.h)\n",
+ recommended_spectrograms);
fclose(out_file);
+ printf("Tracker compilation successful.\n");
+ printf(" Patterns: %zu\n", patterns.size());
+ printf(" Score triggers: %zu\n", score.size());
+ printf(" Max simultaneous patterns: %d\n", max_simultaneous_patterns);
+ printf(" Recommended MAX_VOICES: %d\n", recommended_voices);
+ printf(" Recommended MAX_SPECTROGRAMS: %d\n", recommended_spectrograms);
+
return 0;
}