summaryrefslogtreecommitdiff
path: root/doc/COMPLETED.md
blob: 168d378c35d52bf33461991daaef53ec2cbf54ff (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
# Completed Tasks

This file tracks recently completed tasks, organized by completion date.

## Recently Completed (February 7, 2026)

- [x] **Audio Peak Measurement & Test Coverage Improvements** (February 7, 2026)
    - [x] **Real-Time Peak Fix**: Fixed critical audio-visual sync bug where visual effects triggered ~400ms before audio was heard
      - Root cause: Peak measured at ring buffer write time (synth_render) instead of playback time (audio callback)
      - Solution: Added `get_realtime_peak()` to AudioBackend interface, implemented in MiniaudioBackend audio_callback
      - Used exponential averaging: instant attack, 0.7 decay rate (1-second fade time)
    - [x] **Peak Decay Optimization**: Fixed "test_demo just flashing" issue
      - Old: 0.95 decay = 5.76 second fade (screen stayed white)
      - New: 0.7 decay = 1.15 second fade (proper flash with smooth decay)
    - [x] **SilentBackend Creation**: Test-only backend for audio.cc testing without hardware
      - Created src/audio/backend/silent_backend.{h,cc}
      - 7 comprehensive tests: lifecycle, peak control, tracking, playback time, buffer management
      - Significantly improved audio.cc test coverage
    - [x] **Backend Reorganization**: Moved all backends to src/audio/backend/ subdirectory
      - Cleaner code organization, updated all includes and CMake paths
    - [x] **Dead Code Removal**: Removed unused `register_spec_asset()` function
    - **Result**: All 28 tests passing, perfect audio-visual sync, improved test coverage

## Recently Completed (February 6, 2026)

- [x] **Critical Shader Bug Fixes & Test Infrastructure** (February 6, 2026)
    - [x] **Shader Validation Errors**: Fixed three critical WGSL bugs causing demo64k and test_3d_render crashes:
      - Removed dead code using non-existent `inverse()` function in renderer_3d.wgsl
      - Fixed `get_normal_basic()` signature mismatch in sdf_utils.wgsl and lighting.wgsl (obj_type: f32 → obj_params: vec4<f32>)
      - Fixed scene_query_linear.wgsl incorrectly declaring binding 2 (BVH buffer) - was identical to BVH version due to copy-paste error
    - [x] **Root Cause**: Linear shader mode expected no binding 2, but shader declared it, causing pipeline/shader mismatch
    - [x] **New Test Coverage**: Created `test_shader_compilation.cc` that compiles all production shaders through WebGPU, tests both BVH and Linear composition modes, validates WGSL syntax/bindings/types
    - [x] **Test Gap Analysis**: Existing test_shader_assets only checked keywords, not actual compilation. New test would have caught all three bugs.
    - **Result**: demo64k runs without WebGPU errors, test_3d_render no longer crashes, 22/23 tests pass (FftTest unrelated), comprehensive regression prevention

- [x] **Task C: Build System Optimization** (February 6, 2026)
    - [x] **Header Split**: Refactored `asset_manager.h` into `asset_manager_dcl.h` (forward declarations), `asset_manager.h` (core API), and `asset_manager_utils.h` (typed helpers for TextureAsset/MeshAsset).
    - [x] **Asset Dependency Tracking**: Added file-level dependencies for all assets (.wgsl shaders, .spec audio, .obj meshes). CMake now tracks 42 demo assets + 17 test assets individually.
    - [x] **Performance Impact**: Editing TextureAsset/MeshAsset helpers: 4.82s → 2.01s (58% faster). Editing shaders now triggers correct rebuild (was broken before - stale code bug fixed).
    - [x] **Developer Workflow**: No more manual `touch demo_assets.txt` workaround needed. Edit any asset file and rebuild works correctly.
    - **Result**: Critical correctness bug fixed (shader changes were not triggering rebuilds). Build system now has proper dependency tracking for all source and asset files.

## Recently Completed (February 5, 2026)

- [x] **Audio Lifecycle Refactor (Task #56)**:
    - [x] **Phase 1: Design & Prototype**: Created `AudioEngine` class and `SpectrogramResourceManager` to manage audio subsystem initialization and resource loading with lazy loading strategy.
    - [x] **Phase 2: Test Migration**: Migrated all tracker-related tests (`test_tracker.cc`, `test_tracker_timing.cc`, `test_variable_tempo.cc`, `test_wav_dump.cc`) to use AudioEngine instead of direct synth/tracker initialization.
    - [x] **Phase 3: Production Integration**: Updated `main.cc` to use AudioEngine, eliminating initialization order fragility in production code. Fixed pre-existing demo crash (procedural texture loading).
    - [x] **Phase 4: Cleanup & Documentation**: Removed backwards compatibility (synth_init() from audio_init()), updated HOWTO.md and CONTRIBUTING.md with AudioEngine usage patterns and best practices.
    - **Result**: Initialization order dependency eliminated. All 20 tests pass. Binary size impact <500 bytes. Demo runs successfully.

- [x] **Physics & Collision (Task #49)**:
    - [x] **CPU-Side SDF Library**: Implemented `sdSphere`, `sdBox`, `sdTorus`, `sdPlane` in `src/3d/sdf_cpu.h` using `mini_math.h`. Added `calc_normal` for numerical gradients.
    - [x] **BVH Construction**: Implemented `BVHNode` and `BVHBuilder` in `src/3d/bvh.h/cc`. Optimized broad-phase collision queries with `BVH::Query`.
    - [x] **Physics System**: Created `PhysicsSystem` in `src/3d/physics.h/cc` implementing semi-implicit Euler integration, broad-phase BVH culling, and narrow-phase SDF proxy probing.
    - [x] **Integration & Visualization**: Added `velocity`, `mass`, `is_static` to `Object3D`. Integrated physics loop into `test_3d_render.cc` and added BVH wireframe visualization to `VisualDebug`.

- [x] **Audio Playback Debugging & Core Audio Optimization**:
    - [x] **Core Audio Timing Fix**: Resolved stop-and-go audio glitches caused by timing mismatch. Core Audio optimized for 44.1kHz (10ms periods), but our 32kHz system expected uniform ~13.78ms callbacks, causing resampling jitter. Fix: Added `allowNominalSampleRateChange = TRUE` to force OS-level 32kHz native and `performanceProfile = conservative` for 4096-frame buffers (128ms). Result: Stable ~128ms callbacks, <1ms jitter, zero underruns.
    - [x] **Ring Buffer Capacity**: Increased from 200ms to 400ms (25,600 samples) to handle tempo scaling headroom. Added comprehensive bounds checking with abort() on violations.
    - [x] **Tempo-Scaled Buffer Fill**: Fixed critical bug where buffer pre-fill didn't scale dt by tempo (`audio_render_ahead(g_music_time, dt * g_tempo_scale)`). Buffer now maintains 400ms fullness during 2.0x acceleration.
    - [x] **Extensive Diagnostics**: Added high-resolution timing tracking (clock_gettime), callback interval measurement, buffer level monitoring, underrun detection. All under conditional compilation for future debugging.

- [x] **NOTE_ Parsing Fix & Sample Caching**:
    - [x] **Parser Bug Fix**: Fixed `is_note_name()` checking only first letter (A-G), causing ASSET_KICK_1 → A0 (27.5 Hz) false positives. Required "NOTE_" prefix to distinguish notes from assets. Updated music.track to use NOTE_E2, NOTE_G4 format.
    - [x] **Resource Exhaustion Discovery**: Found every event created NEW spectrogram (14 unique samples → 228 registrations). MAX_SPECTROGRAMS=16 insufficient, causing spectrogram_id=-1 errors.
    - [x] **Comprehensive Caching**: Implemented cache in `tracker_init()` pre-registering all samples. Assets: loaded once from AssetManager. Generated notes: created once, stored in persistent pool. All cached synth_ids reused.
    - [x] **Memory Reduction**: MAX_SPECTROGRAMS reduced from 256 (temporary workaround) to 32 (2.3x headroom over 14 actual). 88% memory savings vs uncached approach.
    - [x] **Resource Analysis Tool**: Enhanced `tracker_compiler` to report required/recommended pool sizes, cache potential, memory usage. Analysis showed 152/228 required without caching, 14 with caching.

- [x] **Debug Logging Infrastructure**:
    - [x] **Central Debug Header**: Created `src/util/debug.h` with 7 category macros (DEBUG_LOG_AUDIO, DEBUG_LOG_RING_BUFFER, DEBUG_LOG_TRACKER, DEBUG_LOG_SYNTH, DEBUG_LOG_3D, DEBUG_LOG_ASSETS, DEBUG_LOG_GPU).
    - [x] **CMake Integration**: Added `DEMO_ENABLE_DEBUG_LOGS` option defining `DEBUG_LOG_ALL` to enable all categories. Individual categories can be enabled selectively.
    - [x] **Source Code Conversion**: Updated miniaudio_backend.cc (timing, device config), ring_buffer.cc (underruns), tracker.cc (validation), synth.cc (parameter checks) to use category macros.
    - [x] **Zero Runtime Cost**: Default build: macros compile to `((void)0)`. Debug build: comprehensive logging preserved for troubleshooting.
    - [x] **Pre-Commit Policy**: Updated CONTRIBUTING.md requiring debug build verification before significant commits to ensure diagnostic code remains maintainable.
    - [x] **Verification**: Both default and debug builds compile without errors. Audio playback works correctly in both modes.

- [x] **Event-Based Tracker for Tempo Scaling**:
    - [x] **Problem Identified**: Notes within patterns didn't accelerate with tempo changes. Pattern events were pre-composited into single spectrograms at fixed positions.
    - [x] **Refactored Architecture**: Changed from pattern compositing to individual event triggering. Each TrackerEvent now triggers as separate voice.
    - [x] **Dynamic Beat Calculation**: `elapsed_beats = (music_time - start_time) / beat_duration` allows notes to respect tempo scaling.
    - [x] **ActivePattern Tracking**: Added structure to track pattern_id, start_music_time, and next_event_idx for each active pattern instance.
    - [x] **Removed Compositing Logic**: Deleted paste_spectrogram approach that baked events at fixed frame offsets.
    - [x] **Full Tempo Scaling**: At 2.0x tempo, both pattern triggering AND note spacing play 2x faster. At 0.5x tempo, both play 2x slower.
    - [x] **Testing**: Updated test_tracker.cc to verify individual event triggers at specific beat times. All 17 tests pass.
    - [x] **WAV Verification**: Confirmed with WAV dump showing 61.24s music time in 60s physical time during tempo transitions.

- [x] **WAV Dump Backend for Debugging**:
    - [x] **Implementation**: Created WavDumpBackend implementing AudioBackend interface to render audio offline to .wav files.
    - [x] **Command-Line Option**: Added `--dump_wav output.wav` flag to enable offline rendering instead of live playback.
    - [x] **Stereo Bug Fix**: Fixed critical mono/stereo mismatch. Synth outputs STEREO (interleaved L/R) but initial implementation wrote MONO.
    - [x] **Correct Allocation**: Changed to allocate `frames * 2` samples and write stereo format (num_channels = 2).
    - [x] **Format Matching**: WAV header now correctly specifies 16-bit PCM, stereo, 32kHz (matches live audio exactly).
    - [x] **Regression Test**: Added test_wav_dump.cc with critical assertion `assert(header.num_channels == 2)` to prevent future mismatches.
    - [x] **Tempo Simulation**: WAV dump backend simulates tempo scaling matching main.cc logic for accurate offline rendering.
    - [x] **All Tests Pass**: 17/17 tests pass including WAV format verification.

- [x] **Variable Tempo System**:
    - [x] **Music Time Abstraction**: Implemented unified music time in `main.cc` that advances at `tempo_scale` rate, decoupling from physical time.
    - [x] **Tempo Control**: Added `g_tempo_scale` (default 1.0) allowing future dynamic tempo changes without pitch shifting.
    - [x] **Reset Tricks**: Comprehensive tests verify 2x speed-up and 2x slow-down reset techniques work correctly.
    - [x] **Test Suite**: Created `test_variable_tempo.cc` with 6 test scenarios: basic scaling, speed-up/slow-down resets, pattern density swap, continuous acceleration, oscillating tempo.
    - [x] **Perfect Verification**: All tests pass, confirming music_time advances correctly at variable rates (e.g., 2.0x tempo → 2x faster triggering).
    - [x] **Zero Pitch Shift**: Spectrograms unchanged, only trigger timing affected (as designed).
    - [x] **Documentation**: Created `ANALYSIS_VARIABLE_TEMPO_V2.md` explaining simplified trigger-timing approach.

- [x] **Task #51.3 & #51.4: Tracker Test Suite & Build Integration**:
    - [x] **Comprehensive Test Suite**: Created `test_tracker_timing.cc` with 7 test scenarios using MockAudioBackend.
    - [x] **Simultaneous Trigger Verification**: Confirmed multiple patterns at same time trigger with **0.000ms delta** (perfect sync).
    - [x] **Test Coverage**: Basic recording, progressive triggering, simultaneous triggers, monotonicity, seek/fast-forward, timestamp clustering, render integration.
    - [x] **Real Music Data**: Tests use generated tracker music data for realistic validation.
    - [x] **Build Integration**: Added to CMake with proper dependencies on generated music data.
    - [x] **All Tests Pass**: 15/15 tests passing (100% success rate).

- [x] **Task #51.2: Mock Audio Backend**:
    - [x] **Event Recording**: Created `VoiceTriggerEvent` structure to capture timestamp, spectrogram_id, volume, and pan.
    - [x] **MockAudioBackend Class**: Implemented test-only backend with event recording and time tracking capabilities.
    - [x] **Time Management**: Added `advance_time()`, `set_time()`, and `get_current_time()` for deterministic testing.
    - [x] **Frame Rendering Hook**: Implemented `on_frames_rendered()` to automatically update time based on audio frames (32kHz).
    - [x] **Synth Integration**: Verified mock backend correctly captures voice triggers from synth engine.
    - [x] **Comprehensive Tests**: Created `test_mock_backend.cc` with 6 test scenarios covering all mock functionality.
    - [x] **Build Integration**: Added mock backend to test builds, all 14 tests pass.

- [x] **Task #51.1: Audio Backend Abstraction**:
    - [x] **Interface Created**: Defined `AudioBackend` interface in `src/audio/audio_backend.h` with hooks for voice triggering and frame rendering.
    - [x] **Production Backend**: Moved miniaudio implementation from `audio.cc` to `MiniaudioBackend` class, maintaining backward compatibility.
    - [x] **Audio Refactoring**: Updated `audio.cc` to use backend abstraction with automatic fallback to `MiniaudioBackend`.
    - [x] **Event Hooks**: Added time tracking to `synth.cc` with `on_voice_triggered()` callbacks (guarded by `!STRIP_ALL`).
    - [x] **Verification Test**: Created `test_audio_backend.cc` to verify backend injection and event recording work correctly.
    - [x] **Build Integration**: Updated CMakeLists.txt to include new backend files and link audio tests properly with util/procedural dependencies.
    - [x] **Zero Size Impact**: All test infrastructure under `#if !defined(STRIP_ALL)`, production path unchanged.

- [x] **Task #50: WGSL Modularization**:
    - [x] **Recursive Composition**: Updated `ShaderComposer` to support recursive `#include "snippet_name"` directives with cycle detection.
    - [x] **Granular SDF Library**: Extracted `math/sdf_shapes.wgsl`, `math/sdf_utils.wgsl`, `render/shadows.wgsl`, `render/scene_query.wgsl`, and `render/lighting_utils.wgsl`.
    - [x] **Pipeline Update**: Refactored `Renderer3D` and `renderer_3d.wgsl` to use the new modular system, reducing C++-side dependency management.
    - [x] **Platform Fix**: Resolved `WGPUShaderSourceWGSL` usage on macOS to ensure compatibility with composed shader strings.

- [x] **Task #48: Improve Audio Coverage**:
    - [x] **New Tests**: Added `test_dct` (100% coverage for transforms) and `test_audio_gen` (94% coverage for procedural audio).
    - [x] **Enhanced Tests**: Updated `test_synth` to cover rendering loop, double-buffering, and resource exhaustion.
    - [x] **Coverage Boost**: Increased `src/audio/` coverage from ~42% to 93%.
- [x] **Task #47: Improve Asset Manager Coverage**:
    - [x] **New Tests**: Added tests for unknown procedural functions, generation failures, and edge cases in `src/tests/test_assets.cc`.
    - [x] **Tooling Update**: Downgraded `asset_packer` validation error to warning to allow testing invalid assets.
    - [x] **Coverage Boost**: Increased `src/util/asset_manager.cc` coverage from 71% to 88%.
- [x] **Task #46: Enhance Coverage Script**: Updated `scripts/gen_coverage_report.sh` to accept an optional directory argument for targeted coverage reports (e.g., `src/procedural`).
- [x] **Task #45: Improve Procedural Generation Coverage**:
    - [x] **Unit Tests:** Implemented comprehensive tests for `gen_perlin`, `make_periodic`, and default parameter handling in `src/tests/test_procedural.cc`.
    - [x] **Coverage Boost:** Increased `src/procedural/generator.cc` coverage from 38% to 96%.
- [x] **Task #44: Developer Tooling (Coverage)**:
    - [x] **Implement Code Coverage:** Added `DEMO_ENABLE_COVERAGE` CMake option and created `scripts/gen_coverage_report.sh` to generate HTML coverage reports using `lcov` on macOS.
    - [x] **Documentation:** Updated `doc/HOWTO.md` with usage instructions.
- [x] **Skybox & Two-pass Rendering Stability**:
    - [x] **Fixed Two-pass Rendering:** Implemented mandatory clear operations for color and depth when the skybox is absent, preventing black screens and depth validation errors.
    - [x] **Implemented Rotating Skybox:** Added `inv_view_proj` to `GlobalUniforms` and updated the skybox shader to perform world-space ray unprojection (`inv_view_proj`), enabling correct rotation with the camera.
    - [x] **Enhanced Procedural Noise:** Implemented a multi-octave Value Noise generator for higher-quality skybox textures.
    - [x] **Scene Integrity:** Restored proper object indexing and removed redundant geometry, ensuring the floor grid and objects render correctly.

- [x] **Task #57: Interactive Timeline Editor (Phase 1 Complete)** 🎉
    - [x] **Core Parser & Renderer**: Implemented demo.seq parser with BPM, beat notation, priority modifiers. Gantt-style timeline rendering with dynamic sequence/effect positioning.
    - [x] **Drag & Drop**: Sequences and effects draggable along timeline with proper offset calculation. Fixed critical e.target vs e.currentTarget bug preventing erratic jumping.
    - [x] **Resize Handles**: Left/right handles on selected effects. Allow negative relative times (effects extend before sequence start).
    - [x] **Snap-to-Beat**: Checkbox toggle with beat markers. Automatic snapping when dragging in beat mode.
    - [x] **Properties Panel**: Floating, collapsible panel with auto-apply (no Apply button). Properties update on input change.
    - [x] **Stack-Order Priority**: Up/Down buttons to reorder effects within sequence. Stack position determines rendering priority (higher index = rendered later = on top).
    - [x] **Priority Modifiers**: Toggle button for "Same as Above" (= modifier) vs "Increment" (+ modifier). Visual feedback in button text.
    - [x] **Diagonal Scroll**: Mouse wheel navigation with 10% viewport slack. Smooth following to time-ordered sequence cascade. Flash animation on active sequence change.
    - [x] **Dynamic Bounds**: Sequence visual bounds calculated from min/max effect times. Cumulative Y positioning prevents overlap.
    - [x] **Waveform Visualization**: Load WAV files (via Web Audio API) and display waveform above timeline. Scales with zoom (pixels per second). Documented integration with `--dump_wav` flag.
    - [x] **UI Polish**: Hoverable sequence names (large centered text, fades on hover). No scrollbars (hidden CSS). Clean, minimal interface.
    - [x] **File I/O**: Load/save demo.seq files with proper serialization. BPM parsing and display. Re-order sequences by time.
    - [x] **Delete & Add**: Delete sequences/effects. Add new sequences (at time 0, priority 0).
    - **Result**: Fully functional timeline editor ready for production use. Phase 1.1 complete (basic editing, snap-to-beat, waveform). Phase 1.2 (Add Effect button) and Phase 2.5 (music.track visualization) documented in ROADMAP.md.
    - **Files**: `tools/timeline_editor/index.html` (~1200 lines), `README.md`, `ROADMAP.md` (3 phases, 117-161 hour estimate).

---

## Milestones from PROJECT_CONTEXT.md

#### Milestone: Audio Peak Measurement & Test Coverage (February 7, 2026) ✅
- **Real-Time Audio Peak Fix**: Resolved critical audio-visual synchronization bug where visual effects triggered ~400ms before audio was heard. Root cause: peak measurement occurred at ring buffer write time (synth_render) instead of playback time (audio callback). Solution: Added `get_realtime_peak()` to AudioBackend interface, implemented real-time peak tracking in MiniaudioBackend audio_callback using exponential averaging (instant attack, 0.7 decay rate for 1-second fade). Updated main.cc and test_demo.cc to use `audio_get_realtime_peak()` API. Result: Perfect audio-visual synchronization, visual effects trigger precisely when audio is heard.

- **Peak Decay Optimization**: Fixed "test_demo just flashing" issue caused by slow decay rate. Old: 0.95 decay = 5.76 second fade (screen stayed white constantly). New: 0.7 decay = 1.15 second fade (proper flash with smooth decay). Mathematical verification: At 128ms audio callbacks, 0.7^9 ≈ 0.1 after ~1 second. Result: Responsive visual effects with proper attack/decay curves.

- **SilentBackend Test Infrastructure**: Created test-only audio backend for comprehensive audio.cc testing without hardware. Features: controllable peak for edge cases, tracks frames rendered and voice triggers, pure inspection (no audio output). Created 7 comprehensive tests covering lifecycle, peak control, frame/voice tracking, playback time, buffer management, audio_update safety. Result: Significantly improved audio.cc test coverage (audio_get_playback_time, audio_render_ahead, audio_update all tested).

- **Backend Reorganization**: Moved all audio backend implementations to src/audio/backend/ subdirectory for cleaner code organization. Moved: miniaudio_backend, mock_audio_backend, wav_dump_backend, jittered_audio_backend, silent_backend (5 backends total). Updated all #include paths in backend files and tests, updated CMakeLists.txt paths. Kept audio_backend.h (interface) in src/audio/. Result: Improved maintainability, zero functionality regressions, all 28 tests pass.

- **Dead Code Removal**: Removed unused `register_spec_asset()` function from audio.{h,cc}. Function was never called anywhere in codebase. Removed declaration and implementation (lines 43-58). Result: Cleaner codebase, reduced maintenance burden.

- **Test Coverage Achievement**: All 28 tests passing (100% success rate). New SilentBackend tests provide comprehensive coverage for audio subsystem. No regressions in existing tests. Build clean with no errors or warnings. Files modified: 15 changed, 3 new files, 8 files reorganized. Commit a6a7bf0 ready for push.

#### Milestone: test_demo - Audio/Visual Sync Debug Tool (February 7, 2026) 🎯
- **Standalone Debug Tool**: Created minimal test executable for debugging audio/visual synchronization and variable tempo system without full demo complexity. **Core Features**: Simple drum beat (kick-snare) with crash landmarks at bars 3 and 7, NOTE_A4 (440 Hz) reference tone at start of each bar for testing, screen flash effect synchronized to audio peaks, 16 second duration (8 bars at 120 BPM). **Variable Tempo Mode**: `--tempo` flag enables alternating tempo scaling (even bars: 1.0x → 1.5x acceleration, odd bars: 1.0x → 0.66x deceleration) to test music time vs physical time system. **Peak Logging**: `--log-peaks FILE` exports audio peak data for gnuplot visualization, `--log-peaks-fine` adds millisecond-resolution per-frame logging (~960 samples vs 32 beat-aligned samples). **Command-Line Options**: `--help` shows usage, `--fullscreen` for fullscreen mode, `--resolution WxH` for custom window size. **Error Handling**: Unknown options print error message and help text before exiting with status 1. **File Structure**: `src/test_demo.cc` (main executable, ~220 lines), `assets/test_demo.track` (drum patterns with NOTE_A4), `assets/test_demo.seq` (visual timeline), `test_demo_README.md` (comprehensive documentation). **Peak Log Format**: Beat-aligned mode logs at beat boundaries (32 samples), fine-grained mode logs every frame with beat_number column for correlation. **Build Integration**: CMake target with timeline/music generation, proper dependencies, size optimizations. **Use Cases**: Verify millisecond-precision sync, detect timing jitter, analyze tempo scaling effects, debug flash-to-audio alignment. **Impact**: Provides isolated testing environment for sync verification without demo64k complexity, enables data-driven analysis via exported logs.

- **CMake Configuration Summary**: Added formatted configuration summary to CMake output displaying all build options (DEMO_SIZE_OPT, DEMO_STRIP_ALL, DEMO_BUILD_TESTS, etc.) with ON/OFF status, build type, and compiler information. Appears automatically at end of `cmake` command for easy verification of enabled options.

- **Code Quality Fixes**: Replaced deprecated `std::sprintf` with `std::snprintf` in `asset_packer.cc` to eliminate compiler warnings and add buffer overflow protection during OBJ mesh vertex key generation.

#### Milestone: Audio Playback Stability & Debug Infrastructure (February 4, 2026)
- **Core Audio Backend Optimization**: Resolved critical audio playback issues (stop-and-go, glitches, eventual silence) caused by timing mismatches in miniaudio's Core Audio backend. Root cause: Core Audio optimized for 44.1kHz with 10ms periods, but our 32kHz system expected uniform ~13.78ms callbacks, causing resampling jitter. Fix: Added `allowNominalSampleRateChange = TRUE` to force OS-level 32kHz native and `performanceProfile = conservative` for larger buffers (4096 frames = 128ms). Result: Stable ~128ms callbacks with <1ms jitter, zero underruns during variable tempo (1.0x → 2.0x).

- **Ring Buffer Capacity Tuning**: Increased ring buffer from 200ms to 400ms (25,600 samples) to handle tempo scaling headroom. Added comprehensive bounds checking with abort() on violations to catch buffer corruption early. Fixed critical bug: tempo-scaled rendering wasn't scaling dt when pre-filling buffer (`audio_render_ahead(g_music_time, dt * g_tempo_scale)`). Buffer now maintains 400ms fullness throughout playback, including 2.0x tempo acceleration.

- **NOTE_ Parsing Bug Fix & Sample Caching**: Fixed critical `is_note_name()` bug that only checked first letter (A-G), causing ASSET_KICK_1 to be misidentified as A0 (27.5 Hz). Solution: Required "NOTE_" prefix (NOTE_E2, NOTE_G4) to distinguish from ASSET_* samples. Discovered resource exhaustion: every note event created NEW spectrogram (14 unique samples → 228 registrations). Implemented comprehensive caching in `tracker_init()`: pre-register all asset samples (loaded once from AssetManager) and generated notes (created once, stored in persistent pool). Result: 256 → 32 MAX_SPECTROGRAMS (88% memory reduction), zero spectrogram_id=-1 errors, perfect audio playback.

- **Debug Logging Infrastructure**: Created systematic debug logging system (`src/util/debug.h`) with 7 category macros (DEBUG_LOG_AUDIO, DEBUG_LOG_RING_BUFFER, DEBUG_LOG_TRACKER, DEBUG_LOG_SYNTH, DEBUG_LOG_3D, DEBUG_LOG_ASSETS, DEBUG_LOG_GPU). Added `DEMO_ENABLE_DEBUG_LOGS` CMake option that defines `DEBUG_LOG_ALL` to enable all categories. Converted all diagnostic code in audio subsystem (miniaudio callbacks, ring buffer tracking, tracker validation, synth parameter checks) to use category macros. Default build: macros compile to `((void)0)` for zero runtime cost. Debug build: comprehensive logging (timing, buffer state, caching, validation). Updated `CONTRIBUTING.md` with pre-commit policy requiring debug build verification to ensure diagnostic code remains maintainable.

- **Resource Analysis Tool**: Enhanced `tracker_compiler` to report required vs recommended pool sizes, cache potential, and memory usage. Analysis showed 152 required / 228 recommended spectrograms without caching, only 14 unique samples with caching. Tool now generates actionable optimization recommendations during music data compilation.

#### Milestone: Audio System Robustness & Variable Tempo (February 4, 2026)
- **Event-Based Tracker for Tempo Scaling**: Refactored tracker system from pattern compositing to individual event triggering. Previously, pattern events were baked into single spectrograms at fixed positions, so tempo scaling only affected pattern trigger timing. Now each TrackerEvent triggers as a separate voice with timing calculated dynamically based on music_time. Result: Notes within patterns correctly accelerate/decelerate with tempo changes. At 2.0x tempo, both pattern triggering AND note spacing play 2x faster. Verified with WAV dump showing 61.24s music time in 60s physical time during tempo transitions. All 17 tests pass (100%).

- **WAV Dump Backend for Debugging**: Added `WavDumpBackend` implementing `AudioBackend` interface to render audio offline to .wav files instead of playing on device. Enabled via `--dump_wav output.wav` flag. Critical bug fix: Synth outputs STEREO (interleaved L/R) but initial implementation wrote MONO, causing severe distortion. Fixed by allocating `frames * 2` samples and writing stereo format (num_channels = 2). Added regression test (`test_wav_dump.cc`) with critical assertion `assert(header.num_channels == 2)` to prevent future mono/stereo mismatches. WAV format now matches live audio exactly: 16-bit PCM, stereo, 32kHz.

- **Variable Tempo System**: Implemented unified music time abstraction in `main.cc` that decouples tracker timing from physical time. Music time advances at configurable `tempo_scale` rate (default 1.0), enabling dynamic tempo changes without pitch shifting. Created comprehensive test suite (`test_variable_tempo.cc`) verifying 2x speed-up and 2x slow-down "reset tricks" work perfectly. All 6 test scenarios pass with mathematical precision. System ready for expressive tempo control in demo with zero size impact.

- **Task #51: Tracker Timing Verification System**: Created robust audio testing infrastructure with mock backend abstraction. Implemented `AudioBackend` interface separating synthesis from output, `MiniaudioBackend` for production, and `MockAudioBackend` for testing. Added event recording with precise timestamp tracking (32kHz sample rate). Created comprehensive test suite (`test_tracker_timing.cc`) that **verified simultaneous pattern triggers have 0.000ms delta** (perfect synchronization). All test infrastructure under `#if !defined(STRIP_ALL)` for zero production impact. 17/17 tests passing.

#### Milestone: Audio Lifecycle Refactor (February 5, 2026)
- **Task #56: AudioEngine Implementation**: Completed 4-phase refactor to eliminate fragile initialization order dependency between synth and tracker. **Phase 1 (Design & Prototype)**: Created `AudioEngine` class and `SpectrogramResourceManager` for unified lifecycle management with lazy loading. **Phase 2 (Test Migration)**: Migrated all tracker tests to use AudioEngine (test_tracker.cc, test_tracker_timing.cc, test_variable_tempo.cc, test_wav_dump.cc). **Phase 3 (Production Integration)**: Updated main.cc to use AudioEngine, fixed pre-existing procedural texture crash (flash_cube_effect.cc, hybrid_3d_effect.cc). **Phase 4 (Cleanup & Documentation)**: Removed backwards compatibility (synth_init from audio_init), updated HOWTO.md and CONTRIBUTING.md with usage patterns. Result: All 20 tests pass, binary size impact <500 bytes, initialization fragility eliminated.

#### Milestone: Build System Optimization (February 6, 2026)
- **Task C: CMake Dependency Graph Optimization**: Resolved critical build correctness bugs and improved developer iteration speed. **Header Split**: Refactored monolithic `asset_manager.h` (61 lines) into three focused headers: `asset_manager_dcl.h` (forward declarations for AssetId), `asset_manager.h` (core GetAsset/DropAsset API), and `asset_manager_utils.h` (typed helpers for TextureAsset/MeshAsset). Updated 17 source files to use appropriate headers. **Asset Dependency Tracking**: Implemented file-level dependency tracking for all 42 demo assets and 17 test assets. CMake now correctly tracks individual `.wgsl` shaders, `.spec` audio files, and `.obj` mesh files. **Critical Bug Fixed**: Changing shader files was NOT triggering asset regeneration, resulting in stale code in binaries. Developers had to manually `touch demo_assets.txt` as workaround. Now works correctly. **Performance**: Editing TextureAsset/MeshAsset helpers improved from 4.82s to 2.01s (58% faster). Shader edits now trigger correct 3.5s rebuild (was 0.28s with no rebuild - incorrect). **Implementation**: Added `parse_asset_list()` CMake function that parses `demo_assets.txt` format (`ASSET_NAME, COMPRESSION, FILENAME, DESC`) and extracts individual file paths for dependency tracking. All 20 tests pass. Zero functionality regressions.

#### Milestone: Critical Shader Stability & Test Infrastructure (February 6, 2026) ✅
- **Shader Crash Resolution**: Fixed three critical WGSL validation errors causing demo64k and test_3d_render to crash on startup. **Bug 1 (renderer_3d.wgsl)**: Removed dead code using non-existent `inverse()` function - WGSL doesn't provide matrix inverse, and validator checks all code paths even unreachable ones. Also removed reference to undefined `in.normal` vertex input. **Bug 2 (sdf_utils.wgsl, lighting.wgsl)**: Fixed `get_normal_basic()` function signature mismatch - changed from `obj_type: f32` to `obj_params: vec4<f32>` to match `get_dist()` calls. **Bug 3 (scene_query_linear.wgsl - ROOT CAUSE)**: Fixed linear scene query mode incorrectly declaring binding 2 (BVH storage buffer). Linear version was identical to BVH version due to copy-paste error. Replaced BVH traversal with proper linear object iteration loop. **Impact**: When `use_bvh=false`, pipeline created without binding 2, but shader expected it → validation error → crash.

- **Comprehensive Shader Compilation Tests**: Created `test_shader_compilation.cc` to prevent regression. Test compiles all production shaders through WebGPU (`wgpuDeviceCreateShaderModule`), validates both BVH and Linear composition modes using `ShaderComposer`, catches WGSL syntax errors, binding mismatches, type errors, and function signature issues. **Test Gap Analysis**: Existing `test_shader_assets.cc` only checked for keywords (`@vertex`, `fn`, etc.) without actual compilation - would NOT have caught any of the three bugs. New test fills this gap with real GPU validation. **Graceful Degradation**: Test handles platforms where WebGPU device unavailable by skipping GPU tests but still validating shader composition.

- **Results**: demo64k runs cleanly without WebGPU errors, test_3d_render no longer crashes, 22/23 tests pass (FftTest unrelated to this work), comprehensive regression prevention infrastructure in place. All shader composition modes (BVH/Linear) now validated in CI. Files modified: renderer_3d.wgsl, sdf_utils.wgsl, lighting.wgsl, scene_query_linear.wgsl, test_shader_compilation.cc (new), CMakeLists.txt.

#### Milestone: FFT-based DCT/IDCT Complete (February 6, 2026) ✅
- **Core FFT Implementation**: Replaced failing double-and-mirror method with Numerical Recipes reordering method for DCT via FFT. Fixed reference IDCT to use DCT-III (inverse of DCT-II, not IDCT-II). All transforms now use orthonormal normalization: sqrt(1/N) for DC term, sqrt(2/N) for AC terms. Result: Perfect round-trip accuracy for impulse signals, <5e-3 error for sinusoidals (acceptable for FFT).

- **Audio Pipeline Integration**: Integrated FFT-based DCT/IDCT into audio engine (`src/audio/idct.cc`, `fdct.cc`) and both web editors (`tools/spectral_editor/dct.js`, `tools/editor/dct.js`). All synthesis paths now use fast O(N log N) FFT instead of O(N²) naive DCT. Regenerated all 14 spectrogram assets with orthonormal DCT to match new synthesis engine.

- **Critical Fixes**: **(1) Normalization Mismatch**: Old non-orthonormal DCT produced 16× larger values. Solution: Regenerated all `.spec` assets with orthonormal DCT. **(2) Procedural Notes**: NOTE_* generation inaudible after normalization change. Solution: Added sqrt(DCT_SIZE/2) = 16× scaling compensation in `gen.cc`. **(3) Windowing Error**: Hamming window incorrectly applied to spectrum before IDCT (should only be used for analysis, not synthesis). Solution: Removed windowing from `synth.cc` and both editors. Result: Correct volume, no distortion, clean frequency spectrum.

- **Testing & Verification**: All 23 tests pass (100% success rate). Round-trip accuracy verified (impulse at index 0: perfect). Audio playback: correct volume, no distortion. Procedural notes: audible at correct levels. Web editors: clean spectrum, no comb artifacts. WAV dumps match expected output.

- **Key Technical Insights**: (1) DCT-III is the inverse of DCT-II, not IDCT-II. (2) Hamming window is ONLY for analysis (before DCT), NOT synthesis (before IDCT). (3) Orthonormal DCT produces sqrt(N/2) smaller values than non-orthonormal. (4) Reordering method is more accurate than double-and-mirror for DCT via FFT. (5) Round-trip accuracy is more important than absolute DCT accuracy.

#### Milestone: Interactive Timeline Editor (February 5, 2026) 🎉
- **Task #57 Phase 1: Production-Ready Timeline Editor**: Created fully functional web-based editor for `demo.seq` timeline files. **Core Features**: Load/save demo.seq with BPM parsing, Gantt-style visual timeline, drag & drop sequences/effects with snap-to-beat, resize handles (left/right) allowing negative relative times, stack-order based priority system (Up/Down buttons + "Same as Above" toggle), floating auto-apply properties panel, diagonal mouse wheel scroll with 10% viewport slack, dynamic sequence bounds calculation, delete/add sequences, re-order by time. **Audio Visualization**: WAV waveform display above timeline using Web Audio API, scales with zoom (pixels per second), documented integration with `--dump_wav` flag for aligning sequences with actual demo audio output. **UI Polish**: Hoverable sequence names (large centered, fades on hover), hidden scrollbars, crosshair cursor on waveform, flash animation on active sequence change, clean minimal interface. **Bug Fixes**: Resolved critical e.target vs e.currentTarget drag offset bug, fixed sequence overlap with cumulative Y positioning, corrected effect relative time calculations. **Files**: `tools/timeline_editor/index.html` (~1200 lines pure HTML/CSS/JS, no dependencies), `README.md` (usage guide, wav_dump integration docs), `ROADMAP.md` (3 phases, 117-161 hour estimate). **Next**: Phase 1.2 (Add Effect button), Phase 2.5 (music.track visualization overlay). **Impact**: Visual timeline editing now production-ready, eliminates manual text editing for sequence placement and timing adjustments.

#### Other Completed Tasks
- **Task #50: WGSL Modularization**: Updated `ShaderComposer` to support recursive `#include` directives, refactored the entire shader library into granular snippets (shapes, utils, lighting), and updated the 3D renderer to use this modular system. This resolved macOS shader compilation issues and significantly improved shader maintainability.
- **Task #48: Improve Audio Coverage**: Achieved 93% coverage for `src/audio/` by adding dedicated tests for DCT transforms, procedural generation, and synthesis rendering.
- **Task #47: Improve Asset Manager Coverage**: Increased `asset_manager.cc` coverage to 88% by testing runtime error paths (unknown functions, generation failure).
- **Task #46: Enhance Coverage Script**: Updated coverage report script to support directory filtering (e.g., `./scripts/gen_coverage_report.sh src/procedural`).
- **Task #45: Improve Procedural Generation Coverage**: Achieved 96% coverage for `src/procedural/` by implementing comprehensive tests for Perlin noise, periodic blending, and parameter handling.
- **Task #44: Developer Tooling (Coverage)**: Added `DEMO_ENABLE_COVERAGE` CMake option and created `scripts/gen_coverage_report.sh` to generate HTML coverage reports using `lcov` on macOS.
- **Skybox & Two-pass Rendering Stability**: Resolved "black screen" and validation errors by implementing a robust two-pass rendering architecture (Pass 1: Skybox/Clear, Pass 2: Scene Objects). Implemented a rotating skybox using world-space ray unprojection (`inv_view_proj`) and a multi-octave procedural noise generator.
- **Task #20: Platform & Code Hygiene**: Consolidated platform-specific shims and WebGPU headers into `platform.h`. Refactored `platform_init` and `platform_poll` for better abstraction. Removed STL containers from initial hot paths (`AssetManager`, `procedural`). Full STL removal for CRT replacement is deferred to the final optimization phase.
- **Task #26: Shader Asset Testing & Validation**: Developed comprehensive tests for `ShaderComposer` and WGSL asset loading/composition. Added a shader validation test to ensure production assets are valid.
- **Asset Pipeline Improvement**: Created a robust `gen_spectrograms.sh` script to automate the conversion of `.wav` and `.aif` files to `.spec` format, replacing the old, fragile script. Added 13 new drum and bass samples to the project.
- **Build System Consolidation (Task #25)**: Modularized the build by creating subsystem libraries (audio, gpu, 3d, util, procedural) and implemented helper macros to reduce boilerplate in `CMakeLists.txt`. This improves build maintenance and prepares for future CRT replacement.
- **Asset System Robustness**: Resolved "static initialization order fiasco" by wrapping the asset table in a "Construct On First Use" getter (`GetAssetRecordTable()`), ensuring assets are available during dynamic global initialization (e.g., shader strings).
- **Shader Asset Integration (Task #24)**: Extracted all hardcoded WGSL strings into `.wgsl` assets, registered them in `demo_assets.txt`, and updated `Renderer3D`, `VisualDebug`, and `Effects` to use `GetAsset` and `ShaderComposer`.
- **WebGPU Stabilization**: Resolved `WGPUSurface` creation failures on macOS by adding platform-specific `GLFW_EXPOSE_NATIVE_COCOA` definitions and fixed validation errors in the render pass configuration.
- **Final Build Stripping (Task #8)**: Implemented the `STRIP_ALL` macro to remove non-essential code (CLI parsing, debug labels, iostream) and refined size optimization flags (`-dead_strip`) for macOS.
- **Minimal Audio Tracker (Task 21.3)**: Finalized a pattern-based audio tracker supporting both procedural notes and asset-based spectrograms with a unified "one-voice-per-pattern" pasting strategy.
- **WGSL Library (Task 21.1)**: Implemented `ShaderComposer` for modular WGSL snippet management.
- **Tight Ray Bounds (Task 21.2)**: Implemented local-space ray-box intersection to optimize SDF raymarching.
- **High-DPI Fix**: Resolved viewport "squishing" via dynamic resolution uniforms and explicit viewports.
- **Unified 3D Shadows**: Implemented robust SDF shadows across all objects using `inv_model` transforms.
- **test_mesh tool**: Implemented a standalone `test_mesh` tool for visualizing OBJ files with debug normal display.