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 WebAssembly (wasm) target for scsynth #5309

Closed
wants to merge 44 commits into from

Conversation

Sciss
Copy link
Contributor

@Sciss Sciss commented Jan 1, 2021

Purpose and Motivation

fixes #5224

Types of changes

  • Documentation
  • Bug fix
  • New feature

To-do list

  • Code is tested
  • All tests are passing
  • Updated documentation
  • This PR is ready for review

- introduce a hypothetical new audio api 'openal'
- some EMSCRIPTEN conditionals
- ignore missing boost pthreads for now

The cmake command for now is:

    $ emcmake cmake -DSC_WII=no -DSC_EL=no -DSUPERNOVA=no -DSC_HIDAPI=no -DNO_LIBSNDFILE=yes -DSC_QT=no -DNO_AVAHI=yes -DSC_ABLETON_LINK=no -DCMAKE_BUILD_TYPE="Release" -Wno-dev -s USE_PTHREADS=1 -DPTHREADS_LIBRARY=ignore --target scsynth ..
- until the missing audio API is detected
- add some more preprocessor conditionals
- now we get an initial list of undefined symbols
  (mostly: initialization of audio API, some pthread, some file system)
- we have unstaged commits in `external_libraries/nova-tt`; thus
  next step will be to commit them in a fork of nova-tt
- use nova-tt fork (branch wasm)
- I ran `update --remote`; was this a good idea?
- seems we had flags on emcmake that were never passed to emcc
- we have a strange linker error regarding shared memory
- now with shared memory actually enabled, we cannot run in Firefox
  without user adjustments
- in Chromium, there is an error enumerating audio/video devices
- some problem now in boost

    at boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>::priv_add_segment(void*, unsigned long) (http://0.0.0.0:8000/scsynth.wasm:wasm-function[4452]:0xceebe)

This may be a problem due to assuming _no_ shared memory in previous
preprocessor tuning; perhaps we need to remove those diversions again
```
abort @ scsynth.js:1475
___assert_fail @ scsynth.js:2082
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>::priv_add_segment(void*, unsigned long) @ scsynth.wasm:1
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>::rbtree_best_fit(unsigned long, unsigned long) @ scsynth.wasm:1
boost::interprocess::segment_manager_base<boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul> >::segment_manager_base(unsigned long, unsigned long) @ scsynth.wasm:1
boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::segment_manager(unsigned long) @ scsynth.wasm:1
boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul>::create_impl(void*, unsigned long) @ scsynth.wasm:1
boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> >::operator()(void*, unsigned long, bool) const @ scsynth.wasm:1
void boost::interprocess::ipcdetail::managed_open_or_create_impl<boost::interprocess::shared_memory_object, 16ul, true, false>::priv_open_or_create<boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > >(boost::interprocess::ipcdetail::create_enum_t, char const* const&, unsigned long, boost::interprocess::mode_t, void const*, boost::interprocess::permissions const&, boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> >) @ scsynth.wasm:1
boost::interprocess::ipcdetail::managed_open_or_create_impl<boost::interprocess::shared_memory_object, 16ul, true, false>::managed_open_or_create_impl<boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > >(boost::interprocess::open_or_create_t, char const* const&, unsigned long, boost::interprocess::mode_t, void const*, boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > const&, boost::interprocess::permissions const&) @ scsynth.wasm:1
boost::interprocess::basic_managed_shared_memory<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::basic_managed_shared_memory(boost::interprocess::open_or_create_t, char const*, unsigned long, void const*, boost::interprocess::permissions const&) @ scsynth.wasm:1
detail_server_shm::server_shared_memory_creator::server_shared_memory_creator(unsigned int, unsigned int) @ scsynth.wasm:1
World_New @ scsynth.wasm:1
```
- somehow it hangs if we call `EventLoop::run([world]() { World_WaitForQuit(world, true); });`
  so skip that for now
- add a 'boot' button so we don't run into the problem of
  having an AudioContext that doesn't start
- so all pieces are in place, OSC messages seem to be correctly encoded
- audio driver start/stop now in place
- but we get these errors:

Uncaught TypeError: Failed to execute 'copyToChannel' on 'AudioBuffer': The provided ArrayBufferView value must not be shared.
    at ScriptProcessorNode.ad.proc.onaudioprocess (scsynth.js:1688)
ad.proc.onaudioprocess @ scsynth.js:1688

It seems that because of `-pthread`, the HEAP is now backed by
`SharedArrayBuffer`, and that in turn cannot be used in `copyToChannel`.

Hopefully, we can just make one additional copy. If not, we're f*cked
:-O
- for example, trying to d_recv analog-bubbles,
  the first UGen encountered, 'Control' is apparently not
  installed
- probably we need to include some binary file for the
  emscripten virtual file system
- DiskIO is disabled because we currently don't build with libsndfile
  (perhaps it's possible -- I don't remember why I had to disable it)
- we need to understand how to allocate (and free) the
  memory for OSC replies. is web_reply_func called from
  different threads? Can we just use malloc, or should we
  use rt memory?
- noticed a bug in `NumOutputBuses`
- extraneous constructor argument `int inNumSamples` was causing crashes
- wasm/configure.sh : use release build type
  (we're still catching exceptions, though)
- probably the originally missing symbols were due to
  wrong pthread linker settings
- go back to timblechmann's repo
- seems the assertion in rbtree_best_fit.hpp
  does hold now
- build file seems ok for now
- Module.oscDriver is now a dictionary from
  virtual port number to an object that at least
  defines the property `receive`, a function taking
  two arguments: sender's port, and Uint8Array raw OSC packet.
@dyfer
Copy link
Member

dyfer commented Jan 4, 2021

Thank you for this, @Sciss !
I don't have the expertise to do a full review, but I've noticed that submodule updates are part of this PR. Is this intentional? If not, then they should probably be reverted. Feel free to submit a separate PR for submodule updates, if desired.

@Sciss
Copy link
Contributor Author

Sciss commented Jan 4, 2021

Not an expert with git submodules: I ran init and update a few times. How would I revert them? And to what commit?

@dyfer
Copy link
Member

dyfer commented Jan 4, 2021

I'm not an expert either...
I think that in order to check which commit they are at on the develop branch, you could switch to that branch, then go to each affected submodule directory, and use git status to check and take note of commit SHA. Then switch back to your PR branch, go to submodule directory again and checkout that commit...
Alternatively you can try deleting submodules and then run update --init --recursive but that sometimes messes things up... see #5306 (comment) (and the rest of that issue, especially if you switched remotes on your submodules)

- needed to do anything more involving like allocating larger buffers
@dyfer
Copy link
Member

dyfer commented Sep 20, 2021

Should this be closed in favor of #5571 ?

@dylans
Copy link

dylans commented Sep 21, 2021

Should this be closed in favor of #5571 ?

Probably, I retained the full commit history from @Sciss , but didn’t have an easy path to merge the updates back into this PR.

@dyfer
Copy link
Member

dyfer commented Jan 19, 2022

Hello @Sciss
Are you interested in continuing work on this PR?

@Sciss
Copy link
Contributor Author

Sciss commented Jan 19, 2022

Definitely interested; I mean I'm using scsynth.wasm. I don't have time resources at the moment, though, so it'll have to wait a bit. I'm happy to comment on questions.

@dyfer
Copy link
Member

dyfer commented Jan 19, 2022

Thanks, got it. Should we close this PR and move the discussion to #5571 (which has all your commits rebased and with resolved conflicts, AFAIU) or should we close that one and keep the discussion here? Just trying to tidy things up a bit.

@Sciss
Copy link
Contributor Author

Sciss commented Jan 19, 2022

Yes, makes sense, thank you

@Sciss Sciss closed this Jan 19, 2022
@dyfer
Copy link
Member

dyfer commented Jan 19, 2022

(continue conversation in #5571)

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.

[servers] porting audio servers for Emscripten/WebAssembly
3 participants