Implement Sound side-panel section (master audio on/off + volume)#22
Merged
Conversation
New "Sound" section between Sketch and Libraries: an Off/On segmented toggle
and a 0-1 master volume slider, muted by default. Implements the design in
docs/proposals/sound-section.md (now updated with a "Status: implemented"
note listing where the code diverges from the original proposal).
- public/script.js: buildAudioController(enabled, volume) is injected into
the sketch iframe's srcdoc (after captureController, before any imported
library or the sketch code). It wraps AudioContext/webkitAudioContext once
per context - each gets a GainNode spliced in via Reflect.construct(RealAC,
arguments), with `destination` shadowed as an own property on that
instance so anything the sketch connects to ctx.destination lands on the
gain node instead. applyAudioState() posts { type: 'audio-set', enabled,
volume } to push changes live without re-running the sketch.
- public/index.html: the panel markup (segmented toggle + range input),
reusing the existing .sketch-bg-row/.segmented styles.
- public/style.css: minor styling for the new #audio-master-slider.
- AGENTS.md/README.md: document the feature and its security note (no new
capability crosses the sandbox - the postMessage payload is just a
boolean and a 0-1 float).
Verified against a real AudioContext in the running app: ctx.destination
resolves to our GainNode, initial gain matches the baked-in state, and
toggling/adjusting the slider updates gain.value live on an already-running
sketch without a re-run.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the previously proposal-only "Sound" section (
docs/proposals/sound-section.md) - a new panel between Sketch and Libraries with a master Off/On toggle and a 0-1 volume slider over sketch audio, muted by default.buildAudioController(enabled, volume)inscript.jsis injected into the sketch iframe (aftercaptureController, before any imported library/the sketch code). It wrapsAudioContext/webkitAudioContextonce: each context gets aGainNodespliced in viaReflect.construct(RealAC, arguments), withdestinationshadowed as an own property on that instance - so anything the sketch connects toctx.destination(p5.sound, raw Web Audio, an imported library) lands on the gain node instead of real output.applyAudioState()posts{ type: 'audio-set', enabled, volume }to the running sketch so toggling/adjusting the slider takes effect immediately, without re-running.sandbox="allow-scripts"with noallow-same-origin, same as everywhere else in the app.Test plan
node --check public/script.jspasses; extractedbuildAudioController's template and ran it throughvm.Scriptto confirm the injected string itself is valid JS.AudioContext+ oscillator:ctx.destination.constructor.name === 'GainNode'and its initialgain.valuematches the baked-in enabled/volume state.ctx.destination.gain.valueupdates live each time (1->0->0.3) via the postMessage bridge.Generated with Claude Code