refactor(studio): extract the Web Audio engine to src/audio-graph.js (step 5)#20
Conversation
…(step 5)
Move the playback graph (_getAudioCtx, _createReverbBus, _play/_pause,
_stopAllSources, _applyMixToLiveAudio/_applyAllMixToLive, _hasSoloActive) out of
main.js. It's the lower audio layer: the per-frame playhead loop + master meter
it starts (_startAnimLoop/_stopAnimLoop/_startMasterMeter — animation/render
layer, still in main.js) are injected via configureAudioGraph({...}) at boot, so
audio-graph doesn't import back into main.js (no cycle). Bodies moved verbatim
except the 3 hook calls. _hasSoloActive kept internal. main.js 2711 -> 2489.
node 11/11, python 25/25.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe Web Audio playback engine is extracted from ChangesAudio graph extraction
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR continues the ES-module migration by extracting the Web Audio playback engine from src/main.js into a new lower-level module src/audio-graph.js, using configureAudioGraph({...}) to inject animation/meter hooks and avoid an import cycle back into main.js.
Changes:
- Moved Web Audio engine functions (
_getAudioCtx,_play/_pause,_stopAllSources, live mix application helpers) frommain.jsinto newsrc/audio-graph.js. - Added
configureAudioGraph({...})boot-time wiring inmain.jsto inject animation loop + master meter seams into the audio layer. - Documented the refactor step in
CHANGELOG.md.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/main.js | Imports audio engine functions from audio-graph.js and wires injected hooks via configureAudioGraph. |
| src/audio-graph.js | New module containing the extracted Web Audio playback engine and injection seam. |
| CHANGELOG.md | Notes migration step 5 and the cycle-breaking injection approach. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/audio-graph.js`:
- Around line 222-229: The original-track branch in _applyMixToLiveAudio can
throw when S.mixState.original is missing, unlike _play() and
_applyAllMixToLive() which already handle that fallback. Update the trackKey ===
'original' path to use the same safe original-track mix state lookup and guard
against an uninitialized S.mixState.original before reading st.muted, st.solo,
st.volume, or st.pan so live updates for original do not fail.
- Around line 172-180: The reverb send in audio-graph.js is currently tapped
from eqHigh before the main gain stage, so tracks that are muted, soloed out, or
faded can still feed the wet path. Update the reverb-send routing in the audio
graph setup to source from gain instead of eqHigh, or otherwise apply the same
effective mute/solo/fade gain to the send, keeping the existing reverbNode
connection behavior intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 5748d2f9-bab9-4f9a-bd22-7a45bc4a4881
📒 Files selected for processing (3)
CHANGELOG.mdsrc/audio-graph.jssrc/main.js
… deferred Address review on #20: - configureAudioGraph(h={}) with typeof-function guards (safe no-arg / bad-value). - ctx.resume(): swallow the promise rejection (autoplay/gesture blocks) instead of leaving it unhandled. - add tests/audio-graph.test.mjs (export surface, configure-seam wiring via _pause -> injected stopAnimLoop, no-arg tolerance). node 14/14, python 25/25. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address CodeRabbit minor on #20 — match the sibling track branch's defensive default so a live 'original' update can't throw if mixState.original is ever absent. (Container always inits it; consistency + belt-and-suspenders.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Step 5 — the first entangled-core extraction. Moves the Web Audio playback engine out of
main.jsintosrc/audio-graph.js:_getAudioCtx,_createReverbBus(internal),_play/_pause,_stopAllSources,_applyMixToLiveAudio/_applyAllMixToLive,_hasSoloActive(internal)Breaking the cycle
audio ↔ animation ↔ waveform are mutually coupled:
_playstarts the per-frame playhead loop + master meter (_startAnimLoop/_stopAnimLoop/_startMasterMeter), which live with the animation/render layer inmain.js. Rather than a static cycle (banned by the no-cycle gate), those 3 are injected viaconfigureAudioGraph({...})wired once at boot — soaudio-graph.jsis a clean lower layer that never imports back intomain.js. Bodies moved verbatim except the 3 hook calls.main.js2711 → 2489.Tests
node --test11/11,pytest25/25 (backend unaffected). Codex preflight: 0.Summary by CodeRabbit