Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebAudio Worklets are Broken Demo (constructor horribly stalls the audio thread) #2269

Closed
carlsmith opened this issue Oct 30, 2020 · 4 comments

Comments

@carlsmith
Copy link

carlsmith commented Oct 30, 2020

I opened an issue already, but it was closed on the assumption that I implemented the same bug half a dozen different ways :(

The API literally has no way of directly passing a track from the main thread to the audio thread, without stalling it horribly.

I've tried chopping the data up, and using setTimeout to sync the threads incrementally (using the port to communicate), but this caused the audio thread to stutter. I tried many different block sizes and timings already, but even if I get it working, it's always going to be relatively slow, as any developer has to prioritize the audio thread, and has no way of knowing how fast they can push data to it. It's basically a hack. The API should have an efficient way to transfer audio data to an audio processor.

@carlsmith carlsmith added Needs Discussion The issue needs more discussion before it can be fixed. Untriaged labels Oct 30, 2020
@carlsmith carlsmith reopened this Nov 2, 2020
@rtoy rtoy removed Needs Discussion The issue needs more discussion before it can be fixed. Untriaged labels Nov 5, 2020
@padenot
Copy link
Member

padenot commented Nov 5, 2020

What you're looking for is postMessage transfer list to be able to transfer a buffer to another thread. This has been available since around 2011, and has nothing to do with AudioWorklet. https://developer.mozilla.org/en-US/docs/Web/API/Transferable has more info.

This is essentially sending a pointer to the data to another thread, so to speak: here to the audio real-time thread, but it's the same for workers (any type of worker).

https://paul.cx/public/transfer.html shows the basics of operations. A button to start the context, a button that sends a new 100MB array with values going to 1 to 104857600. You can mash the second button and it doesn't glitch (modulo browser bugs as usual, that should be filed in the respective browser bug tracker).

A bug in Firefox prevents this from working as it should (but will be fixed). If you need this today, here is a variant of the page above https://paul.cx/public/transfer3.html, that is using a SharedArrayBuffer, not to share data between threads, but to sidestep this bug.

@carlsmith
Copy link
Author

carlsmith commented Nov 6, 2020

https://paul.cx/public/transfer.html shows the basics of operations. A button to start the context, a button that sends a new 100MB array with values going to 1 to 104857600.

@padenot - It glitches about 50% of the time on my machine (assuming I don't mash on it). I know my laptop's specs are not particularly impressive, but I have no issues with other audio software.

@rtoy
Copy link
Member

rtoy commented Nov 6, 2020

I can confirm that @padenot's demo does glitch on Chrome 87 (mac OS). However, when I visit chrome://flags and search for "realtime" and enable "Use realtime priority thread...", the glitch goes away. If I press the "send 100 MB" button constantly, then I do hear an occasional glitch.

I think Chrome will switch to realtime priority by default soon.

@carlsmith
Copy link
Author

Thanks for looking into this, @rtoy.

Even with realtime threads enabled, I still get occasional glitches on my machine, and the demo only sends 100MB. That's fine for my application, but the API does not limit postMessage to 100MB. Ideally, you'd at least be able to pass a Wasm memory, which is currently up to 4GB.

The API effectively overloads postMessage so it has two responsibilities: It has to handle small messages (with low latency), and huge arrays (without blocking the audio thread).

I guess it's possible to use some heuristic under the hood to pick an algorithm, based on the size and shape of the argument (to postMessage), but I don't understand things well enough to comment on the practicalities of doing that. Alternatively, the API could just define separate methods (something like postMessage and syncMessage).

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

No branches or pull requests

3 participants