"sQuinth", an oscillator using wasm modules written in a variety of programming languages. Also connects directly to Twitch.

3 Likes

Cool!

1 Like

I’m not sure I fully comprehend what is going on here, but if my partial understanding is correct, this would allow developers to write (at least portions of) VCV Rack modules in any language in which Extism plugins can be written. is that right?

I would imagine that WASM is fast enough for DSP…

I would love to see a step by step tutorial on this.

2 Likes

The problem with using other languages is how to make it so that VCV can build and distribute such plugins for the library. You’d probably have to vendor your entire toolchain into your project, if VCV were willing to support that. No idea how you install a WASM execution environment for all Rack’s supported platforms (sQuinth is Linux only ATM). You really don’t want to be carrying a copy for each Rack plugin.

Native code will always have an advantage over any VM like WASM. But yeah, WASM would often be fast enough. People even do audio stuff in interpreted javascript. Targeting WASM would let you run that code in the browser.

1 Like

Right, I was thinking of doing this for personal projects, not necessarily for distribution with the library.

It also occurred to me that even if WASM is itself fast enough for DSP, what about the overhead of calling a WASM plugin from C++ 48k times per second?

1 Like

I don’t blame you for the confusion, it was a very ambitious and strange project that wasn’t able to fully come to fruition due to other factors.

Wasm is fast enough for DSP… with some tricks that will limit what you can do. I keep a separate buffer of maybe a thousand samples in the module and calculate those ahead of time, in a fully-wasm loop. This unfortunately meant writing a loop in every language that is supported, but could maybe be done by writing one wasm module that runs the loop and connecting it to another wasm module that has the compiled DSP code. Although, keeping the loop as part of the plugin allows you to use that buffer for effects that reference samples before/after the current.

There is some information in the repo about making plugins, but there are likely some spots that are not adequately explained.

2 Likes

My intuition is the same as yours - it doesn’t sound very efficient.

2 Likes

Yeah, slow when you need to fire up the wasm vm every time, but it does still function. When you precompute a few hundred each time, doing the whole loop in wasm, the overhead is pretty much non-existent as far as I can tell. It’s a bit limiting, but a fun experiment.

don’t you need to post message every sample?

I’m not sure what you mean by “post message”

post message is the API by which one can communicate with a JS worker. Oh, yes, I forgot, you can use a shared array buffer, too. Still, though, wouldn’t you need to post a message to tell the other worker that there was a sample ready?

1 Like

Ah I think I see what you are saying. I think you assume there is a separate wasm process that is communicating back and forth with the VCV plugin process. It works more like a normal function call where I hand over the pointer to the shared memory and the wasm process just returns when it is finished calculating the samples. Having a separate process would avoid those processing spikes every time that the buffer needs to be recomputed, but it wasn’t much of an issue in my case, so I did not bother doing that.

ah, I had assumed a wasm always made a separate worker and that you had the send stuff that way. But I guess you are saying that when you load a wasm module that it’s still running on your same worker, and hence you can pass stuff around just like in normal JS?

btw, a worker isn’t a separate “process”. I don’t know if it’s the correct lingo, but ppl I know say it’s a separate “isolate”, but usually in the same process. Although I guess they are more like a separated process. At least to those of us who are (old) c++ programmers. The difference, of course, is that in c++ you can easily share memory between two threads, in JS shared buffer array is the only way…

WASM is a bytecode virtual machine (like original Java, C#, et al). It can run independently from a browser in other hosts. All that JS interop and workers stuff is all about how WASM is hosted in a web btowser.

1 Like

Yes, exactly… Webassembly is an unfortunate name. In this case the c++ rack plugin acts as the host and passes info back and forth through byte arrays.

Sure. But where is it actually hosted today? Browsers and v8, I’m guessing?

Microsoft flight sim used it for plane dashboard logic in 3rd party plugins, but I think they just transpiled the wasm to a c binary for each platform rather than ship it with a wasm runtime

1 Like

The history of cross-platform UI for third party plugins is a sad story!

1 Like

Cross-platform ui full stop, is a sad story, plugins or not. (looking for the best route for my next project (non-Rack), and I don’t think I want JUCE).

1 Like