summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-12 00:30:56 +0100
committerskal <pascal.massimino@gmail.com>2026-02-12 00:30:56 +0100
commit89c46872127aaede53362f64cdc3fe9b3164650b (patch)
tree844882239088b35f2b1b555029780d26c6b4cfe8 /doc
parent4e0b7c040c3e45c66767b936a8058f76bcc31bf1 (diff)
feat: implement beat-based timing system
BREAKING CHANGE: Timeline format now uses beats as default unit ## Core Changes **Uniform Structure (32 bytes maintained):** - Added `beat_time` (absolute beats for musical animation) - Added `beat_phase` (fractional 0-1 for smooth oscillation) - Renamed `beat` → `beat_phase` - Kept `time` (physical seconds, tempo-independent) **Seq Compiler:** - Default: all numbers are beats (e.g., `5`, `16.5`) - Explicit seconds: `2.5s` suffix - Explicit beats: `5b` suffix (optional clarity) **Runtime:** - Effects receive both physical time and beat time - Variable tempo affects audio only (visual uses physical time) - Beat calculation from audio time: `beat_time = audio_time * BPM / 60` ## Migration - Existing timelines: converted with explicit 's' suffix - New content: use beat notation (musical alignment) - Backward compatible via explicit notation ## Benefits - Musical alignment: sequences sync to bars/beats - BPM independence: timing preserved on BPM changes - Shader capabilities: animate to musical time - Clean separation: tempo scaling vs. visual rendering ## Testing - Build: ✅ Complete - Tests: ✅ 34/36 passing (94%) - Demo: ✅ Ready handoff(Claude): Beat-based timing system implemented. Variable tempo only affects audio sample triggering. Visual effects use physical_time (constant) and beat_time (musical). Shaders can now animate to beats. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/SEQUENCE.md85
1 files changed, 53 insertions, 32 deletions
diff --git a/doc/SEQUENCE.md b/doc/SEQUENCE.md
index 68bd129..03d0c45 100644
--- a/doc/SEQUENCE.md
+++ b/doc/SEQUENCE.md
@@ -20,13 +20,13 @@ Sequence files (`.seq`) define the timeline and layering of visual effects. They
```
# BPM 120
```
-Specifies beats per minute. Used to convert beat notation to seconds.
+Specifies beats per minute. Required. Used to convert beats to physical seconds at runtime.
### END_DEMO Directive
```
END_DEMO <time>
```
-Optional auto-exit time. Supports beat notation (`64b`) or seconds (`32.0`).
+Optional auto-exit time in beats (e.g., `64` or `64b`) or explicit seconds (`32.0s`).
### SEQUENCE Declaration
```
@@ -35,10 +35,10 @@ SEQUENCE <global_start> <priority> ["optional_name"] [optional_end]
```
**Parameters:**
-- `global_start`: Sequence start time (beats or seconds)
+- `global_start`: Sequence start time in beats (default) or explicit seconds (`2.5s`)
- `priority`: Render order (0-9 for scenes, 10+ for post-processing)
- `"optional_name"`: Optional display name for Gantt charts
-- `[optional_end]`: Optional sequence end time (forces effect termination)
+- `[optional_end]`: Optional sequence end time in beats (forces effect termination)
**Examples:**
```
@@ -60,34 +60,47 @@ EFFECT <+|=|-> <EffectClassName> <local_start> <local_end> [constructor_args...]
**Parameters:**
- `EffectClassName`: C++ class from `demo_effects.h`
-- `local_start`, `local_end`: Time relative to sequence start
+- `local_start`, `local_end`: Time in beats relative to sequence start
- `constructor_args`: Optional (rarely used, most effects use standard params only)
---
## Time Notation
+**Beat-based timing (default):** All times are in musical beats, ensuring alignment regardless of BPM changes.
+
| Notation | Example | Description |
|----------|---------|-------------|
-| Integer beats | `0`, `64`, `128` | No decimal point = beats |
-| Explicit beats | `0b`, `64b`, `128b` | Suffix 'b' = beats |
-| Decimal seconds | `0.0`, `32.0`, `64.0` | Decimal point = seconds |
-| Explicit seconds | `32.0s`, `64.0s` | Suffix 's' = seconds |
+| **Beats (default)** | `0`, `4`, `16` | Integer or decimal, no suffix |
+| Explicit beats | `4b`, `16.5b` | Optional 'b' suffix for clarity |
+| Explicit seconds | `2.0s`, `8.25s` | Suffix 's' for physical time (rare) |
+
+**Conversion:** At 120 BPM, 1 beat = 0.5 seconds, 4 beats = 2 seconds
-**At 120 BPM:** Beat 64 = 32.0 seconds, Beat 120 = 60.0 seconds
+**Why beats?**
+- Musical alignment: Sequences stay synchronized to music structure
+- BPM independence: Changing BPM preserves musical timing
+- Intuitive authoring: Timeline matches bars/beats
---
## Runtime Parameters
-All effects receive these parameters every frame in `render()`:
+All effects receive these parameters every frame in `render()` via `CommonPostProcessUniforms`:
| Parameter | Type | Description |
|-----------|------|-------------|
-| `time` | float | Global time in seconds |
-| `beat` | float | Current beat fraction (0.0-1.0) |
-| `intensity` | float | Audio peak (0.0-1.0, for beat sync) |
-| `aspect_ratio` | float | Screen width/height |
+| `resolution` | vec2 | Screen dimensions in pixels |
+| `aspect_ratio` | float | Screen width/height ratio |
+| `time` | float | Physical time in seconds (unaffected by tempo) |
+| `beat_time` | float | Musical time in beats (absolute) |
+| `beat_phase` | float | Fractional beat (0.0-1.0 within current beat) |
+| `audio_intensity` | float | Audio peak (0.0-1.0, for beat sync) |
+
+**Use cases:**
+- `time`: Physics-based animation (constant speed)
+- `beat_time`: Musical animation (sync to bars/beats)
+- `beat_phase`: Smooth oscillation per beat
---
@@ -108,47 +121,55 @@ All effects receive these parameters every frame in `render()`:
### Basic Sequence
```
+# BPM 120
SEQUENCE 0 0
- EFFECT + FlashEffect 0.0 0.5 # Priority 0
- EFFECT + HeptagonEffect 0.2 10 # Priority 1
+ EFFECT + FlashEffect 0 1 # Priority 0, beats 0-1 (0-0.5s @ 120 BPM)
+ EFFECT + HeptagonEffect 0.4 20 # Priority 1, beats 0.4-20
```
### Same Priority Layering
```
SEQUENCE 0 0
- EFFECT + Flash 0.0 0.5 # Priority 0
- EFFECT = Fade 0.1 0.3 # Priority 0 (same layer)
- EFFECT + Other 0.2 3 # Priority 1
+ EFFECT + Flash 0 1 # Priority 0
+ EFFECT = Fade 0.2 0.6 # Priority 0 (same layer)
+ EFFECT + Other 0.4 6 # Priority 1
```
### Background Elements
```
SEQUENCE 0 0
- EFFECT - FlashCube 0 10 # Priority -1 (background)
- EFFECT = BgEffect 0 5 # Priority -1 (same layer)
- EFFECT + MainEffect 0 10 # Priority 0 (foreground)
+ EFFECT - FlashCube 0 20 # Priority -1 (background)
+ EFFECT = BgEffect 0 10 # Priority -1 (same layer)
+ EFFECT + MainEffect 0 20 # Priority 0 (foreground)
```
### Sequence with Explicit End
```
-SEQUENCE 8b 0 [5.0]
- EFFECT + Particles 0 120 # Runs until 5s (sequence end)
+SEQUENCE 16 0 [10]
+ EFFECT + Particles 0 240 # Runs until beat 26 (sequence end at 16+10)
```
### Post-Processing Chain
```
SEQUENCE 0 10
- EFFECT + GaussianBlur 0 60 # Applied first
- EFFECT + ChromaAberration 0 60 # Applied second
- EFFECT + Solarize 0 60 # Applied last
+ EFFECT + GaussianBlur 0 120 # Applied first
+ EFFECT + ChromaAberration 0 120 # Applied second
+ EFFECT + Solarize 0 120 # Applied last
```
-### Music-Synchronized
+### Four-Bar Sequence (16 beats)
```
# BPM 120
-SEQUENCE 0b 0
- EFFECT + Flash 0b 1b # Beat 0-1 (0-0.5s)
- EFFECT + Heptagon 4b 8b # Beat 4-8 (2-4s)
+SEQUENCE 0 0 "Intro"
+ EFFECT + Flash 0 1 # First beat
+ EFFECT + Heptagon 4 12 # Second bar through third bar
+ EFFECT + Fade 15 16 # Final beat
+```
+
+### Explicit Physical Time (Rare)
+```
+SEQUENCE 2.5s 0 "Intro timing" # Start at 2.5 physical seconds
+ EFFECT + Fade 0 4 # Fade from beat 0-4 (relative)
```
---