Check if Tone.js Audio Context is Initialized

In web audio development, browsers restrict audio playback until a user interacts with the page. This article provides a straightforward guide on how to check the initialization state of the audio context in Tone.js, verify if it is running, and properly activate it using user-triggered events.

Checking the Audio Context State

In Tone.js, the audio context is managed globally. You can determine if the audio context has been successfully initialized by checking the state property of the Tone.js global context.

The three possible states of the audio context are: * suspended: The context is paused or blocked (usually waiting for a user interaction). * running: The context is active, initialized, and ready to play audio. * closed: The context has been shut down.

To check the current state, access Tone.context.state (or Tone.getContext().state in newer versions):

if (Tone.context.state === 'running') {
    console.log('Audio context is successfully initialized and active.');
} else {
    console.log('Audio context is currently:', Tone.context.state);
}

How to Initialize the Audio Context

Because modern web browsers block autoplay to prevent unwanted noise, you must initialize the context inside a user gesture event handler, such as a button click.

Tone.js provides a helper function, Tone.start(), which returns a promise that resolves once the audio context transitions to the running state.

const startButton = document.querySelector('#start-btn');

startButton.addEventListener('click', async () => {
    // Start the audio context
    await Tone.start();
    
    // Verify the state immediately after
    console.log('Audio context state:', Tone.context.state); 
    // Output: "running"
});

Listening for State Changes

If you want to track the initialization state dynamically throughout your application’s lifecycle, you can bind an event listener to the statechange event of the context:

Tone.context.on('statechange', (state) => {
    console.log('Audio context state changed to:', state);
    
    if (state === 'running') {
        // Safe to trigger synths, players, or effects
        playAudio();
    }
});