Including whitespace it's 102 lines: https://github.com/omgmog/beatmaker/blob/master/js/index.js
An interesting thing, after a short while the browser unloads the page (Chrome on Mac OS) -- probably due to memory usage, which I think this is down to creating a new Audio element each time, rather than initialising them once and then triggering .play() when needed.
update:
Alright I'm using AudioContext now rather than `new Audio`, seems to be performing a lot better. This puts us at about 144 lines.
I doubt high precision timing can be done with the same amount of code.
I've researched this in the past and it's nowehere near significant more complexity. In fact, a primitive solution is about the same as a setInterval call.
The sounds should work across browsers when you're manually playing (use the bottom row of your keyboard) but when sequenced playback happens, things get weird. Chrome more accurately reproduces the sounds as I'm imagining them.
Grab the whole thing at https://github.com/leviathant/BossDR110/tree/feature/synthes... or just play around with it yourself at http://bitrotten.com/dr110/webaudio/
Here's mine: http://wa-101.net/. I used setInterval too, because I found the web audio api docs for the timing functions rather confusing, and I'd set myself a time-limit on getting something "attractive" working.
(height problem since the slider is rotated to make it vertical).
http://www.bambax.com/beatboxer/index.html#x||||x||||x||||x|...
Edit: now also saves bpm value: http://www.bambax.com/beatboxer/#x||||x||||x||||x||||||x||x|...
Have you considered using WebAudio's streaming functionality to tighten up the timing to something more rock solid? Probably a bit more setup in the first part, but for a drum machine especially, you get much better control over timing and playback note length.
I wrote an Ionic specific example of using the browser's WebAudio functionality to write a metronome app here: https://www.airpair.com/ionic-framework/posts/using-web-audi...
http://www.bambax.com/beatboxer/index.html#x||||x||||x||||x|...
setInterval(function() {...}, 1 / (4*BPM/(60*1000)));
https://codereview.chromium.org/6577021