summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-14 18:06:24 +0100
committerskal <pascal.massimino@gmail.com>2026-02-14 18:06:24 +0100
commite9dde3cea39e69d6188a7f49034f6d95e4c8b6b4 (patch)
treeb3b383eff5f0d1d18bdbb781c331e6a31fcb25a7 /doc
parentb4c901700de0d9e867b9fd0c0c6a6586578f8480 (diff)
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 <noreply@anthropic.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/TRACKER.md41
1 files changed, 24 insertions, 17 deletions
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 <tempo> # Optional, defaults to 120 BPM
+BPM <tempo> # Optional, defaults to 120 BPM
+HUMANIZE SEED <int> TIMING <pct> VOLUME <pct> # Optional humanization
-SAMPLE <name> [OFFSET <sec>] [VOL <volume>] # Define sample with optional offset/volume
+# Generated samples:
+SAMPLE <name>, <freq>, <dur>, <amp>, <attack>, <harmonics>, <decay> [OFFSET <sec>]
-PATTERN <name> LENGTH <duration> # Define pattern with unit-less duration
- <unit_time>, <sample>, <volume>, <pan> # Pattern events
+# Asset samples:
+SAMPLE <asset_id> [OFFSET <sec>] # ASSET_* from assets.txt
-HUMANIZE SEED <int> TIMING <pct> VOLUME <pct> # Optional humanization params
+# Auto-generated notes (no SAMPLE declaration needed):
+# NOTE_C4, NOTE_A#3, NOTE_Eb2, etc.
-SCORE # Score section (pattern triggers)
+PATTERN <name> [LENGTH <duration>] # Defaults to LENGTH 1.0
+ <unit_time>, <sample>, <volume>, <pan>
+
+SCORE
<unit_time>, <pattern_name>
```
@@ -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
---