ringbuf.js
Version:
Wait-free thread-safe single-consumer single-producer ring buffer using SharedArrayBuffer.
110 lines (78 loc) • 4.2 kB
Markdown
# `ringbuf.js`
[](https://github.com/padenot/ringbuf.js/actions/workflows/test.yml)
[](https://www.npmjs.com/package/ringbuf.js)
A thread-safe wait-free single-consumer single-producer ring buffer for the web,
and some utilities.
The main files of this library:
- `src/ringbuf.ts`: base data structure, implementing the ring-buffer. This is
intentionally heavily commented.
- `src/audioqueue.ts`: wrapper for audio data streaming, without using
`postMessage`.
- `src/param.ts`: wrapper for parameter changes, allowing to send pairs of index
and value without using `postMessage`.
## Examples and use-cases
<https://ringbuf-js.netlify.app/> is a deployment of the examples in this
repository with a web server that answers with the right headers for this
directory, and allows the example to work. More details available at [Planned
changes to shared memory
](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned_changes).
Those examples work in browsers that support both the `AudioWorklet`, and
`SharedArrayBuffer`.
While most real-time audio work should happen on a real-time thread (which means
inside the `AudioWorkletGlobaleScope` on the Web), sending (resp. receiving) audio
to (from) a non-real-time thread is useful:
- Decoding a audio codecs that browsers don't support natively in a web worker,
sending the PCM to an `AudioWorklet` (no need to fiddle with
`AudioBufferSourceNode`, etc.)
- Conversely, recording the output of an `AudioContext` using an
`AudioWorkletNode` with a very high degree of reliability and extreme
flexibility, possibly using Web Codecs or a WASM based solution for the
encoding, and then sending the result to the network or storing it locally.
- Implementing emulators for (e.g.) old consoles that only had one execution
thread and did everything on the same CPU
- Porting code that is using a push-style audio API (`SDL_QueueAudio`) without
having to refactor everything.
- Implement off-main-thread off-real-time-thread audio analysis (streaming the
real-time audio data to a web worker, visualizing it using an
`OffscreenCanvas`, shielding the audio processing and visualization from main
thread load)
## Run locally
> `cd public; node ../server.mjs`
This is a simple web server that sets the right headers to use
`SharedArrayBuffer` (see [Planned changes to shared memory
](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned_changes)
on MDN).
## Contribute
Please do (just open an issue or send a PR).
> make build
allows running the build step and copying the file to allow the example to work.
> make doc
allows rebuilding the documentation.
## Performance Benchmarks
As of version `0.4.0`, the whole codebase has been ported to TypeScript, tooling
has been modernized and dependencies were updated. The package is now also
marked as side-effect free, which allows bundlers to tree-shake the code for
unused symbols when imported.
Alongside these updates, two performance optimizations were introduced:
- `_copy` has been optimized by a loop factor of 16.
[`bench`](bench/deinterleave-bench.html)
- `deinterleave` has been optimized by unrolling the loop with a factor of 4.
[`bench`](bench/copy-bench.html)
Early, and limited test results have shown a substantial performance improvement
in buffer copying by **~325%**. For ongoing monitoring in engine behaviour,
benchmarks have been added for independent verification of the results.
## Compatibility
This needs the `SharedArrayBuffer`, so a couple of HTTP headers might need to be
set on the web server serving the page.
```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```
As of 2023-05-25, the following browsers are compatible:
- Firefox Desktop all current versions including current ESR
- Firefox for Android all current versions
- Chrome Desktop and Chromium-based browsers (for a long time)
- Chrome for Android
- Safari
## License
Mozilla Public License 2.0