From e9dde3cea39e69d6188a7f49034f6d95e4c8b6b4 Mon Sep 17 00:00:00 2001 From: skal Date: Sat, 14 Feb 2026 18:06:24 +0100 Subject: feat(tracker): add sample offset and humanization Implements two tracker realism features: 1. Sample Offset (compile-time): - Add offset_sec field to NoteParams and Sample structs - Parse OFFSET parameter in SAMPLE directive - Apply timing shift during compilation (zero runtime cost) - Use for attack-heavy samples to align perceived beat 2. Humanization (runtime, deterministic): - Add humanize_seed, timing_variation_pct, volume_variation_pct to TrackerScore - Parse HUMANIZE directive with SEED/TIMING/VOLUME params - Apply per-event RNG jitter using std::minstd_rand - Deterministic: same seed produces identical output Both features work in real-time playback and WAV export. Test file: data/test_humanize.track Co-Authored-By: Claude Sonnet 4.5 --- doc/TRACKER.md | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'doc/TRACKER.md') diff --git a/doc/TRACKER.md b/doc/TRACKER.md index 5cb59de..dc77976 100644 --- a/doc/TRACKER.md +++ b/doc/TRACKER.md @@ -18,16 +18,22 @@ Patterns are BPM-independent. Changing BPM only affects playback speed. ``` # Comments start with # -BPM # Optional, defaults to 120 BPM +BPM # Optional, defaults to 120 BPM +HUMANIZE SEED TIMING VOLUME # Optional humanization -SAMPLE [OFFSET ] [VOL ] # Define sample with optional offset/volume +# Generated samples: +SAMPLE , , , , , , [OFFSET ] -PATTERN LENGTH # Define pattern with unit-less duration - , , , # Pattern events +# Asset samples: +SAMPLE [OFFSET ] # ASSET_* from assets.txt -HUMANIZE SEED TIMING VOLUME # Optional humanization params +# Auto-generated notes (no SAMPLE declaration needed): +# NOTE_C4, NOTE_A#3, NOTE_Eb2, etc. -SCORE # Score section (pattern triggers) +PATTERN [LENGTH ] # Defaults to LENGTH 1.0 + , , , + +SCORE , ``` @@ -74,26 +80,27 @@ PATTERN short_fill LENGTH 0.5 # 2 beats = 1 second at 120 BPM ### Sample Offset -Samples can specify an intrinsic offset (time-shift left): +Intrinsic timing offset per sample (compile-time): ``` -SAMPLE ASSET_KICK_1 OFFSET 0.05 VOL 1.2 +SAMPLE ASSET_KICK_1 OFFSET 0.01 # Trigger 10ms earlier (attack compensation) +SAMPLE bass, 80, 0.5, 1.0, 0.02, 3, 0.6 OFFSET 0.005 ``` -- **OFFSET**: Seconds to shift trigger earlier (preserves beat sync) -- **VOL**: Default volume multiplier for this sample +- Shifts sample trigger earlier while preserving beat sync +- Applied at compile-time (zero runtime cost) +- Use for attack-heavy samples to align perceived beat ### Humanization -Add per-note timing/volume variation for realistic playback: +Per-note timing/volume variation (runtime, deterministic): ``` -HUMANIZE SEED 42 TIMING 2.0 VOLUME 5.0 +HUMANIZE SEED 42 TIMING 5.0 VOLUME 10.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. +- **SEED**: Deterministic RNG seed (reproducible across runs) +- **TIMING**: ±% jitter of beat duration +- **VOLUME**: ±% variation of event volume +- Identical in real-time playback and WAV export --- -- cgit v1.2.3