How to Loop a Specific Timeline Section in Tone.js

This article explains how to loop a specific section of the timeline in Tone.js using the Tone.Transport API. You will learn how to enable looping, define the exact start and end points of your loop using various time formats, and control playback to create repeating musical patterns.

Enabling and Configuring the Loop

In Tone.js, timeline playback is managed by Tone.Transport. To loop a specific section of your timeline, you need to configure three primary properties on the Transport object: loop, loopStart, and loopEnd.

  1. Tone.Transport.loop: A boolean value that must be set to true to enable looping.
  2. Tone.Transport.loopStart: The position on the timeline where the loop begins.
  3. Tone.Transport.loopEnd: The position on the timeline where the loop ends and jumps back to loopStart.

Defining Time Formats

Tone.js is highly flexible and accepts several time formats for loopStart and loopEnd:

Practical Code Example

The following code demonstrates how to set up a loop between measure 1 and measure 3 using a simple synthesizer to play a repeating note.

import * as Tone from "tone";

// Create a simple synth and connect it to the main output
const synth = new Tone.Synth().toDestination();

// Schedule a note to play at the start of measure 1
Tone.Transport.schedule((time) => {
  synth.triggerAttackRelease("C4", "8n", time);
}, "1:0:0");

// Schedule a note to play at measure 2
Tone.Transport.schedule((time) => {
  synth.triggerAttackRelease("E4", "8n", time);
}, "2:0:0");

// Configure the loop settings
Tone.Transport.loop = true;
Tone.Transport.loopStart = "1:0:0"; // Loop starts at measure 1
Tone.Transport.loopEnd = "3:0:0";   // Loop ends at measure 3 (then repeats)

// Start the audio context and the transport on user interaction
document.getElementById("startButton").addEventListener("click", async () => {
  await Tone.start();
  Tone.Transport.start();
});

In this setup, when the transport starts playing, it will progress normally until it reaches measure 3 ("3:0:0"). It will then immediately jump back to measure 1 ("1:0:0") and repeat that two-measure section indefinitely.