summaryrefslogtreecommitdiff
path: root/doc/test_demo_README.md
blob: bbce0233ff000051ef6adacb1a326b2f89d9618f (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# test_demo - Audio/Visual Synchronization Debug Tool

## Overview

A minimal standalone tool for debugging audio/visual synchronization in the demo without the complexity of the full demo64k timeline.

## Features

- **Simple Drum Beat**: Kick-snare pattern with crash every 4th bar
- **NOTE_A4 Reference Tone**: 440 Hz tone plays at start of each bar for testing
- **Screen Flash Effect**: Visual feedback synchronized to audio peaks
- **16 Second Duration**: 8 bars at 120 BPM
- **Variable Tempo Mode**: Tests tempo scaling (1.0x ↔ 1.5x and 1.0x ↔ 0.66x)
- **Peak Logging**: Export audio peaks to file for gnuplot visualization

## Building

```bash
cmake --build build --target test_demo
```

## Usage

### Basic Usage

```bash
build/test_demo
```

### Command-Line Options

```
  --help              Show help message and exit
  --fullscreen        Run in fullscreen mode
  --resolution WxH    Set window resolution (e.g., 1024x768)
  --tempo             Enable tempo variation test mode
  --log-peaks FILE    Log audio peaks at each beat (32 samples for 16s)
  --log-peaks-fine    Log at each frame for fine analysis (~960 samples)
                      (use with --log-peaks for millisecond resolution)
```

### Examples

#### Run in fullscreen
```bash
build/test_demo --fullscreen
```

#### Custom resolution with tempo testing
```bash
build/test_demo --resolution 1024x768 --tempo
```

#### Log audio peaks for analysis (beat-aligned)
```bash
build/test_demo --log-peaks peaks.txt
```

After running, visualize with gnuplot:
```bash
gnuplot -p -e "set xlabel 'Time (s)'; set ylabel 'Peak'; plot 'peaks.txt' using 2:3 with lines title 'Raw Peak'"
```

#### Log audio peaks with fine resolution (every frame)
```bash
build/test_demo --log-peaks peaks_fine.txt --log-peaks-fine
```

This logs at ~60 Hz (every frame) instead of every beat, providing millisecond-resolution data for detailed synchronization analysis. Produces ~960 samples for the 16-second demo.

## Keyboard Controls

- **ESC**: Exit the demo
- **F**: Toggle fullscreen

## Audio Pattern

The demo plays a repeating drum pattern:

```
Bar 1-2: Kick-Snare-Kick-Snare (with A4 note)
Bar 3:   Kick+Crash-Snare-Kick-Snare (with A4 note)  ← Crash landmark
Bar 4-6: Kick-Snare-Kick-Snare (with A4 note)
Bar 7:   Kick+Crash-Snare-Kick-Snare (with A4 note)  ← Crash landmark
Bar 8:   Kick-Snare-Kick-Snare (with A4 note)
```

**Timing:**
- 120 BPM (2 beats per second)
- 1 bar = 4 beats = 2 seconds
- Total duration: 8 bars = 16 seconds

**Crash Landmarks:**
- First crash at T=4.0s (bar 3, beat 8)
- Second crash at T=12.0s (bar 7, beat 24)

## Tempo Test Mode (`--tempo`)

When enabled with `--tempo` flag, the demo alternates tempo scaling every bar:

- **Even bars (0, 2, 4, 6)**: Accelerate from 1.0x → 1.5x
- **Odd bars (1, 3, 5, 7)**: Decelerate from 1.0x → 0.66x

This tests the variable tempo system where music time advances independently of physical time:
- `music_time += dt * tempo_scale`
- Pattern triggering respects tempo scaling
- Audio samples play at normal pitch (no pitch shifting)

**Console Output with --tempo:**
```
[T=0.50, MusicT=0.56, Beat=1, Frac=0.12, Peak=0.72, Tempo=1.25x]
```

**Expected Behavior:**
- Physical time always advances at 1:1 (16 seconds = 16 seconds)
- Music time advances faster during acceleration, slower during deceleration
- By end of demo: Music time > Physical time (due to net acceleration)

## Peak Logging Format

The `--log-peaks` option writes a text file with three columns.

### Beat-Aligned Mode (default)

Logs once per beat (32 samples for 16 seconds):

```
# Audio peak log from test_demo
# Mode: beat-aligned
# To plot with gnuplot:
#   gnuplot -p -e "set xlabel 'Time (s)'; set ylabel 'Peak'; plot 'peaks.txt' using 2:3 with lines title 'Raw Peak'"
# Columns: beat_number clock_time raw_peak
#
0 0.000000 0.850000
1 0.500000 0.720000
2 1.000000 0.800000
...
```

**Columns:**
1. **beat_number**: Beat index (0, 1, 2, ...)
2. **clock_time**: Physical time in seconds
3. **raw_peak**: Audio peak value (0.0-1.0+)

### Fine-Grained Mode (`--log-peaks-fine`)

Logs at every frame (approximately 960 samples for 16 seconds at 60 Hz):

```
# Audio peak log from test_demo
# Mode: fine (per-frame)
# To plot with gnuplot:
#   gnuplot -p -e "set xlabel 'Time (s)'; set ylabel 'Peak'; plot 'peaks_fine.txt' using 2:3 with lines title 'Raw Peak'"
# Columns: frame_number clock_time raw_peak beat_number
#
0 0.000000 0.850000 0
1 0.016667 0.845231 0
2 0.033333 0.823445 0
3 0.050000 0.802891 0
...
30 0.500000 0.720000 1
31 0.516667 0.715234 1
...
```

**Columns:**
1. **frame_number**: Frame index (0, 1, 2, ...)
2. **clock_time**: Physical time in seconds (millisecond precision)
3. **raw_peak**: Audio peak value (0.0-1.0+)
4. **beat_number**: Corresponding beat index (for correlation with beat-aligned mode)

**Use Cases:**

*Beat-Aligned Mode:*
- Verify audio/visual synchronization at beat boundaries
- Detect clipping at specific beats (peak > 1.0)
- Analyze tempo scaling effects on pattern triggering
- Compare expected vs actual beat times

*Fine-Grained Mode:*
- Millisecond-resolution synchronization analysis
- Detect frame-level timing jitter or drift
- Analyze audio envelope shape and attack/decay characteristics
- Debug precise flash-to-audio alignment issues
- Identify sub-beat audio artifacts or glitches

## Files

- **`src/test_demo.cc`**: Main executable (~220 lines)
- **`assets/test_demo.track`**: Drum pattern and NOTE_A4 definition
- **`assets/test_demo.seq`**: Visual timeline (FlashEffect)
- **`src/generated/test_demo_timeline.cc`**: Generated timeline (auto)
- **`src/generated/test_demo_music.cc`**: Generated music data (auto)

## Verification Checklist

### Normal Mode
- [ ] Visual flashes occur every ~0.5 seconds
- [ ] Audio plays (kick-snare drum pattern audible)
- [ ] A4 tone (440 Hz) audible at start of each bar
- [ ] Synchronization: Flash happens simultaneously with kick hit
- [ ] Crash landmark: Larger flash + cymbal crash at T=4.0s and T=12.0s
- [ ] Auto-exit: Demo stops cleanly at 16 seconds
- [ ] Console timing: Peak values spike when kicks hit (Peak > 0.7)
- [ ] No audio glitches: Smooth playback, no stuttering

### Tempo Test Mode
- [ ] Bar 0 accelerates (1.0x → 1.5x)
- [ ] Bar 1 decelerates (1.0x → 0.66x)
- [ ] Music time drifts from physical time
- [ ] Audio still syncs with flashes
- [ ] Smooth transitions at bar boundaries
- [ ] Physical time = 16s at end
- [ ] Music time > 16s at end
- [ ] Console shows tempo value

### Peak Logging
- [ ] File created when `--log-peaks` specified
- [ ] Contains beat_number, clock_time, raw_peak columns
- [ ] Gnuplot command in header comment
- [ ] One row per beat (32 rows for 16 seconds)
- [ ] Peak values match console output
- [ ] Gnuplot visualization works

## Troubleshooting

**Flash appears before audio:**
- Cause: Audio latency too high
- Fix: Reduce ring buffer size in `ring_buffer.h`

**Flash appears after audio:**
- Cause: Ring buffer under-filled
- Fix: Increase pre-fill duration in `audio_render_ahead()`

**No flash at all:**
- Cause: Peak threshold not reached
- Check: Console shows Peak > 0.7
- Fix: Increase `visual_peak` multiplier in code (currently 8.0×)

**A4 note not audible:**
- Cause: NOTE_A4 volume too low or procedural generation issue
- Check: Console shows correct sample count (4 samples)
- Fix: Increase volume in test_demo.track (currently 0.5)

**Peak log file empty:**
- Cause: Demo exited before first beat
- Check: File has header comments
- Fix: Ensure demo runs for at least 0.5 seconds

## Design Rationale

**Why separate from demo64k?**
- Isolated testing environment
- No timeline complexity
- Faster iteration cycles
- Independent verification

**Why use main demo assets?**
- Avoid asset system conflicts (AssetId enum collision)
- Reuse existing samples
- No size overhead
- Simpler CMake integration

**Why 16 seconds?**
- Long enough for verification (8 bars)
- Short enough for quick tests
- Crash landmarks at 25% and 75% for easy reference

**Why NOTE_A4?**
- Standard reference tone (440 Hz)
- Easily identifiable pitch
- Tests procedural note generation
- Minimal code impact