function setup() {
  createCanvas(720, 400);
  frameRate(10);
  controlPanelHeight = height / pitches.length;

  // Prepare cells
  cellWidth = width / numTimeSteps;
  cellHeight = (height - controlPanelHeight) / pitches.length;
  for (var i = 0; i < numTimeSteps; i++) {
    for (var j = 0; j < pitches.length; j++) {
      var x = i * cellWidth;
      var y = controlPanelHeight + j * cellHeight;
      var pitch = pitches[pitches.length - j - 1]; // Pitches go from bottom to top
      var newCell = new Cell(createVector(x, y), pitch);
      cells.push(newCell);
    }
  }

  // Create a synth to make sound with
  synth = new p5.PolySynth();

  // Create SoundLoop with 8th-note-long loop interval
  sloop = new p5.SoundLoop(soundLoop, "8n");
  sloop.bpm = bpm;

  // UI
  playPauseButton = createButton('PLAY/PAUSE');
  playPauseButton.mousePressed(togglePlayPause);
  playPauseButton.position(0, 0);
  playPauseButton.size(width / 4, controlPanelHeight);

  tempoSlider = createSlider(30, 300, bpm);
  tempoSlider.position(width / 4, 0);
  tempoSlider.size(width / 4, controlPanelHeight);
  tempoText = createP("BPM: " + bpm);
  tempoText.position(width / 2, 0);
  tempoText.size(width / 4, controlPanelHeight);

  clearButton = createButton('CLEAR ALL');
  clearButton.mousePressed(clearAll);
  clearButton.position(width * 3 / 4, 0);
  clearButton.size(width / 4, controlPanelHeight);
}
Example of using the p5.SoundLoop in a dynamic user-controlled
manner: the grid sequencer.

Users can select what tune the sequencer plays by clicking to
activate/deactive notes, start and pause playback, and control
playback tempo on-the-fly.