4'33" (as performed by your browser)
I made a thing!
Well, actually, several smaller things. Performers. Music players!
4'33" (as performed by your browser) can play John Cage's 4'33", using different Web APIs and ways of combining them.
For example, one uses "nothing", other uses a Web Audio AudioContext, other uses OfflineAudioContext, other generates WAV files and then can play them with an <audio> element, etc.
It has only taken me around 10 years to build this (from the time I had the idea to actually shipping).
But then it came out quite neatly. I'm very happy that my mental hierarchy corresponded neatly to a buildable class hierachy. This helped me minimise the amount of code I wrote for each player. That sounds to me like a good design (patting myself on the back, yes!).
Slightly following from that, I'm also quite pleased that it's so SMALL. The whole deployment comes out as... 18 Kb. Yes. It's not even 20 Kb. Yay! And in fact even a smaller amount of data will be transmitted over the wire as my server compresses the data before sending it to clients. I wasn't planning to build a small thing, but I appreciate the fact.
Another interesting aspect was figuring out a good answer for how to make sure that it really is playing, when you're "playing silence", i.e. zeros. For example, how do I know for sure that the node for my AudioWorklet is properly connected and doing the right thing, when I can't "technically" hear it? That's why I ended up adding a "debug" mode so that players could add some artificial debugging noise to the output signal when the setting was on. This, in turn, made me figure out how to pass configuration parameters to the players. Easy when you're running normal code, but it required a little bit more figuring out when it came to the AudioWorklet (that's why I wrote a post to shed light on using and configuring AudioWorklets).
For the WAV generation I used the same code I keep using since 2012... although it is unfortunately only capable of generating mono sound. I looked into how to extend the code so it would generate stereo but I saw that there are other modules that did that, but since for the purposes of this project mono was sufficient, I have left it as is for now. Separately, I wonder if WAV generation won't be better done some other way (maybe with Web Codecs?), but it's not like it's keeping me awake at night.
I have written some more notes including the list of players and which one extends which and it's all in the project page, so if you're curious about it, you know where to go.
Happy listening (or reading)!