Some time ago, I came across Sonant, which is a very specialized tracker. Its main purpose is to create songs that can be used in tiny demos, where the size of the song data plus the player software must not exceed a couple of kilobytes (for comparison, an MP3 file is usually several megabytes).

For various reasons, I decided to make a JavaScript port of Sonant, and the result is:

Feel free to try it out!

The “Why?”

Why make a synth tracker in JavaScript? The top reasons were probably:

I already had the synth implemented – so the editor was the next natural step.

I wanted a Linux port of the Sonant tool (which was originally a native Windows app). What better way to do it than in JavaScript?

Push the limits of current browser technology (i.e, can it be done?).

Note: There have already been some attempts at doing online trackers, for instance the Flash port of Skale Tracker (nice, but Flash) and apparently an HTML 5 synth (has anyone ever seen this live?).

The disclaimer

Just to be clear:

Sonant Live is still beta (functions are missing, the user interface is not optimal, and there are bugs).

It is a minimal synth that’s designed for production of music for minimal demos (i.e. do not expect to find a fully fledged omnipotent music studio).

The wish list

One of the goals of making this tool was to explore what can be done with current browser technologies. Throughout the work, I’ve come up with a few wishes for the future directions of browsers:

Low latency audio API – The current HTML audio element was not really designed for real-time interactive audio. In fact, it acts more like a subset of the video element, which in turn seems to primarily be a replacement for Flash video players (such as the one used on YouTube). With a proper audio API, such as OpenSL ES (WebSL, anyone?), interactive music and game apps would be much more compelling. For instance, the JavaScript synth in Sonant Live is fully capable of producing audio in real-time, so with a “real” audio API it would be possible to get instantaneous playback.

Better optimizing JIT compilers – As pointed out by Erik Möller in a blog post, you can get a great deal of performance gain by just eliminating property accesses and common sub expressions. In fact, I roughly got a 2x performance win (on all browsers) just by pre-loading common object properties and expressions in local variables. These are well known compiler optimizations that should not have to be performed by the programmer. Now, I realize that the situation is a bit more complicated for a dynamically typed language with setters/getters, but my point is that without those compiler optimizations, bad programming practices are actually encouraged.

Typed arrays – Life would just be so much simpler if high performance typed arrays were common place. For now, I had to resort to using the CanvasPixelArray trick, which gives me 8-bit arrays (while I’d like to use 16-bit arrays).

More flexible web workers – The message passing paradigm may be great and fail safe and all, but it really does not cut it for passing huge amounts of data between workers (in my case, I’d like to create the multi-megabyte audio data in a worker, and pass it to the UI thread). Shared objects would be much more efficient (read only or mutex locked, etc).

Better URL handling – I suspect that in most browsers, the internal URL handling is optimized for URL:s that are at most a few hundred characters long. For short URL:s, keeping a few duplicates around and traversing the string is cheap, but then a 50MB URL comes along… For instance, when I tried to export a WAV file from Sonant Live, Firefox 4 peaked at 1.6GB , Opera peaked at 2.8GB, and Chrome peaked at 1.1GB and puked (Chrome processes seem to have an upper memory limit of 1GB).

The future

The future is not to see… However, some things are obvious candidates for the future of Sonant Live.

First, the GUI is far from complete. For instance, there are some missing functions (copy/paste, undo, etc), and it would be nice to make the editor usable on mobile devices too (e.g. tablets). It would also be nice to make the tool more interactive (e.g. sound playback while pressing keys on the “piano” for easier instrument tuning).

Another area of improvement is the synth. As it is now, the synth is 100% compatible with the original Sonant tool, which I consider a feature rather than a bug. However, it is quite limited, and there are several simple improvements that can make the synth more powerful (even if minimalism is to be preserved). Some ideas that I have are:

Richer oscillators – e.g. up to 8 oscillators with different detune settings, which can give quite rich sounds (e.g. check out the Superwave P8 VSTi synth, which uses such tricks).

Better polyphony – supporting several note columns per channel would make it easier to do things like chords.

Effect commands – e.g. control instrument and effect parameters dynamically from the pattern.

Drums – Hmmm… Something should be done to spice up drum sound generation.

These changes would not make the song data noticeably larger (at least not if you compress/deflate it, which is the typical use case), nor would it make the player routine much more complicated.

Another area of improvement would be server-side storage of songs (they are usually less than 1KB compressed, so no problem with disk quotas), so that you can easily access all your songs from anywhere, and publish them for others to enjoy, etc.

The challenge

Feeling inspired? Since Sonant Live is quite minimalistic, it is a bit of a challenge to create good sounding music with it.

So, if you make your own cool song or groovy instrument, I’d like to hear it! Until I get some sort of song submission form up, you can post an URL to your song file in a comment to this post (I can grab it and delete the comment). If it’s good, I’ll include it in the song list on the front page.

19 Responses to Let’s make some music – online!

First, let me say that the project is extremely cool. If you had told someone five years ago that we’re going to compose music (or play Doom in a browser without plugins of any kind, they’d have laughed at you, and yet here we are …

Regarding your complaint about missing CSE optimization in JavaScript JIT compilers: The thing is, they can’t do CSE unless only local variables are involved. Repeated read access to global state and particularly to the DOM can’t be optimized out because in JavaScript, everything except local variables is mutable: Another concurrently running script might be changing stuff, or something in the DOM might change while your script runs.

I know that some compiler optimizations are harder in JavaScript than in C++, for instance, but far from impossible. In my opinion, it just requires a slightly bigger effort (in some cases it may not be worth the effort, though). Also remember: it’s a wish list – not a complaint list! 😉

I’m aware of the audio API:s in Mozilla and WebKit. However, my wish is for a cross-browser solution, and without a doubt it will come sooner or later (just as with typed arrays).

Nice project you got there! It got me quite interested in trying the original Sonant as well, but it seems the download is restricted and there is no working mirror to be found. Could you please e-mail me a copy of the software? Sorry to bother you, haha!

Here is the .snt if you want to include it in the list of examples: http://adinpsz.org/data/adinpsz_-_Fabrik.snt
(The 2 main constraints:
* 4 tracks (for the final filesize)
* fit the intro mood (not too “synthetic” sound)

Really nice track – you managed to squeeze out some nice instruments there (hope you don’t mind if I use some of them as presets in the future). I put up the song on the Sonant Live front page. I was actually already half-way through reverse-engineering the song data from the demo, but this was simpler 😉

Actually, I haven’t published the format (invented by Ferris/Youth Uprising) nor the code I use to parse it (in Sonant Live, it’s actually done in PHP). However, there is an untested JS-implementation here: http://sonantlive.bitsnbites.eu/tool/gui.js (see the binToSong() function) – that should point you in the right direction at least. I have some yet-to-be-published work in the pipe that will perhaps make things easier for you, any day now…