How to Trigger Notes with Velocity in Tone.js

Triggering notes with a specific velocity in Tone.js allows developers to control the volume and dynamics of synthesized sounds, creating more realistic and expressive audio experiences in the browser. This article provides a straightforward guide on how to configure a synthesizer and use the triggerAttackRelease method to play notes with varying velocity levels.

In Tone.js, velocity is represented as a normalized value between 0 (silent) and 1 (maximum intensity). It determines how hard or fast a note is struck, which directly influences the output volume and timbre of the synthesizer.

Step 1: Initialize the Synthesizer

First, you need to create an instance of a Tone.js synthesizer and connect it to the main audio output (toDestination).

import * as Tone from 'tone';

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

Step 2: Use the triggerAttackRelease Method

To trigger a note with velocity, use the triggerAttackRelease method. This method accepts four main arguments: 1. Note: The pitch of the note (e.g., "C4"). 2. Duration: How long the note should hold (e.g., "8n" for an eighth note). 3. Time: When the note should start playing (use undefined or Tone.now() for immediate playback). 4. Velocity: A number between 0 and 1 defining the velocity.

Code Example

Here is how to play the same note at three different velocity levels:

// Ensure the audio context is started before playing sounds
await Tone.start();

const now = Tone.now();

// Play a quiet note (velocity 0.2)
synth.triggerAttackRelease("C4", "8n", now, 0.2);

// Play a medium-volume note (velocity 0.5) half a second later
synth.triggerAttackRelease("C4", "8n", now + 0.5, 0.5);

// Play a loud note (velocity 1.0) one second later
synth.triggerAttackRelease("C4", "8n", now + 1, 1.0);

Alternative: Using PolySynth

If you are using a PolySynth to trigger chords, the process remains the same. You can pass an array of notes and a single velocity value to apply to all of them:

const polySynth = new Tone.PolySynth().toDestination();

// Trigger a C Major chord with a velocity of 0.6
polySynth.triggerAttackRelease(["C4", "E4", "G4"], "4n", undefined, 0.6);