The listener's volume and pause, for whatever is playing: the page's own audio and the sandbox's (a listener's song plays in a frame with its own AudioContext; sandbox.mjs passes both on).
Volume is a gain after everything that is measured (superdough's
volume, behind speakers): turning the sound down changes what is
heard, not what the meters, the mixer and Jev read. It is kept per browser.
Pause suspends the AudioContext rather than the scheduler. The scheduler runs on the audio clock, so everything waits in place (the song, held notes and reverb tails, Jev's sections, the highlights, the lyrics) and continues from the same sample, and nothing that watches "stopped" (the performance recorder, autoplay, a party) sees a stop. Playing, stopping or running the code ends a pause, so the play button never plays into a suspended context.
19const VOLUME = 'jevstrudel.volume';
the slider is 0 to 100; the gain is its square, so the middle sounds like half
21export const gainOf = (percent) => Math.pow(Math.min(100, Math.max(0, percent)) / 100, 2);
23const stored = () => { 24 try { 25 const v = Number(localStorage.getItem(VOLUME)); 26 return localStorage.getItem(VOLUME) !== null && v >= 0 && v <= 100 ? v : 100; 27 } catch { 28 return 100; 29 } 30}; 31 32let state = { volume: typeof localStorage === 'undefined' ? 100 : stored(), paused: false }; 33const listeners = new Set(); 34function set(patch) { 35 state = { ...state, ...patch }; 36 for (const l of listeners) l(); 37} 38export const audioControls = { 39 subscribe(l) { 40 listeners.add(l); 41 return () => listeners.delete(l); 42 }, 43 get: () => state, 44}; 45 46function apply() { 47 const gain = gainOf(state.volume); 48 setMasterVolume(gain); 49 sandboxVolume(gain); 50} 51 52export function setVolume(percent) { 53 const volume = Math.round(Math.min(100, Math.max(0, Number(percent) || 0))); 54 try { 55 localStorage.setItem(VOLUME, String(volume)); 56 } catch {} 57 set({ volume }); 58 apply(); 59} 60 61export async function pause() { 62 if (state.paused) return; 63 set({ paused: true }); 64 sandboxPaused(true); 65 await getAudioContext().suspend(); 66}
Also what play, stop and run call (useReplContext): they end a pause.