Hacker News new | ask | show | jobs
Show HN: Drum machine in 100 lines of HTML/JS (sig.gy)
134 points by siggy 3565 days ago
21 comments

I had a go at rewriting this to use requestAnimationFrame, and provide more instruments and some random/clear buttons: https://blog.omgmog.net/beatmaker/

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.

Really like your changes! I've incorporated your use of requestAnimationFrame and AudioContext back into mine: https://github.com/siggy/beatboxer/commit/dccff243474b17ca34...
Well your version doesn't crash shortly after toying around in it unlike OP's so good job!.
Never use setInterval for audio based applications. It's just totally unreliable. WebAudio has nice built in features for high precision timing.
When the goal is showing off what you can do with 100 lines of code, what's wrong with it?

I doubt high precision timing can be done with the same amount of code.

First, it's an enourmous waste of computing resources. Second, it doesn't even work, since the 'setinterval' is unusable for audio timing. Third, what's there to show off? So Javascript got a 'PlayWav' function that you call in not so regular intervals depending on buttonstate. Simple beatbox is simple. Could aswell be 30 lines.
Not sure why this is down voted — the demo literally does not work in my browser (Safari 10) because of the (mis)use of setInterval.
>Safari

Try a better browser first. You might as well be using IE 8. I could write a book about the things that don't work in Safari.

The problmem is that it's shaking like it has Parkinson's. It can be be coded with webaudio with the same effort.

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.

I thought the drum sounds would be generated using JS, but they are just pre-recorded samples (bass_drum.wav, snare_drum.wav, low_tom.wav, mid_tom.wav, hi hat, cymbal, cowbell, hand clap, hi tom, conga, claves). I'm looking for drum-generated sounds using pure javascript, so I can make changes on them and create new kinds of sounds. I already created some pure JS sounds (e.g. laser sounds, bass effect, white noise, achords, bell sounds, water drop) but I'm still looking for equations to generate more realistic drum sounds: http://js.do/blog/sound-waves-with-javascript/
I can't give you 'realistic' drum sounds, but I was working on an approximate recreation of a Roland analog drum machine using only Javascript. I got the sound engine down more or less, but kind of fell off the rails when I moved away from my earlier, crappier sequencer and started using a framework.

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/

Looking at the source, yours appears to be sample based too. I think the GP was interested in an oscillator based sound engine.
These appear to be the synthesized versions:

https://github.com/leviathant/BossDR110/blob/feature/synthes...

To the parent, what did you use as the reference for the synthesis patches and parameters? I wouldn't mind trying something similar in ChucK.

My Boss DR-110, a probe, and oscilloscope software - Visual Analyser 2011. You can short the different individual oscillators to ground, and they'll come out the audio & headphone jack.

There's a great breakdown of how the circuitry works at http://www.sdiy.org/richardc64/new_drums/dr110/dr110a1.html - but some of the frequency values there (related to the cymbals) didn't sound right to me - though it's possible I misinterpreted what's going on at that page.

Thanks!

I added a sample-based ChucK class with examples here https://github.com/heuermh/lick/commit/be60769ae32ca955b35b9....

I'll dig into the docs you linked to and see if I can come up with a synthesized version as well!

I started out with a sample-based version in 2011 or so, but the link I posted uses synthesized sounds, in updates I made last year. Have a closer look at the javascript as referenced in index.html and take a look at dr110_synth.js

This is probably most evident if you play a roll on the snare or the handclap. A free-running LFO on the noise sources for these instruments prevents "machine-gunning" like you get when you roll a sample.

Reminds me of one I made years ago (back before Web Audio, when the HTML5 <audio> tag was actually pretty new)[0]. It's not under 100 lines, but it's self-contained and (mostly) readable like this one is. These days I'd definitely go with Web Audio as the playback mechanism, of course.

[0] http://stepheneisenhauer.com/demos/drummachine/

The last 2 sequence boxes for each type of hit wrap around to a new line (firefox). Pretty cool for 100 lines of HTML and JS.
Fun! I like the interface and the URL pattern encoding.

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.

With a slider to change bpm:

http://www.bambax.com/beatboxer/

Nice, but your slider is blocking interaction with most of the boxes http://i.imgur.com/Ae4uyoJ.png
Yes, corrected, can you check?

(height problem since the slider is rotated to make it vertical).

Very cool! It'd be great if you could also serialize the notes to the url, so people can share these.
Nice work! Although from my experience with audio programming in the browser, setInterval() is always fraught with timing danger and inconsistencies.

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...

Nice! A little feature suggestion -- it would be really cool if the current pattern were encoded in a URL so you could link it to friends. :)
I can change color of the boxes. Something animates from left to right. But I can't hear anything. (Android 7, latest Chrome.)
Tried it on my desktop computer now - works just fine, nicely done. Needs more cowbell, though.
Me too - android 6,latest chrome. Works fine on Firefox on the same phone...
Unenjoyable, even as a gimmick, since the timing is all over the place. Either get timing right, or don't do a drum machine. Also this wastes resources like mad. What's the point of this?
Cool! when tab is not active, the rhythm slows down in Chrome/win7.
This is due to a step taken by the browser to improve performance, namely, timers in Chrome are limited to 'ticking' at most once a second when a tab is backgrounded. The drum loop is at its core:

    setInterval(function() {...}, 1 / (4*BPM/(60*1000)));
https://codereview.chromium.org/6577021
How peculiar you didn't use the webaudio API for this. I'm working on something similar right now for sun, but with a bank of generated sounds through the oscillator.
Cool! It would be cool to have more instruments to create little loops to share with friends.
hehe.. I was just a few squares short of recreating drop it like it's hot :D
it behaves weirdly when you change the tabs, must be because of setInterval?
JS intervals are limited to one per second for background tabs.
This is really fun, FYI. Social features would be fun.
Very nice. Could you add a hi-hat?
Super fun.