
About « The Drumlet »
Everything started when discovering the Audiolet Javascript library. Audiolet enables sound synthesis and music composition directly through the browser's Web Audio API
We quicky had the idea to create a small application running this technology and what's better than creating a drum machine?. One of the most famous drum machine being Roland's TR-808 we decided to use its samples as a basis (view the sample)
We wanted to maintain the machine's spirit, so we decided to give the Drumlet a vintage and realistic look and feel (Don't you hear transistors crackling?).
Technically
Now that we know what we're looking at, we chose to start with a 9 tracks machine : kick, snare, tom, rim shot, clap, cow bell, cymbal, open hihat et closed hihat.
On the Javascript side, a track looks like this:
var Voice = function(name, audiolet) {
AudioletGroup.call(this, audiolet, 0, 1);
// Set the name
this.name = name;
// Set the sequence
this.sequence = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
];
// Create an empty buffer
this.buffer = new AudioletBuffer(1, 0);
// Create a buffer player
this.player = new BufferPlayer(audiolet, this.buffer, 1, 0, 0);
// Create the sequencer
this.durations = new PSequence([0.25], Infinity);
this.pattern = new PSequence(this.sequence, Infinity);
// Create trigger to re-trigger the playback of samples
this.trigger = new TriggerControl(audiolet);
// Create a gain object to control the gain of sample
this.gain = new Gain(audiolet, 1.00);
// Create an upMixer object
this.upMixer = new UpMixer(audiolet, 2);
// Connect it all up
// output of trigger to input of player
this.trigger.connect(this.player, 0, 1);
// output of player to input of gain
this.player.connect(this.gain);
// output of gain to general output
this.gain.connect(this.upMixer);
// all signals will be added together when connected to the output
this.upMixer.connect(this.outputs[0]);
}
extend(Voice, AudioletGroup);
As you can see, a track is a AudioletGroup. And it allows us to encapsulate several elements and play a sample.
These 9 tracks will be connected to the « Audiolet » object in our Processor:
var Processor = function(sampleRate, bufferSize, bpm) {
// Create a new Audiolet object
this.audiolet = new Audiolet(sampleRate, 2, bufferSize);
this.audiolet.scheduler.setTempo(bpm);
// Scheduler events array
this.scheduler = [];
// Create a gain object
this.gain = new Gain(this.audiolet, 1.00);
// Create an upMixer object
this.upMixer = new UpMixer(this.audiolet, 2);
// Voices array
this.voices = {};
// Bassdrum
this.bd = new Voice('bd', this.audiolet);
this.bd.connect(this.gain);
this.voices['bd'] = this.bd;
// Snaredrum
this.sd = new Voice('sd', this.audiolet);
this.sd.connect(this.gain);
this.voices['sd'] = this.sd;
// Tom
this.tom = new Voice('tom', this.audiolet);
this.tom.connect(this.gain);
this.voices['tom'] = this.tom;
// Rim Shot
this.rs = new Voice('rs', this.audiolet);
this.rs.connect(this.gain);
this.voices['rs'] = this.rs;
// Clap
this.cp = new Voice('cp', this.audiolet);
this.cp.connect(this.gain);
this.voices['cp'] = this.cp;
// Cow Bell
this.cb = new Voice('cb', this.audiolet);
this.cb.connect(this.gain);
this.voices['cb'] = this.cb;
// Cymbal
this.cy = new Voice('cy', this.audiolet);
this.cy.connect(this.gain);
this.voices['cy'] = this.cy;
// Open HiHat
this.oh = new Voice('oh', this.audiolet);
this.oh.connect(this.gain);
this.voices['oh'] = this.oh;
// Closed HiHat
this.ch = new Voice('ch', this.audiolet);
this.ch.connect(this.gain);
this.voices['ch'] = this.ch;
// output of gain to input of the upMixer
this.gain.connect(this.upMixer);
// all signals will be added together when connected to the output
this.upMixer.connect(this.audiolet.output);
}
After that, you only have to use the object's sequencer to play a sample at a given moment. Therefore we have a loop which will run the sequencer for our 9 tracks. On each « tick » (The interval is given by the bpm) the sample will be played (or won't) at a volume defined by the value of the current pattern.
var voice = null;
for(k in this.voices) {
voice = this.voices[k];
this.scheduler[k] = this.audiolet.scheduler.play([voice.pattern], voice.durations, function(pattern) {
// apply amplitude
if(pattern == 2)
this.gain.gain.setValue(1.00);
else if (pattern == 1)
this.gain.gain.setValue(0.50);
// re-trigger the sample
if(pattern > 0)
this.trigger.trigger.setValue(1);
}.bind(voice));
}
Volume's variation is implemented in the « scheduler »'s callback play function. A track sequence can therefore be defined as:
1 – 0 – 0 – 0 – 2 – 0 – 0 – 0 – 1 – 0 – 0 – 0 – 2 – 0 – 0 – 0Now that the audio engine is up, you only have to make things pretty and use graphical interface. To do so, we used the « canvas » technology and the EaselJS library.
Shortcuts
To create something not only funny but also usable, we decided to use several keyboard shortcuts to help everyone creating and playing his/her own music.
These shortcuts are:
(Spacebar) : Play/Pause
![]()
(Arrow up/down) : Volume
+ ![]()
(Ctrl + arrow up/down) : Tempo
![]()
(Delete & backspace) : Clear
![]()
(Arrow left/right) : Switch patterns
![]()
![]()
![]()
(1, 2, 3, 4) : Edit patterns 1, 2, 3, 4
Sharing
You can also share your very own tune with your friends using a unique address and maybe we'll discover you're really gifted at this!
Play
Now it's time to play!
We would be really glad to hear what you can compose with it so don't hesitate to share your creations with us.

Hey Guys, great app, thanks for all your efforts.
I am thinking about using it as a metronome/drum machine for my fingerpicking projects. Am at the very beginning of the road though.
Can't seem to find how to share my patterns with myself (I think it would be a method to "save" them.)
Thanks,
Zsolt
I've found it, just needed to look harder :)
Amazing work Dude.Your app inspired me to write an article here is the link.
http://prashantsani.com/spider/2012/01/html5-musical-instruments/
All the best and thanks for inspiring.
Did I waste some 30 mins of my life or enjoyed most for 30 mins in my life?
Why does it take so long to load… It may not be on other pc’s, but at my pc it’s loading for about 30 minutes already… Chrome 16.0.912.77, Win7 Premium
Fuckin siiiiiick. Love it. Check my beat out yo!
http://drumlet.epic.net/p/4f2ea5a87dbc0f2eca0000f3
#getrichhull
Didn’t load.
Chrome 13.0.7
OS X 10.6.8
Updated Chrome to version 16. It’s working now.
great…great…great
Cool old skool guys! Works like a charm (OSX 10.7.2 + Chrome 16.0.912.77) Amazing but have to stop otherwise my boss will go mad; addicting ;-)
Are you able to put “effects” on the tracks?
http://www.kendallarneaud.me/facebook/detnator I tried to create something similar but to use samples and apply effects to them….doesn’t pan out too well.
I’m having trouble being able to apply the filter/dsp nodes to audio buffer files…any suggestions?
Awesome experiment!! very similar to reason. Check out my beat:
My Tune
And an “Epic” Site!!!!
;)
Chrome 21 and it’s not working. Any ideas. please?