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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
|
# To-Do List
This file tracks prioritized tasks with detailed attack plans.
## Recently Completed (February 4, 2026)
- [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 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, 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.
## Priority 1: Physics & Collision (Task #49)
**Goal**: Implement a lightweight physics engine using SDFs and BVH acceleration. (See `doc/3D.md` for design).
- [ ] **Task #49.1: CPU-Side SDF Library**:
- [ ] Create `src/3d/sdf_cpu.h` implementing `sdSphere`, `sdBox`, `sdTorus`, `sdPlane` using `mini_math.h`.
- [ ] Implement `calc_normal` (numerical gradient) for these SDFs.
- [ ] Add unit tests in `src/tests/test_physics.cc` to verify CPU SDFs match ground truth.
- [ ] **Task #49.2: BVH Construction**:
- [ ] Define `BVHNode` struct in `src/3d/bvh.h` (shared/compatible with GPU layout).
- [ ] Implement `BVHBuilder::Build(const std::vector<Object3D>&)` in `src/3d/bvh.cc`.
- [ ] Implement `BVH::Query(AABB)` for broad-phase collision detection.
- [ ] Visualize BVH in `src/tests/test_3d_render.cc` (using `VisualDebug`).
- [ ] **Task #49.3: Physics Loop**:
- [ ] Create `PhysicsSystem` class in `src/3d/physics.h`.
- [ ] Implement `Update(dt)`: Integration -> Broad Phase -> Narrow Phase (SDF Probe) -> Resolution.
- [ ] Add `velocity`, `mass`, `restitution` fields to `Object3D`.
- [ ] Integrate into `test_3d_render.cc` main loop.
## Priority 2: 3D System Enhancements (Task #18)
**Goal:** Establish a pipeline for importing complex 3D scenes to replace hardcoded geometry.
- [ ] **Task #36: Blender Exporter:** Create a Python script (`tools/blender_export.py`) to export meshes/cameras/lights to a binary asset format.
- [ ] **Task #37: Asset Ingestion:** Update `asset_packer` to handle the new 3D binary format.
- [ ] **Task #38: Runtime Loader:** Implement a minimal C++ parser to load the scene data into the ECS/Renderer.
## Priority 3: WGSL Modularization (Task #50) [RECURRENT]
**Goal**: Refactor `ShaderComposer` and WGSL assets to support granular, reusable snippets and `#include` directives. This is an ongoing task to maintain shader code hygiene as new features are added.
## Priority 4: Developer Tooling & CI
**Goal**: Improve developer workflows, code quality, and release processes.
- [ ] **Task #51: Tracker Timing Verification**
- [x] **Task #51.1: Audio Backend Abstraction**: Create an interface to separate audio output from synth logic, enabling testable backends.
- [x] **Task #51.2: Mock Audio Backend**: Implement a test backend that records voice trigger events with precise timestamps.
- [ ] **Task #51.3: Tracker Test Suite**: Create `test_tracker.cc` to verify pattern triggering, timing accuracy, and synchronization.
- [ ] **Task #51.4: Integration with Build**: Wire up tests to CMake and ensure they run in CI.
## Phase 2: Size Optimization (Final Goal)
- [ ] **Task #34: Full STL Removal**: Replace all remaining `std::vector`, `std::map`, and `std::string` usage with custom minimal containers or C-style arrays to allow for CRT replacement. (Minimal Priority - deferred to end).
- [ ] **Task #22: Windows Native Platform**: Replace GLFW with direct Win32 API calls for the final 64k push.
- [ ] **Task #28: Spectrogram Quantization**: Research optimal frequency bin distribution and implement quantization.
- [ ] **Task #35: CRT Replacement**: investigation and implementation of CRT-free entry point.
---
## Task #51: Tracker Timing Verification - Detailed Attack Plan
**Problem Statement**: The tracker and synthesizer have audio sync issues. There's no robust way to verify that tracker patterns trigger at the correct timestamps without running the full audio hardware stack.
**Goal**: Implement a testable audio backend abstraction with event recording capabilities to verify tracker timing accuracy.
### Task #51.1: Audio Backend Abstraction
**Objective**: Decouple audio output from synthesis logic to enable testing without hardware.
**Implementation Steps**:
- [ ] **Create `src/audio/audio_backend.h`**:
- Define `AudioBackend` interface with pure virtual methods:
- `init()`: Initialize backend resources
- `start()`: Start audio playback/recording
- `shutdown()`: Clean up resources
- `on_voice_triggered(timestamp, spec_id, volume, pan)`: Hook for voice events
- Add `#if !defined(STRIP_ALL)` guards around test-only methods
- [ ] **Create `src/audio/miniaudio_backend.h` and `.cc`**:
- Move current miniaudio implementation from `audio.cc` to `MiniaudioBackend` class
- Implement `AudioBackend` interface
- Keep production behavior identical (no regressions)
- This backend does NOT record events (production path)
- [ ] **Refactor `src/audio/audio.cc`**:
- Add global `AudioBackend* g_audio_backend` pointer
- Add `void audio_set_backend(AudioBackend* backend)` function (under `!STRIP_ALL`)
- Default to `MiniaudioBackend` if no backend is set
- Replace direct miniaudio calls with backend interface calls
- [ ] **Update `src/audio/synth.cc`**:
- Add external hook: `extern AudioBackend* g_audio_backend_for_events`
- In `synth_trigger_voice()`, call `backend->on_voice_triggered()` if backend exists
- Ensure hook is `#if !defined(STRIP_ALL)` guarded
**Size Impact**: Zero (test code stripped in final build).
**Validation**: Existing tests (`test_synth.cc`) must pass unchanged.
---
### Task #51.2: Mock Audio Backend
**Objective**: Create a test-only backend that records all audio events with timestamps.
**Implementation Steps**:
- [ ] **Create `src/audio/mock_audio_backend.h` and `.cc`** (under `#if !defined(STRIP_ALL)`):
- Define `struct VoiceTriggerEvent`:
```cpp
struct VoiceTriggerEvent {
float timestamp_sec;
int spectrogram_id;
float volume;
float pan;
};
```
- Implement `MockAudioBackend` class:
- Maintain `std::vector<VoiceTriggerEvent> recorded_events`
- Override `on_voice_triggered()` to record events with current time
- Add `const std::vector<VoiceTriggerEvent>& get_events() const`
- Add `void clear_events()`
- Add `void advance_time(float delta_sec)` to simulate time progression
- Implement `init()`, `start()`, `shutdown()` as no-ops
- [ ] **Time Tracking**:
- Add `float current_time_sec` member to `MockAudioBackend`
- Increment `current_time_sec` in `advance_time()`
- Use `current_time_sec` as timestamp when recording events
- [ ] **Synth Integration**:
- When `synth_render()` is called, calculate frames rendered
- Notify backend of time elapsed: `frames / sample_rate`
- Update mock's internal clock accordingly
**Testing**: Create minimal unit test in `test_tracker.cc` to verify event recording works.
---
### Task #51.3: Tracker Test Suite
**Objective**: Comprehensive tests for tracker pattern triggering and timing accuracy.
**Implementation Steps**:
- [ ] **Create `src/tests/test_tracker.cc`**:
- **Test 1: Single Pattern Trigger**
- Define a minimal `TrackerScore` with 1 pattern at `t=1.0s`
- Set up mock backend
- Call `tracker_update(0.5)` → verify no events
- Call `tracker_update(1.0)` → verify 1 event recorded
- Validate event timestamp matches expected trigger time
- **Test 2: Multiple Pattern Triggers**
- Score with 3 patterns at `t=0.5s, 1.0s, 2.0s`
- Progressively call `tracker_update()` with increasing times
- Verify each pattern triggers exactly once at correct time
- **Test 3: Event Timing Accuracy**
- Pattern with multiple events at different beat offsets
- Verify each event's timestamp matches: `pattern_start_time + (beat * beat_duration)`
- Use tolerance: `±1 frame` (1/32000 sec ≈ 31.25µs)
- **Test 4: BPM Scaling**
- Same pattern tested at different BPMs (60, 120, 180)
- Verify beat-to-time conversion is accurate: `beat_sec = 60.0 / bpm`
- **Test 5: Pattern Overlap**
- Two patterns with overlapping time ranges
- Verify both trigger correctly without interference
- **Test 6: Asset vs Procedural Samples**
- Pattern using both asset-based spectrograms and procedural notes
- Verify both types render and trigger correctly
- **Test 7: Seek/Fast-Forward Simulation**
- Simulate `audio_render_silent()` behavior
- Start at `t=0`, fast-forward to `t=10.0s`
- Verify all patterns in range [0, 10] triggered correctly
- [ ] **Helper Functions**:
```cpp
void assert_event_at_time(const std::vector<VoiceTriggerEvent>& events,
float expected_time, float tolerance = 0.001f);
void assert_event_count(const std::vector<VoiceTriggerEvent>& events,
int expected_count);
TrackerScore create_test_score(const std::vector<float>& trigger_times,
float bpm = 120.0f);
```
**Coverage Target**: 95%+ for `src/audio/tracker.cc`.
---
### Task #51.4: Integration with Build
**Objective**: Wire up tests to CMake and ensure they run automatically.
**Implementation Steps**:
- [ ] **Update `src/CMakeLists.txt`**:
- Add `mock_audio_backend.cc` to test-only sources (under `DEMO_BUILD_TESTS`)
- Link `test_tracker` executable with audio subsystem library
- [ ] **Add test to CTest**:
```cmake
if(DEMO_BUILD_TESTS)
add_executable(test_tracker tests/test_tracker.cc audio/mock_audio_backend.cc)
target_link_libraries(test_tracker PRIVATE audio_lib util_lib)
add_test(NAME TrackerTest COMMAND test_tracker)
endif()
```
- [ ] **Verify in CI**:
- Run `cmake --build build && cd build && ctest`
- Ensure `test_tracker` runs and passes
- Check coverage report includes tracker.cc
**Validation**: `ctest` output shows `TrackerTest: PASSED`.
---
## Implementation Layout Summary
### New Files
```
src/audio/audio_backend.h # Interface definition
src/audio/miniaudio_backend.h # Production backend (header)
src/audio/miniaudio_backend.cc # Production backend (impl)
src/audio/mock_audio_backend.h # Test backend (header, !STRIP_ALL)
src/audio/mock_audio_backend.cc # Test backend (impl, !STRIP_ALL)
src/tests/test_tracker.cc # Comprehensive tracker tests
```
### Modified Files
```
src/audio/audio.cc # Backend abstraction layer
src/audio/synth.cc # Add event hooks
src/CMakeLists.txt # Add new files and tests
```
### File Structure
```
src/audio/
├── audio_backend.h [NEW] Interface (50 lines)
├── miniaudio_backend.h [NEW] Header (30 lines)
├── miniaudio_backend.cc [NEW] Production impl (~100 lines, moved from audio.cc)
├── mock_audio_backend.h [NEW] Test header (60 lines)
├── mock_audio_backend.cc [NEW] Test impl (~120 lines)
├── audio.h [MODIFIED] Add backend setter
├── audio.cc [MODIFIED] Use backend abstraction (~30 lines changed)
├── synth.cc [MODIFIED] Add event hook (~10 lines)
└── tracker.cc [NO CHANGE]
src/tests/
└── test_tracker.cc [NEW] Test suite (~400 lines)
```
### Code Organization Principles
1. **Zero Size Impact**: All test infrastructure under `#if !defined(STRIP_ALL)`
2. **Backward Compatible**: Production path unchanged, existing tests pass
3. **Clean Separation**: Interface-based design, easy to add more backends later
4. **Testable**: Mock backend has minimal dependencies (no hardware/threads)
---
## Future Goals
|