JSmin the good’ole JS minifier by Douglas Crokford. JSmin only removes whitespace. | wayback machine |
http://nanard.free.fr/demojs/ | local copy |
Making of Cyboman 5 | local copy |
RegPack and other LZss based packers work well in Javascript however PNG bootstraping gives much better compression ratios by giving access to gz/deflate compression and tools to JavaScript intros. PNG bootstraping is a polyglot file which is both a PNG image representing the code compressed, an HTML page which bootstrap the code compressed by loading it into an image, drawing and reading the pixels onto a canvas to rebuild the code uncopmressed before evaluating it.
The web platform offers many ways to render and animate things, from HTML+CSS including CSS transforms, transitions and filters, to SVG, 2D Canvas and eventually webGL ( a binding of OpenGL ES ). Each with their own strengths and weaknesses. The most common approaches remain 2D Canvas and webGL.
There are basically two ways to produce and play sounds in JavaScript. Using the Audio element or the Web Audio API.
The basic setup for either techniques clock around 170 bytes.
The Audio element is a simple HTML element whose core attributes and methods are src
, loop
and currentTime
, volume
, play()
and stop()
. To use this element in an intro, generate a WAVE PCM file and load it as a data:
URL.
// HEADER of an 8bits mono WAVE PCM at 16384 Hz
wavePCM = 'RIFF_oO_WAVEfmt ' + atob('EAAAAAEAAEABAAAAAEAAAABACAA') + 'data';
for(t = 0; t < duration; t += 1/16384)
wavePCM += String.fromCharCode(/* insert awesome synth here */);
A = new Audio('data:audio/wav;base64,' + btoa(wavePCM));
A.play();
// You can now access A.currentTime
The Web Audio API is a power house of audio nodes used to produce, filter, mix and play sounds in JavaScript. The ScriptProcessor node give programatic access to the next chunk of sound data needed to do realtime sound synthesis.
A = new AudioContext;
S = myAudio.createScriptProcessor(L = 4096, T = 0, /*channels=*/1);
S.connect(A.destination);
S.onaudioprocess= e => {
for (i = 0; i < L; i++, T += 1 / A.sampleRate)
e.outputBuffer.getChannelData(0)[i] = /* insert awesome synth here */
}