Audio | Part 3 — Controlling Beat Playback with Tone.js

When performing web-based audio manipulation with the Tone.js library, one quickly realizes the sheer scope of possibilities. Among the most fundamental, yet critical aspects, is understanding how to control your beat's playback - when it starts and when it stops. In this blog post we'll delve into the intricacies of how to command your beats, stopping them in their tracks, and adding that crucial control to your sonic web creations.

Existing Code Breakdown

Currently, we have three different sound samples: a kick, a snare, and a hi-hat. The function playBeat is set up to schedule these samples to play in a repeating loop, creating a rhythmic beat. When a button on the webpage is clicked, the startBeat function begins this loop.

const kick = new Tone.Player("./kick.mp3").toDestination();
const snare = new Tone.Player("./snare.mp3").toDestination();
const hihat = new Tone.Player("./hi-hat.mp3").toDestination();

const playBeat = () => {
  Tone.Transport.scheduleRepeat((time) => {
    hihat.start(time);
    hihat.start(time + 0.25);
    hihat.start(time + 0.5);
    hihat.start(time + 0.75);

    kick.start(time);
    snare.start(time + 0.5);
  }, "2n");
  
  Tone.Transport.start();
};

const startBeat = () => Tone.start().then(() => {
  playBeat();
});

const btn = document.querySelector('button');
btn?.addEventListener('click', () => startBeat());

Implementing Beat Stop Functionality

To stop the beat, we need to stop the Tone.Transport, which controls the timing of our scheduled tasks. Let's create a function called stopBeat to do this.

const stopBeat = () => {
  Tone.Transport.stop();
  Tone.Transport.cancel();
};

Tone.Transport.stop() stops the Transport's timeline progression, while Tone.Transport.cancel() clears all scheduled events.

Adding Stop Button and Functionality

Now, let's create a button on our webpage that will stop the beat when clicked. Here's the new HTML for our stop button:

<button id="start">Start Beat</button>
<button id="stop">Stop Beat</button>

And here's the updated JavaScript to include event listeners for both the start and stop buttons:

const startButton = document.querySelector('#start');
const stopButton = document.querySelector('#stop');

startButton?.addEventListener('click', () => startBeat());
stopButton?.addEventListener('click', () => stopBeat());

Now, when the "Start Beat" button is clicked, our beat will start, and when the "Stop Beat" button is clicked, the beat will stop.

Demo

Wrapping Up

And that's it! Now you have control over when your beat starts and stops. It's worth mentioning that this is a simple implementation, and there are numerous other ways to control audio playback with Tone.js, such as adding pause functionality, altering the playback speed, and much more. Feel free to experiment and create a playback control system that suits your project's needs.