Drum Loops and Effects with Web Audio API
Before we start, just a note: you might want to read thisintroductory post first if you are new to Web Audio API.
Let's do something we can hear: play a looping beat.
To play the audio buffer we loaded we need a BufferSource which we connect to the output. Continuing the studio analogy from my other blog post:AudioContext is the sound studio where all the equipment lives, buffer (that we already loaded) is an mp3 file, The BufferSource is an mp3 player created like this: source = context.createBufferSource(); Load the mp3 file in the mp3 player: source.buffer = buffer; context.destination is the speakers. The .connect() method is the wire, Connect the mp3 player to the speakers: source.connect(context.destination);
Good, all hooked up!
The sound clip is just 1.8 seconds long but looping is as easy as: source.loop = true; . Now it will play in a gapless loop until you click Stop.
Hit the play button on the mp3 player with source.start() .
Trivia: do you know what the beat is called and where it comes from? (It's not the whole sample, I just took a bar/measure.) Answer in the comments below :)
"But hey! Why are we recreating, connecting and configuring all of this stuff from scratch every time Start is clicked?!"
Good question! You see, once a BufferSource is stopped you can't start it again. The MDN documentation about stop() says:
If this method is called twice or more, an exception is raised.
Recreating everything over and over again is totally OK, it's the intended way of working. Those operations are cheap, don't be afraid, later we are going to trigger a whole slew of BufferSource s to play... :smiling_imp: But first:The Phaser Effect
Back in 1996, I was a big fan of Chemical Brothers. I must have listened to their album "Exit Planet Dust" a thousand times. On the track "Song To The Siren", at 2.01, there is this phaser effect on the drum loop that I thought sounded very cool.
We can easily create the same sort of effect with Web Audio API by starting two loops of the same beat but setting the playback rate on one slightly faster than the other. Over time they will drift away from each other, going from phaser to echo to chaos to headache. :hear_no_evil:
To get the two loops to start at the exact same time I'm reading the currentTime property on the AudioContext and using it as a parameter in the two calls to start() .
If you listen for a while you will hear the two loops becoming more and more out of synch. I think the Chemical Brothers adjusted the playback rate continuously so that the two loops drifted back together again.The Aphex Twin Effect
Aphex Twin is an artist that experiments a lot with sounds. Sometimes to a point where the result is more abstract sound art than a song. To me, his signature effect is triggering drums tightly and aggressively creating a metallic robotic stutter effect.
We are going to use the same drum beat as we did before. It is sliced in short peaces and scheduled to be played with a for loop in the code. You can control the slice size, delay, overlap and slice duration with the sliders.
To the AudioBufferSourceNode.start() method you can specify three parameters (all three are optional):When to start Offset - where in the audio buffer to start Duration - for how long we should play the sound
With these three parameters we can get the slices to be played with a slight overlap to create a stuttering effect.
Note that you can click the Result button to hide the result tab and automatically expand the JS tab. It's easier to read the code that way. =)
That's it for now, thank you for reading. Go ahead and f0rk my Pens and start experimenting. Share the result in the comments below.
Other blog posts I have written about Web Audio API:Fun with Web Audio API - already mentioned in the begining. More Fun with Web Audio API - creating reverb with ConvolverNode and more.
I also have a CodePen Collection with allmy Web Audio Pens.