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

Add support for Web Audio (Emscripten/WebAssembly) #887

Draft
wants to merge 32 commits into
base: master
Choose a base branch
from

Conversation

fwcd
Copy link

@fwcd fwcd commented Mar 5, 2024

Fixes #497

This is a work-in-progress, from-scratch implementation of a Web Audio hostapi, using the Wasm Audio Worklets API, which Emscripten already provides nice C/C++ wrappers for.

Useful resources

fwcd added a commit to fwcd/m1xxx that referenced this pull request Mar 6, 2024
These didn't really work as-is (since they required special support on
the JS side) and should be rewritten for the new Wasm Audio Worklets API
as per PortAudio/portaudio#887
@RossBencina
Copy link
Collaborator

RossBencina commented Mar 8, 2024

Cool. Great that you're working on this. We look forward to merging it when its ready.

Please give a status update from time to time and let us know when you're ready for a code review. Ideally we'd like to hear from multiple users who are successfully using this host API.

Copy link
Collaborator

@philburk philburk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for adding this new webaudio hostapi. This is very exciting technology. I love writing host-independent code and webasm and webaudio makes the web a compelling platform. I may try to integrate this with multi-platform kotlin/compose.

Please add a YAML target for continuous integration.

We will review this in more detail when you tell us it is ready.

src/hostapi/webaudio/README.txt Outdated Show resolved Hide resolved
@fwcd
Copy link
Author

fwcd commented Mar 10, 2024

When building with -Werror I get

portaudio/src/common/pa_converters.c:344:32: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-const-int-float-conversion]
  344 |         double scaled = *src * 0x7FFFFFFF;
      |                              ~ ^~~~~~~~~~
portaudio/src/common/pa_converters.c:389:32: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-const-int-float-conversion]
  389 |         double scaled = *src * 0x7FFFFFFF;
      |                              ~ ^~~~~~~~~~
portaudio/src/common/pa_converters.c:508:32: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-const-int-float-conversion]
  508 |         double scaled = *src * 0x7FFFFFFF;
      |                              ~ ^~~~~~~~~~
3 errors generated.

Any ideas? At first glance this looks like an issue outside this PR's scope. Perhaps something funky happens because we are compiling for a 32-bit platform (wasm32)?

@fwcd
Copy link
Author

fwcd commented Mar 10, 2024

Status update: There is audio! It currently only supports the default 2-channel output device, but paex_sine and paex_saw already sound like sine/saw waves.

It would be really cool if we could get rid of -sASYNCIFY to avoid imposing this mode on downstream consumers, but that seems to be nontrivial, unfortunately: emscripten-core/emscripten#18853 (comment)

This synchronous mode uses `emscripten_thread_sleep` instead of
`emscripten_sleep` and is intended to run from a separate thread where
blocking is allowed.

In its current state, this seems to depend on

    WebAudio/web-audio-api#2423

The alternative would be to proxy audio context-related calls to the
main thread.
@fwcd
Copy link
Author

fwcd commented Mar 11, 2024

I've added some highly experimental support for building without -sASYNCIFY via the PA_WEBAUDIO_ASYNCIFY flag (which still defaults to on). It mainly replaces the sleep implementation with a blocking emscripten_thread_sleep and avoids awaiting any audio context-related calls. We'll have to be extra careful to not block the main thread in that case and PortAudio would have to be invoked from a worker thread. However, for the audio context-related methods to be available from a worker, it looks like we will have to wait for

This is also why the examples, even with -sPROXY_TO_THREAD currently don't run when PA_WEBAUDIO_ASYNCIFY is off. We could manually proxy everything audio context-related to the main thread, but I haven't had time to look into how hard that would be to implement (and how to avoid potential deadlocks).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P4 Priority: Low
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Is portaudio convertible to webassembly ?
3 participants