From 65f6866b985fb3d0993fc2b6798c74015fb4fa6a Mon Sep 17 00:00:00 2001 From: skal Date: Fri, 13 Feb 2026 08:55:18 +0100 Subject: Refactor: Extract duplicate logic in compiler tools Consolidate repeated timeline/resource analysis code to improve maintainability and reduce duplication. seq_compiler.cc changes: - Extract timeline analysis (max time, sorting) into analyze_timeline() - Extract sequence end calculation into get_sequence_end() - Reduces ~45 lines of duplicate code tracker_compiler.cc changes: - Extract resource analysis into ResourceAnalysis struct - Consolidate sample counting and recommendations - Reduces ~75 lines of duplicate code Both tools verified with successful builds. Co-Authored-By: Claude Sonnet 4.5 --- tools/tracker_compiler.cc | 186 ++++++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 82 deletions(-) (limited to 'tools/tracker_compiler.cc') diff --git a/tools/tracker_compiler.cc b/tools/tracker_compiler.cc index 6784209..43b4185 100644 --- a/tools/tracker_compiler.cc +++ b/tools/tracker_compiler.cc @@ -116,6 +116,95 @@ struct Trigger { std::string pattern_name; }; +// Resource usage analysis for synth configuration +struct ResourceAnalysis { + int asset_sample_count; + int generated_sample_count; + int max_simultaneous_patterns; + int avg_events_per_pattern; + int estimated_max_polyphony; + int min_spectrograms; + int recommended_spectrograms; + int recommended_voices; +}; + +// Analyze resource requirements from tracker data +ResourceAnalysis analyze_resources(const std::vector& samples, + const std::vector& patterns, + const std::vector& score) { + ResourceAnalysis result = {}; + + // Count sample types + for (const auto& s : samples) { + if (s.type == ASSET) { + result.asset_sample_count++; + } else { + result.generated_sample_count++; + } + } + + // Calculate maximum simultaneous pattern triggers + std::map time_pattern_count; + for (const auto& t : score) { + time_pattern_count[t.time]++; + } + + for (const auto& entry : time_pattern_count) { + if (entry.second > result.max_simultaneous_patterns) { + result.max_simultaneous_patterns = entry.second; + } + } + + // Calculate average events per pattern + int total_events = 0; + for (const auto& p : patterns) { + total_events += p.events.size(); + } + result.avg_events_per_pattern = + patterns.empty() ? 0 : total_events / patterns.size(); + result.estimated_max_polyphony = + result.max_simultaneous_patterns * result.avg_events_per_pattern; + + // Conservative recommendations with 50% safety margin + result.min_spectrograms = result.asset_sample_count + + (result.generated_sample_count * + result.estimated_max_polyphony); + result.recommended_spectrograms = (int)(result.min_spectrograms * 1.5f); + result.recommended_voices = result.estimated_max_polyphony * 2; + + return result; +} + +// Write resource analysis to output file +void write_resource_analysis(FILE* out, const ResourceAnalysis& analysis, + int total_samples) { + fprintf(out, "// ============================================================\n"); + fprintf(out, "// RESOURCE USAGE ANALYSIS (for synth.h configuration)\n"); + fprintf(out, "// ============================================================\n"); + fprintf(out, "// Total samples: %d (%d assets + %d generated notes)\n", + total_samples, analysis.asset_sample_count, + analysis.generated_sample_count); + fprintf(out, "// Max simultaneous pattern triggers: %d\n", + analysis.max_simultaneous_patterns); + fprintf(out, "// Estimated max polyphony: %d voices\n", + analysis.estimated_max_polyphony); + fprintf(out, "// \n"); + fprintf(out, "// REQUIRED (minimum to avoid pool exhaustion):\n"); + fprintf(out, "// MAX_VOICES: %d\n", analysis.estimated_max_polyphony); + fprintf(out, "// MAX_SPECTROGRAMS: %d (no caching)\n", + analysis.min_spectrograms); + fprintf(out, "// \n"); + fprintf(out, "// RECOMMENDED (with 50%% safety margin):\n"); + fprintf(out, "// MAX_VOICES: %d\n", analysis.recommended_voices); + fprintf(out, "// MAX_SPECTROGRAMS: %d (no caching)\n", + analysis.recommended_spectrograms); + fprintf(out, "// \n"); + fprintf(out, "// NOTE: With spectrogram caching by note parameters,\n"); + fprintf(out, "// MAX_SPECTROGRAMS could be reduced to ~%d\n", + analysis.asset_sample_count + analysis.generated_sample_count); + fprintf(out, "// ============================================================\n\n"); +} + int main(int argc, char** argv) { if (argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); @@ -314,102 +403,35 @@ int main(int argc, char** argv) { fprintf(out_file, " SCORE_TRIGGERS, %zu, %.1ff\n", score.size(), bpm); fprintf(out_file, "};\n\n"); - // ============================================================================ - // RESOURCE USAGE ANALYSIS - // ============================================================================ - - // Count unique samples - int asset_sample_count = 0; - int generated_sample_count = 0; - for (const auto& s : samples) { - if (s.type == ASSET) { - asset_sample_count++; - } else { - generated_sample_count++; - } - } + // Analyze resource requirements + ResourceAnalysis analysis = analyze_resources(samples, patterns, score); - // Calculate maximum simultaneous pattern triggers - std::map 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; - } - } - - // Calculate maximum polyphony (events per pattern on average) - int total_events = 0; - for (const auto& p : patterns) { - total_events += p.events.size(); - } - const int avg_events_per_pattern = - patterns.empty() ? 0 : total_events / patterns.size(); - const int estimated_max_polyphony = - max_simultaneous_patterns * avg_events_per_pattern; - - // Conservative recommendations with safety margins - // - Each asset sample needs 1 spectrogram slot (shared across all events) - // - Each generated note needs 1 spectrogram slot PER EVENT (no caching yet) - // - Add 50% safety margin for peak moments - const int min_spectrograms = - asset_sample_count + (generated_sample_count * estimated_max_polyphony); - const int recommended_spectrograms = (int)(min_spectrograms * 1.5f); - const int recommended_voices = estimated_max_polyphony * 2; - - fprintf(out_file, - "// ============================================================\n"); - fprintf(out_file, "// RESOURCE USAGE ANALYSIS (for synth.h configuration)\n"); - fprintf(out_file, - "// ============================================================\n"); - fprintf(out_file, "// Total samples: %d (%d assets + %d generated notes)\n", - (int)samples.size(), asset_sample_count, generated_sample_count); - fprintf(out_file, "// Max simultaneous pattern triggers: %d\n", - max_simultaneous_patterns); - fprintf(out_file, "// Estimated max polyphony: %d voices\n", - estimated_max_polyphony); - fprintf(out_file, "// \n"); - fprintf(out_file, "// REQUIRED (minimum to avoid pool exhaustion):\n"); - fprintf(out_file, "// MAX_VOICES: %d\n", estimated_max_polyphony); - fprintf(out_file, "// MAX_SPECTROGRAMS: %d (no caching)\n", - min_spectrograms); - fprintf(out_file, "// \n"); - fprintf(out_file, "// RECOMMENDED (with 50%% safety margin):\n"); - fprintf(out_file, "// MAX_VOICES: %d\n", recommended_voices); - fprintf(out_file, "// MAX_SPECTROGRAMS: %d (no caching)\n", - recommended_spectrograms); - fprintf(out_file, "// \n"); - fprintf(out_file, "// NOTE: With spectrogram caching by note parameters,\n"); - fprintf(out_file, "// MAX_SPECTROGRAMS could be reduced to ~%d\n", - asset_sample_count + generated_sample_count); - fprintf( - out_file, - "// ============================================================\n\n"); + // Write analysis to output file + write_resource_analysis(out_file, analysis, samples.size()); fclose(out_file); + // Print compilation summary printf("Tracker compilation successful.\n"); printf(" Patterns: %zu\n", patterns.size()); printf(" Score triggers: %zu\n", score.size()); printf(" Samples: %d (%d assets + %d generated)\n", (int)samples.size(), - asset_sample_count, generated_sample_count); - printf(" Max simultaneous patterns: %d\n", max_simultaneous_patterns); - printf(" Estimated max polyphony: %d voices\n", estimated_max_polyphony); + analysis.asset_sample_count, analysis.generated_sample_count); + printf(" Max simultaneous patterns: %d\n", + analysis.max_simultaneous_patterns); + printf(" Estimated max polyphony: %d voices\n", + analysis.estimated_max_polyphony); printf("\n"); printf("RESOURCE REQUIREMENTS:\n"); - printf(" Required MAX_VOICES: %d\n", estimated_max_polyphony); + printf(" Required MAX_VOICES: %d\n", analysis.estimated_max_polyphony); printf(" Required MAX_SPECTROGRAMS: %d (without caching)\n", - min_spectrograms); + analysis.min_spectrograms); printf(" Recommended MAX_VOICES: %d (with safety margin)\n", - recommended_voices); + analysis.recommended_voices); printf(" Recommended MAX_SPECTROGRAMS: %d (with safety margin)\n", - recommended_spectrograms); + analysis.recommended_spectrograms); printf(" With caching: MAX_SPECTROGRAMS could be ~%d\n", - asset_sample_count + generated_sample_count); + analysis.asset_sample_count + analysis.generated_sample_count); return 0; } -- cgit v1.2.3