summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-02-28refactor(gpu): move SamplerCache impl to .cc, expose single entry pointskal
get_or_create() and clear() moved out of the header-only class. SamplerSpec and presets remain inline (trivial, no deps). handoff(Gemini): sampler_cache split into .h/.cc, sampler_cache.cc added to COMMON_GPU_EFFECTS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28remove SDFEffect base class and sdf_test, update SDF_EFFECT_GUIDEskal
- Delete unused SDFEffect base class (src/gpu/sdf_effect.h) - Delete sdf_test.wgsl and SHADER_SDF_TEST from assets.txt - Rewrite SDF_EFFECT_GUIDE.md based on Scene1 canonical pattern: correct bindings (2/3), vec4f syntax, UniformsSequenceParams - Fix missing newline at end of gpu.h handoff(Claude): SDF cleanup done, guide updated to match current Effect API
2026-02-28remove vestigial demo_effects.ccskal
handoff(Gemini): deleted src/gpu/demo_effects.cc (empty stub), removed from headless GPU_SOURCES in DemoSourceLists.cmake, dropped stale #include from post_process_helper.cc. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28replace wgsl type: vec4<f32> -> vec4f ..skal
2026-02-28fix: double-free of external views in NodeRegistry and PASSTHROUGH shader testskal
- NodeRegistry: skip external nodes (texture==nullptr) in ~NodeRegistry() and resize() to avoid double-releasing views set via set_external_view() - test_shader_assets: update PASSTHROUGH check to match #include pattern handoff(Claude): 35/35 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28fix(shaders): deduplicate VertexOutput/vs_main via render/fullscreen_uv_vs ↵skal
snippet - Fix vs_main return type (VertexOutput, not vec4<f32>) - Fix #include paths in passthrough, gaussian_blur, heptagon, combined_postprocess - ShaderComposer: assert + suggest correct path on missing #include (non-STRIP_ALL) - VerifyIncludes: upgrade WARNING to ERROR + assert, add "did you mean?" hint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27remove old files, add new training setskal
2026-02-23docs(build): add WSL (Windows 10) build support and documentationskal
- build_win.sh: platform-aware MinGW DLL search (macOS Homebrew vs Linux apt paths) - HOWTO.md: new WSL section covering native Linux build and Windows cross-compile - PROJECT_CONTEXT.md: note WSL support in Build status handoff(Gemini): WSL native + cross-compile build support added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21docs: Update WGSL files to use shorter vector and matrix type aliasesskal
Replaced `vec2<f32>`, `vec3<f32>`, `vec4<f32>`, `mat4x4<f32>`, and `mat3x3<f32>` with their shorter aliases `vec2f`, `vec3f`, `vec4f`, `mat4x4f`, and `mat3x3f` across all WGSL shader files in `workspaces/main/shaders/`. This improves readability and aligns with modern WGSL conventions.
2026-02-21test: fix test_effect_base intermittent crashes and SIGTRAPskal
- Fix stack-use-after-scope dangling reference by storing mutable GpuContext in WebGPUTestFixture. - Fix wgpuDevicePoll causing SIGTRAP and replace with target.read_pixels() to block for GPU teardown safely. - Fix WGPUCommandEncoder leak.
2026-02-21refactor(wgsl): Use vec*f alias for vector typesskal
Replaces all instances of `vec<f32>` with the more concise `vec*f` alias (e.g., `vec3f`) across all `.wgsl` shaders. This improves readability and aligns with common graphics programming conventions. Also adds a new coding style rule to `doc/CODING_STYLE.md` to enforce this standard going forward. Finally, this commit fixes a build error in `test_effect_base.cc` by replacing a call to the non-existent `wgpuDeviceTick` with `wgpuDevicePoll`, which resolves the test failure.
2026-02-21fix(tests): Resolve intermittent SIGTRAP in test_effect_baseskal
The test `test_sequence_render` was disabled due to an intermittent SIGTRAP. The issue was caused by the test application exiting before the GPU finished rendering. This commit fixes the issue by adding a call to `wgpuDeviceTick()` after submitting the command buffer. This ensures that the GPU has completed its work before the test finishes. The test is now re-enabled and passes consistently.
2026-02-21split raymarching.wgsl in two: with id, or without id.skal
2026-02-21refactor(wgsl): Factorize getScreenCoord helperskal
Factorizes the screen coordinate calculation from scene1.wgsl into a reusable getScreenCoord function in common/shaders/math/common_utils.wgsl. This improves code reuse and simplifies fragment shaders.
2026-02-21docs: Proposal for scene1.wgsl SDF helper integrationskal
2026-02-21docs: Update test count in PROJECT_CONTEXT.md to 35/35.skal
This commit resolves an inconsistency in the documentation by updating the test count in to match the 35/35 passing tests reported in .
2026-02-21feat(math): Add vec3::rotate methods for quaternion and axis-angle rotationskal
Adds two convenient methods to the struct: - : Rotates the vector by a given quaternion. - : Rotates the vector around a given axis by an angle in radians. These functions provide a more intuitive and streamlined syntax for vector rotation, improving code readability and usability.
2026-02-21feat: Add vec3::rotate function for quaternion rotation.skal
2026-02-21refine scene1 shaderskal
2026-02-20fix(scene1): refactor render0/render1 to accept Ray structskal
Pass Ray directly instead of separate ro/rd params; minor cleanup (remove redundant consts, cache ray.direction.y). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20feat(scene1): replace ad-hoc camera with CameraParams uniformskal
Build camera via mat4::look_at + inverse in scene1_effect.cc, upload as CameraParams at binding 3. Shader uses getCameraRay() from camera_common. Enable camera_common snippet registration in shaders.cc. handoff(Claude): Scene1 camera now driven by CameraParams uniform; fov=TAU/6 (60° vFOV) matches original tan(PI/3) parameterization. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20feat(sequence): port Scene1Effect + fix seq_compiler absolute time bugskal
- Add Scene1 effect: raymarching cube+sphere+ground (reflections, shadows) - Fix scene1.wgsl: binding 0→2, CommonUniforms→UniformsSequenceParams - Replace Heptagon+Placeholder stub in heptagon_scene with Scene1 - Fix seq_compiler.py: emit seq.start_time+effect.start/end (absolute times) so dispatch_render active check works correctly for all sequences Bug: effects in sequences starting after t=0 were never active because local times (e.g. 0-8) never satisfied params.time<end for absolute time 20+. 34/34 tests passing. handoff(Gemini): seq_compiler now emits absolute effect times. All existing sequences affected — verify visual output across the full timeline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19update tools mq-editor TODOskal
2026-02-19fix(mq_editor): offset playhead to partial t_start when playing single ↵skal
partial (key 3) handoff(Claude): playhead offset fix for single partial playback
2026-02-19fix(mq_editor): remove duplicate mode toggle, add SINE badge, fix ↵skal
mini-spectrum invalidation - Remove redundant synthModeToggle from _updatePropPanel + index.html - Add SINE badge (grey) to panel title, matching existing RES badge (blue) - Invalidate mini-spectrum (viewer.render) on sinusoid/resonator switch handoff(Claude): mq_editor partial panel polish
2026-02-19feat(mq_editor): UI revamp — params panel, layout, partial spectrumskal
- Move Synthesis controls (integratePhase, jitter, spread, resonator, LP/HP filters) and Auto Spread All into the ⚙ Params dropdown - Group Extract Partials / +Partial / ✕ Clear All in one toolbar group - Add per-partial Sine/Res mode toggle in the property panel (Mode row) - Move partial mini-spectrum below the right panel (right-col layout) - Partial mini-spectrum: dynamic dB range scanned across full duration (8 samples, [peak−60, peak]), cached on partial select - Print bezier amplitude A= in red at top-right of partial spectrum - Status/info messages set to 80% gray (#ccc) handoff(Claude): UI revamp complete, TODO items implemented. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19fix(mq_editor): jitter + central spectrum invalidationskal
mq_synth.js: - jitter was only used as a static initial phase offset (inaudible); now drives per-sample LCG frequency perturbation (±jitter fraction of instantaneous freq) in both sinusoidal (integratePhase path) and resonator modes (separate jitterSeed, independent from noise excitation) - disableJitter option now correctly gates jitter to 0 in both modes (was never read before) viewer.js / app.js: - remove invalidatePartialSpectrum() and onResonatorParamChange callback; replace with viewer.onGetSynthOpts callback, called inside _computePartialSpectrum to pull fresh synthOpts at compute time - all UI changes (resonator r/gain, forceResonator, globalR/gain, forceRGain, sinusoidal params) now use viewer.render() as the single invalidation path — no more split between render() and invalidatePartialSpectrum() handoff(Gemini): jitter active on both synth modes; spectrum always sees fresh synthOpts via onGetSynthOpts; viewer.render() is the only invalidation path needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19fix(mq_editor): fuse spread_above/below into single spread paramskal
Asymmetric spread offset the pitch center. Replace with a single symmetric `spread` in harmonics config. autodetectSpread now returns max(above, below). Update all defaults, UI, comments, and README. handoff(Gemini): spread is now a single param; no compat shims. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18fix(mq_editor): partial mini-spectrum — correct FFT, time selection, ↵skal
resonator sync - Fix: fftRadix2 called without bitReversePermute → noisy spectrum (use fftForward) - specTime = mouse pos if inside partial [t0,t3], else center of partial interval - Cache check moved before canvas clear to keep spectrum visible outside [t0,t3] - viewer.synthOpts forwarded to synthesizeMQ so forceResonator/globalR/gain apply - invalidatePartialSpectrum() wired to forceResonator/forceRGain/globalR/globalGain handoff(Gemini): mini-spectrum now correct; fft bug fixed, resonator mode synced
2026-02-18feat(mq_editor): partial spectrum viewer — synth+FFT power displayskal
Adds a 200×100 canvas (left of the main spectrum overlay) that shows the synthesised power spectrum of the selected partial at the time under the mouse (or playhead). Pipeline: synthesizeMQ → Hann window → FFT (2048-pt) → dB power bars. - freqCurve times are shifted so the synthesis window is centred on t - X-axis: log-frequency (same scale as main view) - Y-axis: dB, normalised to peak of the synthesised frame - Cache: {partialIndex, time} → avoids re-synthesis on mouse move; bypassed (force=true) from render() so param changes always redraw handoff(Claude): partial spectrum viewer complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): replace replicas with harmonics modelskal
- Fundamental f0 always synthesized; harmonics added at n*freq_mult - decay^n amplitude rolloff per harmonic (capped at 0.90) - Resonator mode also expanded across harmonics (per-harmonic y1/y2 state) - UI: h.decay, h.freq (default 2.0), jitter, spread↑/↓ params - Viewer: faint dotted harmonic bands with spread visualization - Default freq_mult=2.0 (natural harmonic series) handoff(Gemini): harmonics model complete, ready for next task Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18fix(mq_editor): swap keys 1/2 — 1=original, 2=synth, 3=partialskal
handoff(Gemini): key bindings updated in app.js and README.md
2026-02-18fix(mq_editor): destroy old viewer listeners on WAV reloadskal
Each loadAudioBuffer() was creating a new SpectrogramViewer without removing the previous one's canvas event listeners. Old viewers would fire on every mouse event, rendering stale spectrogram data and calling editor.onPartialSelect() with out-of-range indices (hiding the amp panel). Fix: store handlers as named instance properties, add destroy() to remove them, and call destroy() before creating a new viewer. handoff(Claude): bug fix only, no behaviour change Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): movable inner bezier control points + clamp() refactorskal
- P1/P2 in amp editor now draggable horizontally; t0<t1<t2<t3 enforced - Add clamp() to utils.js; replace all Math.max/min clamping patterns - Cursor hints: move for P1/P2, ns-resize for P0/P3 - Remove test_fft.html - Docs: Delete key, style.css/utils.js in architecture, bezier editor section handoff(Claude): inner control points done, clamp() adopted everywhere Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): group toolbar buttons with separatorsskal
handoff(Claude): toolbar buttons grouped with vertical separators: [Open WAV] | [Extract][AutoSpread] | [Play][Stop] | [+Partial][ClearAll] | [Explore][Contour] | [Undo][Redo] | [Params] Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18refactor(mq_editor): extract refreshPartialsView() and playOriginal() helpersskal
- refreshPartialsView(selectIdx) consolidates editor+viewer sync (5 call sites) - playOriginal() replaces inline play button logic; Digit2 calls it directly - autoSpreadAll() now called after extractPartials via named function handoff(Claude): factored common button actions in app.js
2026-02-18feat(mq_editor): add Delete key to remove selected partial; remove Test WAV ↵skal
debug button - 'Delete'/'Backspace' key deletes the currently selected partial - Show 'Del' hint on Delete button in side panel - Remove 'Test WAV' button and validateTestWAVPeaks() debug code Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18fix(mq_editor): key '3' plays partial from t_start; add getAudioBuffer()skal
- synthesizeMQ output trimmed to [t_start-50ms, t_end+50ms] so playback starts immediately at the partial instead of t=0 - Extract synth+trim logic into getAudioBuffer(partials, margin=0) - Stack params vertically in dropdown (grid layout) handoff(Claude): partial playback and CSS param layout fixes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18refactor(mq_editor): extract CSS to style.css, consolidate UI paramsskal
- Move all styles from index.html <style> block to style.css - Merge duplicate :focus rules; add canvas-col, canvas-wrap, amp-edit-header, slider-val classes - Move params (Hop/Threshold/Prominence/Birth/Death/Phase Wt/Min Len) into ⚙ Params dropdown - Relocate Keep slider to bottom-left canvas overlay handoff(Claude): UI consolidation complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): switch curve interpolation to Lagrange through all control ↵skal
points Replace cubic Bezier with Lagrange interpolation so P1/P2 are actual points on the curve. Eval uses stored t1/t2 as arbitrary knot positions. fitBezier keeps least-squares but with Lagrange basis at u=1/3,2/3. Remove endpoint companion drag (no longer tangent handles). TODO: support arbitrary number of inner control points. handoff(Claude): Lagrange interpolation replaces Bezier in mq_editor curve eval/fit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18docs(mq_editor): document Explore and Contour interactive modesskal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): add iso-contour tracking mode for bass/diffuse regionsskal
trackIsoContour() follows constant energy level through STFT frames instead of peaks. Useful for broad bass areas where peak detector finds nothing. Preview in cyan, auto-detects spread on commit (naturally large). Toggle: ≋ Contour button or C key. Mutually exclusive with ⊕ Explore. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18fix(mq_editor): enable explore mode immediately on WAV loadskal
Pre-compute peak frames after STFT cache is built, so trackFromSeed works without requiring Extract Partials first. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): add explore mode for interactive partial trackingskal
Hover to preview a tracked partial from mouse position (peak-snapped, forward+backward MQ tracking). Click to commit. Toggle with ⊕ Explore button or X key. Escape exits explore mode. handoff(Gemini): explore mode added in mq_extract.trackFromSeed + viewer.js/app.js Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): add clear all partials buttonskal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18perf(mq_editor): move playhead to overlay canvas, avoid full render on tickskal
setPlayheadTime() now updates only the playhead overlay and spectrum panel instead of triggering a full renderSpectrogram() every rAF tick. handoff(Gemini): playhead is now an overlay canvas (like cursorCanvas), no more O(n_frames) redraw during playback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18feat(mq_editor): add new partial, undo/redoskal
- '+ Partial' button (N key): insert 440Hz/max-amp partial at front - Undo/Redo buttons (Ctrl+Z/Y): JSON snapshot stack, 50 levels - Hooks in delete, mute, curve edits, amp drag, freq drag handoff(Gemini): undo/redo + new-partial added to mq_editor Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18fix(mq_editor): exclude below-keep partials from hit-test selectionskal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18refactor(mq_editor): unify freq+amp into single bezier curveskal
freqCurve now carries a0-a3 (amplitude control values) alongside v0-v3 (frequency). Both components share the same t0-t3 time parameterization. evalBezierAmp() added to utils.js. ampCurve removed from partials and synth pipeline. Amp panel drag now changes only a_i; t is read-only (shared with freq). handoff(Claude): unified freq/amp bezier done
2026-02-18fix(mq_editor): apply coupled anchor drag to freqCurve in viewer canvasskal
Same P0↔P1 / P3↔P2 coupling as the amp editor, now for the frequency bezier dragged in the main spectrogram viewer. handoff(Claude): freq curve coupled drag fixed