WASM SYNTH, or, how music taught me the beauty of math
timdaub.github.io
timdaub.github.io
Synth: http://www.errozero.co.uk/stuff/poly/ Source: https://github.com/errozero/poly-synth
Works best in chrome
Otherwise it's a nifty little toy, thanks for sharing :) Lots of fun.
After a good bit of trial and error, I came up with a setup that works well on all platforms I could test: https://github.com/Ameobea/web-synth/blob/master/src/index.h...
https://web-audio-midi.herokuapp.com/
Adding a keyboard, scale selection, oscilloscope, score note viewer, sound font player, bluetooth/web midi controller detection, etc :)
Did you decide on a license for your synth code?
https://sourceforge.net/p/vmpk/shared-keymaps-and-instrument...
Since it looks like we're all sharing our web-based synthesizers, here's a FM synthesizer I built with Rust + Wasm with SIMD earlier this year: https://notes.ameo.design/fm.html
Blog post: https://notes.ameo.design/blog/fm-synth-rust-wasm-simd/
I figured what I was working on was pretty niche; it's cool to see so many other people experimenting in this space too
(Also since I’m writing something already, you’re serving your site on both HTTP and HTTPS and only some URLs are doing the appropriate 301 HTTP → HTTPS redirect, presumably because it’s being done at the Wordpress/PHP level, so any direct file references handled directly by Apache don’t get done. You should make it do all URLs, and ideally add an HSTS header.)
You can also use setPeriodicWave() to have it iterate over any sampled waveform you like. There is enough in the JavaScript API to fool around with basic subtractive synthesis where you connect an oscillator to a filter.
I also recommend Syntorial [2] for understanding what subtractive synthesis is capable of. It won’t help you synthesize real instruments, but you learn what the various knobs on synthesizers do by trying to reproduce increasingly sophisticated synthesizer sounds.
Learning the basic math is useful too though.
[1] https://developer.mozilla.org/en-US/docs/Web/API/OscillatorN... [2] https://www.syntorial.com/
One problem I've had in the past trying to do audio on the web is I struggled to find any reference material on how to generate my own waveforms and rely on the browser APIs only for playback. This tutorial, with the AudioWorklet, is the first piece I've seen on how to easily do this.
If it's a static waveform, you could also do a Fast Fourier Transform and hard-code the resulting table into your program as a Periodic Wave. Apparently, this is how the prefined waveforms of OscillatorNode work. [2]
Generally speaking, you need to read about all the different kinds of nodes that WebAudio gives you and wire them together, sort of like you would with a modular synthesizer. For experimenting with audio synthesis, I'd recommend trying out Rack [3] to figure out what kinds of sounds you want to make, then coding it in JavaScript if you can find equivalent nodes. (Rack is going to have much more capable modules, though.)
[1] https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer... [2] https://webaudio.github.io/web-audio-api/#oscillator-coeffic... [3] https://vcvrack.com/
Never underestimate Safari. Its support of WebAudio is pathetic.
It, however, never ended up sounding quite as good as my brothers's simple 300€ Yamaha keyboard.
Even after having trained my ears for many months, I still don't know why the piano sounds from my speakers just weren't as pleasing as what by bro's Yamaha produced.
Pianoteq generates the sounds using nothing but a bit of software and it is really most impressive.
I suspect it's the latter, because there's a hint of detail missing in the way the overtones move.
[1] https://en.wikipedia.org/wiki/Pianoteq
[2] https://www.modartt.com/modartt
[3] https://hal.inria.fr/file/index/docid/768234/filename/RR-818...
The other thing that affects your experience, and that doesn't have anything to do with timbre, is latency. Ableton through a USB audio interface into monitors is going to take (much) longer than the onboard sound generation + speakers on a digital piano. It's going to add at least 20ms plus whatever time is required to compute the sound. Meanwhile any cheap digital piano is going to do better than that.
Software instruments are usually about as quick as you'd ever need them to be (no latency). So just make sure your audio buffer is set low (32 - 128 samples) and that you're not doing any heavy DSP processing that's going to add extra latency.
It takes some vigilance to do and it can be a pain in the ass to manage when you're trying to play the instrument in a CPU intensive session, but if you do it right you'll only get latency at the output stage (3ms).
Unfortunately it is not possible to link to the examples page directly. To see what I mean, click on the Fine details of sound tab here: https://www.modartt.com/pianoteq#acoustic
I really wish there were more open source physical modeling synths out there. I'd love to play with physical modeling code, but it's just not that common.
non-footnote version: https://timdaub.github.io/2020/02/19/wasm-synth/
If you encounter an operator, where the corresponding command with \ does not exist, you can create it with
\DeclareMathOperator{\operator}{operator}requestAnimationFrame does make those timing guarantees.
A great programming exercise that forces you to wrap your head around JavaScript timing events is writing a small step sequencer that can be used while it is running with minimal latency.
It turns out that this is currently true [0] because the base audio context (BAC) time is accurate to within 20us whereas RAF is accurate to within 1ms [1]. However in future browser versions the default sensitivity for BAC is going to drop to 2ms. This is done to help improve user privacy by hampering browser fingerprinting.
This is all configurable and its materiality depends on use case, but interesting read: thank you.
[0] https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioCo...
[1] https://developer.mozilla.org/en-US/docs/Web/API/window/requ...
From https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWor...
- Nested timeouts
> As specified in the HTML standard, browsers will enforce a minimum timeout of 4 milliseconds once a nested call to setTimeout has been scheduled 5 times.
- Timeouts in inactive tabs
> To reduce the load (and associated battery usage) from background tabs, browsers will enforce a minimum timeout delay in inactive tabs. It may also be waived if a page is playing sound using a Web Audio API AudioContext.
> The specifics of this are browser-dependent.
- Throttling of tracking scripts
> Firefox enforces additional throttling for scripts that it recognises as tracking scripts. When running in the foreground, the throttling minimum delay is still 4ms. In background tabs, however, the throttling minimum delay is 10,000 ms, or 10 seconds..
- Late timeouts
> The timeout can also fire later than expected if the page (or the OS/browser) is busy with other tasks.
- Deferral of timeouts during pageload
> Firefox will defer firing setTimeout() timers while the current tab is loading.
It may be that I assumed emscripten to use gcc but since its been over a year I wrote about it, I'm not sure anymore and so I default to trusting what I wrote. Happy to change with a source.
> To see the full list of Clang options supported on the version of Clang used by Emscripten, run clang --help.
Could probably find a more authoritative statement but just a quick search.
EDIT: I don't think it was intended to refer to the footnote, because the title of the discussion refers to the title of the page itself.