Skip to content

Per-channel mute via the libopenmpt_ext interactive interface - #8

Open
LumenPrima wants to merge 1 commit into
DrSnuggles:v3from
LumenPrima:feat/channel-mute
Open

Per-channel mute via the libopenmpt_ext interactive interface#8
LumenPrima wants to merge 1 commit into
DrSnuggles:v3from
LumenPrima:feat/channel-mute

Conversation

@LumenPrima

Copy link
Copy Markdown

Fills in the toggleMute stub in the worklet.

Why it was a stub

libopenmpt only exposes channel mute through openmpt_module_ext's interactive interface, which comes back as a struct of C function pointers rather than exported functions. Calling one from JS needs the wasm function table, and Emscripten doesn't put wasmTable (or HEAP32, needed to read the pointers) on the module object unless asked. Older toolchains did by default, which is how Chipsound (a libopenmpt-based player built on chiptune3) has had mute working; the Emscripten 6 build dropped them.

What

  • docker/Dockerfile: add HEAP32 and wasmTable to EXPORTED_RUNTIME_METHODS. The rebuilt libopenmpt.worklet.js is included (same 0.8.7, +37 bytes); happy to drop it if you'd rather rebuild yourself.
  • chiptune3.worklet.js: create the module via openmpt_module_ext_create_from_memory and take the plain handle from openmpt_module_ext_get_module (everything else keeps using modulePtr); resolve set/get_channel_mute_status from the interactive interface once per load; destroy via the ext handle. New messages setChannelMute {ch, mute} and toggleMute ch; the worklet replies with channelMute {ch, mute} read back from libopenmpt so the state is authoritative. On a build without the exports, mute is unavailable and a warning is logged once.
  • chiptune3.js: setChannelMute(ch, mute), toggleMute(ch), onChannelMute(({ch, mute}) => …).
  • index.html: a row in the API table. README: feature and history lines. Minified files regenerated with npm run minify.

Mutes reset on each load, as libopenmpt does.

Verified

  • Node, driving the worklet with stubbed AudioWorklet globals against aryx.s3m (12 ch): mute reply {ch:0, mute:true}, toggle back false, all channels muted → output silent after the ramp-down block, unmute → audio returns, reload resets, stop() frees the interface and both handles.
  • Chromium, real AudioWorklet: Chipsound's existing mute path (which reads wasmTable) works unchanged against this build; it is silent against the current published one.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LZxPVZVBEDisdipGRJfcwn

Fills in the toggleMute stub. libopenmpt exposes channel mute only
through openmpt_module_ext's "interactive" interface, a struct of C
function pointers, so calling it from JS needs the wasm function table.

- docker/Dockerfile: export HEAP32 and wasmTable alongside the existing
  runtime methods (rebuilt libopenmpt.worklet.js included, +37 bytes).
- worklet: create the module through openmpt_module_ext_create_from_memory
  and take the plain handle from openmpt_module_ext_get_module; resolve
  set/get_channel_mute_status once per load; destroy through the ext
  handle. New messages setChannelMute {ch, mute} and toggleMute ch; the
  worklet replies with channelMute {ch, mute} read back from libopenmpt.
  On a build without the exports mute is unavailable and warns once.
- chiptune3.js: setChannelMute(ch, mute), toggleMute(ch), onChannelMute.
- index.html: a toggle row in the API table. README: feature + history.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZxPVZVBEDisdipGRJfcwn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant