summaryrefslogtreecommitdiff
path: root/test_demo_README.md
blob: f84f972590bcb00df57e27e4e4fa0269d2f633d7 (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
# 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 to FILE for gnuplot visualization
```

### 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
```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 1:3 with lines title 'Raw Peak'"
```

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

```
# Audio peak log from test_demo
# To plot with gnuplot:
#   gnuplot -p -e "set xlabel 'Time (s)'; set ylabel 'Peak'; plot 'peaks.txt' using 1: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+)

**Use Cases:**
- Verify audio/visual synchronization timing
- Detect clipping (peak > 1.0)
- Analyze tempo scaling effects
- Compare expected vs actual beat times

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