Did some poking around with SuperSonic (Sam Aaron's supercollider to wasm fork). I couldn't get shadow-cljs to load it from node_modules, but if you simply download the zip and unpack it, you can do something like this:
(ns net.arnebrasseur.lab
(:require
[kitchen-async.promise :as p]))
(def supersonic (atom nil))
(p/let [^js ss (js* "import('/supersonic/supersonic.js')")
SuperSonic (.-SuperSonic ss)]
(reset! supersonic (SuperSonic.))
(.addEventListener
(js/document.querySelector "button") "click"
#(p/do
;; Must be called from some kind of user interaction like a click event
(.init ^js @supersonic)
(.loadSynthDefs ^js @supersonic #js ["sonic-pi-prophet"]))))
(comment
(.send @supersonic
"/s_new", "sonic-pi-prophet", -1, 0, 0, "note", 28, "release", 8, "cutoff", 70))
yeah, it just bundles a bunch of scsynth files and loads them via http. You can drop your own compiled synths in there just the same.
I did find that this js* import trick didn't work with advanced compilation with shadow-cljs, but you can use :target :esm, and then (:require [shadow.esm :refer [dynamic-import]]) and (dynamic-import "/supersonic/supersonic.js")
I do want to poke at supersonic a bit, it uses import.meta.url, which prevents shadow/closure from transpiling it, I think it may not be necessary and with small tweaks we could load it like a regular js library that gets included in the build. The wasm would still be loaded separately
That’s all awesome! Thanks a lot for spending time with this!
this opens the door to a clojurescript version (subset?) of overtone... gonna be a boatload of work to make all of that code portable. I guess one would start with the synthdef (de)serialization logic and build up from there.
wow, nice work figuring this out! is it clear how to load other synthdefs (i.e. from compiled files)?
im toying with strudel atm, its very convenint. having the same for overtone would be awesome!