summaryrefslogtreecommitdiff
path: root/doc/TRACKER.md
blob: 48829c004482f00f1b85af9de97f2938c203e2ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 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 <tempo>              # Optional, defaults to 120 BPM

SAMPLE <name>            # Define sample (asset or generated note)

PATTERN <name> LENGTH <duration>   # Define pattern with unit-less duration
  <unit_time>, <sample>, <volume>, <pan>   # Pattern events

SCORE                    # Score section (pattern triggers)
  <unit_time>, <pattern_name>
```

### 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
```

### Future: Modifiers

Potential runtime modifiers (not yet implemented):
- Randomization, accents, volume modulation, distortion, noise, effects

---

## 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()`