How to Configure Tone.AMSynth in Tone.js

This article provides a practical guide on how to configure and use the Tone.AMSynth class in Tone.js to create amplitude modulation (AM) synthesis. You will learn the core architecture of an AM synthesizer, how to instantiate the synthesizer with custom properties, adjust the carrier and modulator oscillators, and trigger sounds in your web applications.

Understanding Tone.AMSynth

Amplitude modulation synthesis involves two oscillators: a carrier and a modulator. In Tone.AMSynth, the output of the modulator oscillator modulates the amplitude (volume) of the carrier oscillator. This creates sidebands and rich, metallic, or tremolo-like timbres depending on the frequency relationship between the two oscillators.

Basic Initialization

To use Tone.AMSynth, you must first import Tone.js and create an instance of the synthesizer, connecting it to the master output.

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

// Play a note
synth.triggerAttackRelease("C4", "8n");

Configuring Synth Parameters

You can highly customize the sound of the Tone.AMSynth by passing a configuration object to the constructor. The primary parameters you can configure include harmonicity, detune, oscillator (the carrier), envelope (the carrier’s envelope), modulation (the modulator), and modulationEnvelope (the modulator’s envelope).

Here is a comprehensive configuration example:

const amSynth = new Tone.AMSynth({
  harmonicity: 2.5,
  detune: 0,
  oscillator: {
    type: "sine"
  },
  envelope: {
    attack: 0.05,
    decay: 0.2,
    sustain: 0.6,
    release: 0.8
  },
  modulation: {
    type: "triangle"
  },
  modulationEnvelope: {
    attack: 0.1,
    decay: 0.2,
    sustain: 1.0,
    release: 0.5
  }
}).toDestination();

Parameter Breakdown

Modifying Parameters Dynamically

You can also modify the synthesizer’s parameters dynamically after initialization using the set method or by directly targeting the AudioParams.

// Change harmonicity dynamically
amSynth.harmonicity.value = 1.5;

// Change carrier oscillator type
amSynth.oscillator.type = "sawtooth";

// Ramp detune over time
amSynth.detune.setValueAtTime(0, Tone.now());
amSynth.detune.linearRampToValueAtTime(1200, Tone.now() + 2);

Triggering the Synthesizer

To play a sound, you must ensure the audio context is started (usually via a user interaction like a button click) and then call triggerAttackRelease.

document.querySelector('#play-button').addEventListener('click', async () => {
  await Tone.start();
  
  // Play a C4 note for the duration of a quarter note
  amSynth.triggerAttackRelease("C4", "4n");
});