diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-12 00:47:57 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-12 00:47:57 +0100 |
| commit | 1b6f3a1273dd7552098d0e634b85ed16e72aabfe (patch) | |
| tree | b78bfa8fbd089e2d101d33bbfbfbfbe15246ce71 | |
| parent | c6aa7f1be2d52d9b12507fd0d5381513f5c0b9b6 (diff) | |
docs: complete beat-based timing documentation
Updated all affected documentation files:
- UNIFORM_BUFFER_GUIDELINES.md: New CommonUniforms example
- ARCHITECTURE.md: Beat-based timing section
- EFFECT_WORKFLOW.md: Available uniforms reference
- CONTRIBUTING.md: Updated uniform buffer checklist
handoff(Claude): Beat-based timing system fully implemented and documented.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| -rw-r--r-- | doc/ARCHITECTURE.md | 23 | ||||
| -rw-r--r-- | doc/CONTRIBUTING.md | 6 | ||||
| -rw-r--r-- | doc/EFFECT_WORKFLOW.md | 10 | ||||
| -rw-r--r-- | doc/UNIFORM_BUFFER_GUIDELINES.md | 39 |
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"); ``` |
