Web Audio API: Build a Digital Synthesizer in under 50 Lines of JavaScript
Making Noise: Build a Digital Synthesizer in 50 Lines of JavaScript
For a long time, playing sound in a web browser meant using the clunky <audio> HTML tag. You could play, pause, or loop an existing MP3 file, but you couldn't manipulate the sound wave itself, generate raw sound waves, or create real-time audio effects. That all changed with the introduction of the Web Audio API.
The Web Audio API is a high-performance system for controlling audio on the Web, allowing developers to generate sound synthesis, design spatial effects, analyze audio frequencies, and much more. In this post, we’ll build a fully working, interactive monophonic synthesizer in under 50 lines of pure JavaScript.
๐ต How the Web Audio API Works: The Audio Graph
The Web Audio API operates on the concept of an **Audio Graph**. Instead of calling simple playback methods, you construct a network of modular **Audio Nodes** connected together, similar to linking guitar effects pedals with cables:
- Source Node: Generates the sound (e.g., an
OscillatorNodegenerating a raw mathematical wave). - Modification Nodes: Manipulates the sound (e.g., a
GainNodefor volume, or aBiquadFilterNodefor high/low pass filtering). - Destination Node: The final output, usually representing the user's speakers or headphones (
audioCtx.destination).
๐น The Synthesizer Code
Here is the complete JavaScript code to initialize an audio context, create an oscillator, connect a volume knob (gain), and play a note at a specific frequency:
// Initialize the Web Audio Context
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playTone(frequency, duration = 0.5) {
// 1. Create the Oscillator (Source)
const oscillator = audioCtx.createOscillator();
// 2. Create the Gain Node (Volume control)
const gainNode = audioCtx.createGain();
// Configure the Oscillator
oscillator.type = 'sawtooth'; // Try 'sine', 'square', or 'triangle'
oscillator.frequency.value = frequency; // Frequency in Hz (e.g., 440 for A4)
// Smooth out the sound (Envelope) to prevent clicking noises
const now = audioCtx.currentTime;
gainNode.gain.setValueAtTime(0, now);
gainNode.gain.linearRampToValueAtTime(0.5, now + 0.1); // Attack
gainNode.gain.exponentialRampToValueAtTime(0.0001, now + duration); // Decay/Release
// 3. Connect the Nodes: Oscillator -> Gain -> Speakers
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
// Start the oscillator immediately, and stop it after duration
oscillator.start(now);
oscillator.stop(now + duration);
}
// Example: Play an A4 note (440Hz) when the user clicks anywhere
document.addEventListener('click', () => {
// AudioContext must be resumed after a user gesture (browser security)
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
playTone(440, 0.8);
});
๐ฌ Deep Dive: Customizing the Sound Wave
In the code above, the oscillator's type is set to 'sawtooth'. The Web Audio API provides four basic waveforms out of the box, each with its own harmonic texture:
- Sine (
'sine'): A pure, clean, whistle-like sound wave with no harmonics. Ideal for sub-bass or smooth flute sounds. - Square (
'square'): A hollow, buzzy sound wave. Very retro and perfect for 8-bit chip-tune game sounds. - Triangle (
'triangle'): A softer, warmer wave. A middle ground between sine and square. - Sawtooth (
'sawtooth'): A harsh, bright, buzzy wave packed with harmonics. The foundation of modern EDM lead synths and brassy sounds.
By hooking up this simple function to a set of HTML buttons representing keys, you can build a playable musical keyboard directly in the browser with zero external dependencies.
Have you ever built anything with the Web Audio API? What kind of browser-based audio app would you want to build next? Tell me all about it in the comments below!

Comments
Post a Comment