summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/ARCHITECTURE.md23
-rw-r--r--doc/CONTRIBUTING.md6
-rw-r--r--doc/EFFECT_WORKFLOW.md10
-rw-r--r--doc/UNIFORM_BUFFER_GUIDELINES.md39
4 files changed, 55 insertions, 23 deletions
diff --git a/doc/ARCHITECTURE.md b/doc/ARCHITECTURE.md
index 97413de..4c36ec5 100644
--- a/doc/ARCHITECTURE.md
+++ b/doc/ARCHITECTURE.md
@@ -18,11 +18,26 @@ Detailed system architecture for the 64k demo project.
**Effect**: Abstract base for visual elements. Supports `compute` and `render` phases.
-**Sequence**: Timeline of effects with start/end times.
+**Sequence**: Timeline of effects with start/end times defined in beats.
**MainSequence**: Top-level coordinator and framebuffer manager.
-**seq_compiler**: Transpiles workspace `timeline.seq` into C++ `timeline.cc`.
+**seq_compiler**: Transpiles workspace `timeline.seq` (beat-based) into C++ `timeline.cc` (seconds).
+
+### Beat-Based Timing
+
+**Timeline Notation**: Sequences authored in musical beats (default) or explicit seconds (`s` suffix).
+
+**Runtime Conversion**: Beats → seconds at compile time using BPM. Effects activate at physical seconds.
+
+**Uniform Timing**: Effects receive both:
+- `time` - Physical seconds (constant, unaffected by tempo)
+- `beat_time` - Musical beats (from audio playback clock)
+- `beat_phase` - Fractional beat 0.0-1.0
+
+**Tempo Separation**: Variable tempo scales `music_time` for audio triggering only. Visual rendering uses constant physical time with optional beat synchronization.
+
+See `doc/BEAT_TIMING.md` for details.
---
@@ -42,10 +57,10 @@ Detailed system architecture for the 64k demo project.
Real-time additive synthesis from spectrograms via FFT-based IDCT (O(N log N)). Stereo output (32kHz, 16-bit, interleaved L/R). Uses orthonormal DCT-II/DCT-III transforms with Numerical Recipes reordering method.
### Variable Tempo
-Music time abstraction with configurable tempo_scale. Tempo changes don't affect pitch.
+Music time abstraction with configurable `tempo_scale`. Tempo changes don't affect pitch. **Visual effects unaffected** - they use physical time, not tempo-scaled music time.
### Event-Based Tracker
-Individual TrackerEvents trigger as separate voices with dynamic beat calculation. Notes within patterns respect tempo scaling.
+Individual TrackerEvents trigger as separate voices with dynamic beat calculation. Notes within patterns respect tempo scaling. Triggers based on `music_time` (tempo-scaled).
### Backend Abstraction
`AudioBackend` interface with `MiniaudioBackend` (production), `MockAudioBackend` (testing), and `WavDumpBackend` (offline rendering).
diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md
index 98df873..d7ef88a 100644
--- a/doc/CONTRIBUTING.md
+++ b/doc/CONTRIBUTING.md
@@ -153,8 +153,8 @@ To ensure consistency and prevent alignment-related issues:
2. **Mirror in C++:** Create corresponding C++ structs that mirror WGSL definitions.
3. **`static_assert` for Size:** Every C++ struct must have a `static_assert` verifying size matches WGSL.
4. **Standard Bindings:**
- - **Binding 2:** Always use `CommonPostProcessUniforms` for per-frame data (resolution, time, beat).
+ - **Binding 2:** Always use `CommonPostProcessUniforms` for per-frame data (resolution, time, beat_time, beat_phase, audio_intensity).
- **Binding 3:** Use effect-specific parameter structs for unique data.
-5. **Shader Consistency:** Ensure WGSL shaders correctly declare uniforms at specified bindings.
+5. **Shader Consistency:** Use `ShaderComposer` to include `common_uniforms` snippet. Reference `CommonUniforms` struct in WGSL shaders.
6. **Validation Script:** Run `tools/validate_uniforms.py` to catch discrepancies.
-7. **Documentation:** Refer to `doc/UNIFORM_BUFFER_GUIDELINES.md` for detailed alignment rules.
+7. **Documentation:** Refer to `doc/UNIFORM_BUFFER_GUIDELINES.md` for detailed alignment rules and `doc/BEAT_TIMING.md` for timing usage.
diff --git a/doc/EFFECT_WORKFLOW.md b/doc/EFFECT_WORKFLOW.md
index d68d148..e453b63 100644
--- a/doc/EFFECT_WORKFLOW.md
+++ b/doc/EFFECT_WORKFLOW.md
@@ -37,6 +37,16 @@ void render(WGPURenderPassEncoder pass,
const CommonPostProcessUniforms& uniforms) override;
```
+**Uniforms Available:**
+```cpp
+uniforms.time; // Physical seconds (constant speed)
+uniforms.beat_time; // Musical beats (bar synchronization)
+uniforms.beat_phase; // Fractional beat 0.0-1.0 (smooth oscillation)
+uniforms.audio_intensity; // Audio peak for beat sync
+uniforms.resolution; // Screen dimensions
+uniforms.aspect_ratio; // Width/height ratio
+```
+
**Template:** See `tools/shadertoy/template.*` or use `convert_shadertoy.py`
### 2. Add Shader to Assets
diff --git a/doc/UNIFORM_BUFFER_GUIDELINES.md b/doc/UNIFORM_BUFFER_GUIDELINES.md
index ac02223..93999d8 100644
--- a/doc/UNIFORM_BUFFER_GUIDELINES.md
+++ b/doc/UNIFORM_BUFFER_GUIDELINES.md
@@ -19,7 +19,7 @@ Structs are padded to the alignment of their largest member. Any trailing space
To maintain consistency and facilitate efficient rendering, a standard pattern for uniform buffer usage is established:
- **Binding 0 & 1:** Reserved for Sampler and Texture access (handled by `pp_update_bind_group`).
-- **Binding 2:** **Common Uniforms** (`CommonPostProcessUniforms` or similar). This buffer should contain frequently used data like resolution, aspect ratio, time, beat, and audio intensity.
+- **Binding 2:** **Common Uniforms** (`CommonPostProcessUniforms` or similar). This buffer should contain frequently used data like resolution, aspect ratio, physical time, beat time, beat phase, and audio intensity.
- **Binding 3:** **Effect-Specific Parameters**. This buffer holds parameters unique to a particular effect (e.g., `strength`, `speed`, `fade_amount`).
This pattern ensures that common data is shared efficiently across effects, while effect-specific data remains isolated.
@@ -34,20 +34,26 @@ When defining uniform structs in WGSL, adhere to the following:
- **Use `vec2<f32>` for 8-byte padding:** If you need 8 bytes of padding, use `_pad0: vec2<f32>` instead of `_pad0: f32, _pad1: f32` for potentially better clarity and to leverage WGSL's type system.
- **Minimize Padding:** Only add padding where required by alignment rules to reduce memory usage.
-**Example (CommonPostProcessUniforms / HeptagonUniforms):**
+**Example (CommonPostProcessUniforms):**
```wgsl
struct CommonUniforms {
- resolution: vec2<f32>,
- _pad0: vec2<f32>, // 8 bytes padding to align subsequent members
- aspect_ratio: f32,
- time: f32,
- beat: f32,
- audio_intensity: f32,
+ resolution: vec2<f32>, // Screen dimensions (8 bytes)
+ aspect_ratio: f32, // Width/height ratio (4 bytes)
+ time: f32, // Physical seconds, unaffected by tempo (4 bytes)
+ beat_time: f32, // Musical time in beats (4 bytes)
+ beat_phase: f32, // Fractional beat 0.0-1.0 (4 bytes)
+ audio_intensity: f32, // Audio peak for beat sync (4 bytes)
+ _pad: f32, // Alignment padding (4 bytes)
};
-// Expected size: 32 bytes
+// Total size: 32 bytes (8 f32 values)
```
+**Use cases:**
+- `time`: Constant-speed physics animation
+- `beat_time`: Musical bar/beat synchronization
+- `beat_phase`: Smooth per-beat oscillation
+
**Example (EffectParams with f32 members):**
```wgsl
@@ -73,14 +79,15 @@ For every WGSL uniform struct, a corresponding C++ struct must exist. This C++ s
```cpp
struct CommonPostProcessUniforms {
- vec2 resolution; // 8 bytes
- float _pad[2]; // 8 bytes padding (matches vec2<f32> in WGSL)
- float aspect_ratio; // 4 bytes
- float time; // 4 bytes
- float beat; // 4 bytes
- float audio_intensity; // 4 bytes
+ vec2 resolution; // 8 bytes - screen dimensions
+ float aspect_ratio; // 4 bytes - width/height ratio
+ float time; // 4 bytes - physical seconds
+ float beat_time; // 4 bytes - musical beats
+ float beat_phase; // 4 bytes - fractional beat 0-1
+ float audio_intensity; // 4 bytes - audio peak
+ float _pad; // 4 bytes - alignment padding
};
-static_assert(sizeof(CommonPostProcessUniforms) == 32,
+static_assert(sizeof(CommonPostProcessUniforms) == 32,
"CommonPostProcessUniforms must be 32 bytes for WGSL alignment");
```