# Minimal Audio Tracker System for assembling audio samples (assets or procedural) into patterns and loops. ## .track File Format ### Timing Convention **Unit-less timing:** - **1 unit = 4 beats** - Conversion: `seconds = units * (4 / BPM) * 60` - At 120 BPM: 1 unit = 2 seconds Patterns are BPM-independent. Changing BPM only affects playback speed. ### File Structure ``` # Comments start with # BPM # Optional, defaults to 120 BPM SAMPLE [OFFSET ] [VOL ] # Define sample with optional offset/volume PATTERN LENGTH # Define pattern with unit-less duration , , , # Pattern events HUMANIZE SEED TIMING VOLUME # Optional humanization params SCORE # Score section (pattern triggers) , ``` ### Examples #### Simple 4-beat pattern (1 unit): ``` PATTERN kick_snare LENGTH 1.0 0.00, ASSET_KICK_1, 1.0, 0.0 # Start of pattern (beat 0) 0.25, ASSET_SNARE_1, 0.9, 0.0 # 1/4 through (beat 1) 0.50, ASSET_KICK_1, 1.0, 0.0 # 1/2 through (beat 2) 0.75, ASSET_SNARE_1, 0.9, 0.0 # 3/4 through (beat 3) ``` #### Score triggers: ``` SCORE 0.0, kick_snare # Trigger at 0 seconds (120 BPM) 1.0, kick_snare # Trigger at 2 seconds (1 unit = 2s at 120 BPM) 2.0, kick_snare # Trigger at 4 seconds ``` #### Generated note: ``` SAMPLE NOTE_C4 # Automatically generates C4 note (261.63 Hz) PATTERN melody LENGTH 1.0 0.00, NOTE_C4, 0.8, 0.0 0.25, NOTE_E4, 0.7, 0.0 0.50, NOTE_G4, 0.8, 0.0 ``` ### Pattern Length - `LENGTH` parameter defaults to 1.0 if omitted - Can be any value (0.5 for half-length, 2.0 for double-length) - Events must be within `[0.0, LENGTH]` Example half-length pattern: ``` PATTERN short_fill LENGTH 0.5 # 2 beats = 1 second at 120 BPM 0.00, ASSET_HIHAT, 0.7, 0.0 0.50, ASSET_HIHAT, 0.6, 0.0 # 0.50 * 0.5 = 1 beat into the pattern ``` ### Sample Offset Samples can specify an intrinsic offset (time-shift left): ``` SAMPLE ASSET_KICK_1 OFFSET 0.05 VOL 1.2 ``` - **OFFSET**: Seconds to shift trigger earlier (preserves beat sync) - **VOL**: Default volume multiplier for this sample ### Humanization Add per-note timing/volume variation for realistic playback: ``` HUMANIZE SEED 42 TIMING 2.0 VOLUME 5.0 ``` - **SEED**: Random seed for reproducibility - **TIMING**: Timing variation (% of beat duration) - **VOLUME**: Volume variation (% of event volume) Applied per-note, baked into WAV export. --- ## AudioEngine API **Production usage:** ```cpp #include "audio/audio_engine.h" audio_init(); static AudioEngine g_audio_engine; g_audio_engine.init(); // Main loop g_audio_engine.update(music_time); g_audio_engine.shutdown(); audio_shutdown(); ``` **Methods:** - `init()`: Initialize synth + tracker - `update(music_time)`: Update music state, trigger patterns - `shutdown()`: Cleanup - `seek(time)`: Jump to timestamp (debug builds only) **Testing:** ```cpp AudioEngine engine; engine.init(); engine.update(1.0f); engine.shutdown(); ``` **Direct synth APIs** (performance-critical code only): - `synth_register_spectrogram()` - `synth_trigger_voice()` - `synth_get_output_peak()` - `synth_render()`