Skip to content

feat: add setStereoSeparation method to ChiptuneJsPlayer#4

Open
indigo423 wants to merge 1 commit into
DrSnuggles:v3from
indigo423:feat/set-stereo-separation
Open

feat: add setStereoSeparation method to ChiptuneJsPlayer#4
indigo423 wants to merge 1 commit into
DrSnuggles:v3from
indigo423:feat/set-stereo-separation

Conversation

@indigo423
Copy link
Copy Markdown

@indigo423 indigo423 commented May 12, 2026

Summary

Adds a setStereoSeparation(val) method to ChiptuneJsPlayer and a matching 'setStereoSeparation' case in the worklet's handleMessage_. Mirrors the existing setPitch / setTempo shape.

Why

The worklet's play() already reads this.config.stereoSeparation and stamps it via openmpt_module_set_render_param at module-create time, and defaultCfg.stereoSeparation is a public config key, but there's currently no path from the main thread to mutate the value after the constructor's auto-config post. Today, changing stereo separation after page load means recreating the ChiptuneJsPlayer — destroying the AudioContext, reloading the worklet, and giving the listener ~0.5s of silence on every tick of a UI slider.

This method fills the gap symmetrically with the existing render-param consumer in play():

  • Posts {cmd:'setStereoSeparation', val} from the main thread.
  • The worklet handler mutates this.config.stereoSeparation so subsequently-loaded modules inherit the value.
  • If a module is currently loaded, the handler also calls _openmpt_module_set_render_param(modulePtr, OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT, val) for an immediate audible update.

The worklet clamps incoming values to [0, 200] (libopenmpt's documented range — 100 = default, 0 = mono, 200 = exaggerated) and falls back to 100 on non-finite values, so callers can be liberal in what they send.

Use case

The CoolModFiles project is using this library and wants a "stereo separation" slider in the player UI so headphone listeners can gradually collapse the classic hard-panned MOD field toward mono. The slider lives in a settings panel and updates the value live as the user drags. A live demo is on https://mods.amiga.fans.

Diff

+14 lines, 2 files. No new dependencies, no API removals.

  • chiptune3.js: setStereoSeparation(val) { this.postMsg('setStereoSeparation', val) } placed next to setTempo.
  • chiptune3.worklet.js: new case 'setStereoSeparation' in handleMessage_ placed next to setTempo.

Notes

  • .min.js siblings are not regenerated in this PR — I assumed minify.js runs as part of a release cut. Happy to include them if you'd prefer.
  • The branch is forked off v3 (current default).

Thanks for chiptune — it's the audio backbone of the site. Glad to send fixes back when we have them.

Add a main-thread entry point to update the stereo-separation render
param on a running module, and to update the worklet's persisted
this.config.stereoSeparation so subsequently-loaded modules inherit
the value without a reload.

Today the worklet's play() handler already reads
this.config.stereoSeparation and stamps it via
openmpt_module_set_render_param at module-create time, but consumers
have no way to mutate the config from the main thread after the
ChiptuneJsPlayer constructor's auto-config post. setStereoSeparation
fills that gap by posting a {cmd:'setStereoSeparation', val} message
that the worklet handles by mutating this.config and (when a module
is loaded) calling set_render_param immediately.

The worklet-side handler clamps incoming values to [0, 200] (the
libopenmpt documented range; 100 = default, 0 = mono) and falls back
to the default 100 on non-finite values, so callers can be liberal
in what they send.

Use case: an Amiga MOD player UI that exposes a "stereo separation"
slider letting listeners gradually collapse the classic hard-panned
field toward mono. Without this method the only way to change the
value after page load is to recreate the ChiptuneJsPlayer (destroys
the AudioContext + reloads the worklet, ~0.5s silence on every
slider tick).

The .min.js siblings are not regenerated in this PR -- I assume
minify.js runs as part of a release cut. Happy to add them if
preferred.

Assisted-by: ClaudeCode:claude-opus-4-7
Signed-off-by: Ronny Trommer <ronny@no42.org>
@indigo423 indigo423 force-pushed the feat/set-stereo-separation branch from e35b889 to baf8e51 Compare May 12, 2026 22:41
indigo423 added a commit to no42-org/CoolModFiles that referenced this pull request May 12, 2026
Add a Stereo separation slider (0% mono → 100% libopenmpt default) to
the Sound pane. Persists under audio.stereoSeparation and rides the
ChiptuneJsPlayer constructor config so the worklet receives it via
the auto-posted {cmd:'config'} message — no per-track re-apply, no
race against audioWorklet.addModule().

Local vendored chiptune3 patch adds a typed setStereoSeparation
method; upstream PR DrSnuggles/chiptune#4 mirrors it.

Assisted-by: ClaudeCode:claude-opus-4-7
indigo423 added a commit to no42-org/CoolModFiles that referenced this pull request May 12, 2026
Add a Stereo separation slider (0% mono → 100% libopenmpt default) to
the Sound pane. Persists under audio.stereoSeparation and rides the
ChiptuneJsPlayer constructor config so the worklet receives it via
the auto-posted {cmd:'config'} message — no per-track re-apply, no
race against audioWorklet.addModule().

Local vendored chiptune3 patch adds a typed setStereoSeparation
method; upstream PR DrSnuggles/chiptune#4 mirrors it.

Assisted-by: ClaudeCode:claude-opus-4-7
Signed-off-by: Ronny Trommer <ronny@no42.org>
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