Cowbell - a universal web audio widget for scene music
category: code [glöplog]
I made a thing.
It's a widget for playing a whole load of different music formats in the browser, namely:
* MP3, OGG and anything else your browser supports natively
* MOD, S3M, XM, IT and anything else libopenmpt can handle
* ZX Spectrum STC and PT3 tracker files
* PSG and VTX (from the Spectrum or anything else with an AY chip)
...and hopefully in future, SID, SNDH and anything else that's ever served as a music distribution format in the scene's illustrious lifetime.
The motivation for this is that there's a whole lot of JS code floating around for playing different scenish music formats (see: chiptune2.js, jsSID...) but since no-one's standardised these things, they all have their own APIs and frontends. So I decided to come up with a common API for all of them. And then I remembered that that's a stupid idea, and stole the one for the HTML <audio> element instead.
So, the idea is, someone can easily hack up a player frontend that calls (a subset of) the HTML <audio> API, and it will work against all of these backend engines. And conversely, if someone codes up a JS player routine for a new music format that works on the time-honoured "shove some audio wave data into a buffer" principle, it can be dropped into Cowbell's handy wrapper code and made to work with any of those frontends.
The code is up on Github and has proper API docs and everything, so I'd like to invite audio / webby minded folks to have a play and contribute!
*KLONK* *KLONK* *KLONK*
It's a widget for playing a whole load of different music formats in the browser, namely:
* MP3, OGG and anything else your browser supports natively
* MOD, S3M, XM, IT and anything else libopenmpt can handle
* ZX Spectrum STC and PT3 tracker files
* PSG and VTX (from the Spectrum or anything else with an AY chip)
...and hopefully in future, SID, SNDH and anything else that's ever served as a music distribution format in the scene's illustrious lifetime.
The motivation for this is that there's a whole lot of JS code floating around for playing different scenish music formats (see: chiptune2.js, jsSID...) but since no-one's standardised these things, they all have their own APIs and frontends. So I decided to come up with a common API for all of them. And then I remembered that that's a stupid idea, and stole the one for the HTML <audio> element instead.
So, the idea is, someone can easily hack up a player frontend that calls (a subset of) the HTML <audio> API, and it will work against all of these backend engines. And conversely, if someone codes up a JS player routine for a new music format that works on the time-honoured "shove some audio wave data into a buffer" principle, it can be dropped into Cowbell's handy wrapper code and made to work with any of those frontends.
The code is up on Github and has proper API docs and everything, so I'd like to invite audio / webby minded folks to have a play and contribute!
*KLONK* *KLONK* *KLONK*
Maybe scene.org/demozoo can include it to play the music files of the compos directly.
Good work!
1.3MB zipped :D
w00t!
gasman for president!
gasman for president!
Screams for PM integration. Will have a look at some point :)
Gargaj: I guess Emscripten for libopenmpt? But yes, quite cool.
Nice!
Excellent work! :D
(never mind, you've already seen that :P)
Quote:
Maybe scene.org/demozoo can include it to play the music files of the compos directly.
Yep, adding that feature to Demozoo is the not-so-secret ulterior motive behind this project :-)
Quote:
Gargaj: I guess Emscripten for libopenmpt?
Yep. The bloatiness of Emscripten annoys me too (enough to push me to start writing my own alternative C-to-JS compiler in fact... but at that point we're basically into expert-level yak shaving). I've tried to mitigate that here by implementing lazy loading (so you're not loading the player + module on every single page load regardless of whether the user clicks on it) and splitting the backend modules into their own scripts (so you don't have to import it at all if you're only interested in playing AY / SID or whatever). There's also nothing to stop us from adding a more lightweight mod player backend - Micromod / IBXM.js is one that's been suggested - as an alternative for when you don't need the uber-accuracy and format support of libopenmpt.
In fact I wanted to do that when I will update chiptune.com (the code is so old), so I will probably use what gasman did :)
Nice! :)
A compressed libopenmpt.js (using gzip) usually yields about 650KB. I know Gargaj brought this up before that it's "too big", but consider that a native version won't be much smaller - it supports about 30 module formats (two more in the next version), and it supports them well (e.g. all kinds of quirks are supported on a per-format basis). If you really want a "universal web audio widget", you are already aiming at something that has the functionality of what is normally considered a desktop application, and I think that entirely justifies that it has the same size as a desktop application. I hate bloated websites but at this time it's not really a classic website anymore but rather a fully-fledged application.
gasman: i've been using micromod on files.scene.org and have been quite happy with it's size footprint; websites are too big already, and I'd much rather not have a site where the JS library exceeds the size of the module it's trying to play.
Saga: do you think it's possible to split the library into small pieces, each only capable of replaying a specific format? That way people could only load that specific part needed to play a desired format.
Gargaj: Sure, website are huge these days but they also do a bunch of stuff that they couldn't do some years ago. I still think that, for the sake of functionality, it's an ok tradeoff. Especially since all scripts are cached once they've been loaded once.
Gargaj: Sure, website are huge these days but they also do a bunch of stuff that they couldn't do some years ago. I still think that, for the sake of functionality, it's an ok tradeoff. Especially since all scripts are cached once they've been loaded once.
D.Fox: It doesn't really help. With that you'd have to download 30 300-400KB-sized chunks instead of of one 600kb-sized chunk. The reason is that a lot of the code is common between all formats and I certainly won't split up the module renderer into 30 things that consist of mostly duplicate code because someone on the internet thinks that downloading a 600kb script once is asking for too much. As soon as you play two files of different formats, you already lost the game.
Ok, schade. I've seen some js libraries who use a "common" part of a library though, which is quite big in size and then load tiny bits of modules as needed. I guess that won't really make much of a difference here either.
In any case, this project is very promising and I'm looking forward to integrating this into PM in the future to listen to competition entries.
If we're all worried about size and traffic, including 1MB of scripts and then only loading small modules is still a lot less traffic than streaming all music compo entries as mp3s :)
In any case, this project is very promising and I'm looking forward to integrating this into PM in the future to listen to competition entries.
If we're all worried about size and traffic, including 1MB of scripts and then only loading small modules is still a lot less traffic than streaming all music compo entries as mp3s :)
gargaj: there are some js libs to unzip in memory, might be worth extending the player on scene.org to also look inside zips and if there is a recognizable module extract on the client browser and play that.
I remember looking into that, but I mostly kept coming up with logical problems, like how to decide if an archive that contains an image and a module should preview the image, the module, or both; in the latter case, some archives for demos would end up as texture galleries and so on. All the solutions I thought about ended up being extremely arbitrary.
Clearly what we need is a metadata spec for demos. With XML. Lots of XML. :-P
(Granted, for the particular case of scene.org, everything is already sorted by type, so you can just look at the directory name.)
gargaj: go through list of files in the zip, dynamic add preview button for each previewable file format found and people can choose which to click to preview?
So if someone wants to preview the screenshot from a 100MB demo, first they unknowingly download the entire archive? :)