Skip to content

Transpose does not work for network clients, and could via a ScriptProcessorNode fallback #558

Description

@thcp

The limit

The pitch stage is an AudioWorklet, which browsers expose only on a secure context. https:// and localhost qualify. A plain http://192.168.x.x does not, so a client opening a networked StemDeck is never given the API and the SoundTouch stage cannot be built at all.

Measured in Chromium against the same page served three ways:

http://127.0.0.1:8777/     secureContext=true   audioWorklet=true
http://localhost:8777/     secureContext=true   audioWorklet=true
http://192.168.1.14:8777/  secureContext=false  audioWorklet=false

Reported as #552. That issue covers the messaging, which was wrong, and is fixed separately. This one is the capability.

There is a way

createScriptProcessor is not secure-context gated. Same probe, same insecure origin:

http://192.168.1.14:8778/  secure=false  worklet=false  scriptProcessor=true

So a ScriptProcessorNode path would make transpose work over a plain LAN IP with no certificate, no new dependency, and nothing for the user to configure.

What it costs

Three things make this a project rather than a patch.

It has to reimplement the whole worklet, not just the pitch part. The worklet also owns tempo, through stNode.parameters.get('tempo'). Without it, speed resamples the sources, which already moves the key. Adding a pitch shifter on top of that stacks two shifts and the result is incoherent. So the fallback needs both.

The graph shape does not port. The worklet is built with 13 inputs, one per semitone, because a lane's transpose is a connection rather than a parameter. ScriptProcessorNode has exactly one input. The workable design is probably one processor per distinct semitone actually in use, usually one, which is a second pitch architecture rather than a port of the first.

It runs on the main thread. StemDeck redraws waveforms, VU meters and the playhead continuously. Audio dropouts under UI load are the likely failure, on exactly the machine this is meant to help, which is already a remote client on a LAN.

There is also a hint in the tree worth knowing before starting: static/vendor/soundtouch-processor.js redefines PITCH_MIN_SEMITONES and PITCH_MAX_SEMITONES locally rather than importing them from pitchBus.js, even though that module exists to stop the mapping being written twice. Someone chose duplication over a worklet import. Extracting a shared DSP core may run into whatever reason that was.

Suggested first step

Prototype before building. One question decides it: does main-thread audio hold up while the waveform is redrawing? Everything else follows. An afternoon spent answering that is cheaper than a week spent discovering it.

Not in scope

Serving HTTPS. It needs a certificate, generating one needs cryptography, and adding that changes uv.lock, which sends every existing desktop install to a full re-download instead of an in-app update.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions