Chapter 14

Web Audio API

Learning Objectives

  • Understand the Web Audio API
  • Learn about AudioContext and nodes
  • Create and connect audio nodes
  • See how MixMind uses the Web Audio API

What is the Web Audio API?

The Web Audio API is a powerful browser API for working with audio. It lets you:

  • Load and decode audio files
  • Process audio in real-time
  • Apply effects (filters, reverb, etc.)
  • Analyze audio (frequency, volume)
  • Synthesize sounds
  • Create complex audio graphs

MixMind relies heavily on the Web Audio API for all audio operations.

AudioContext

The AudioContext is the main entry point. It's like a factory for creating audio nodes.

// Create an AudioContext
const audioContext = new AudioContext();

// Important properties
console.log(audioContext.sampleRate); // 44100 (usually)
console.log(audioContext.currentTime); // Current time in seconds
console.log(audioContext.state); // 'running', 'suspended', 'closed'

// Resume if suspended (browsers require user interaction)
audioContext.resume();

Audio Nodes

Audio processing happens through nodes connected in a graph. Each node performs a specific function:

Node TypePurposeExample
SourceNodeAudio sourceBufferSource, MediaStream
GainNodeVolume controlAdjust volume
PannerNodeSpatial positioningLeft/right balance
FilterNodeFrequency filteringLow-pass, high-pass
AnalyserNodeAudio analysisFFT, waveform
DestinationNodeAudio outputSpeakers

Connecting Nodes

// Create nodes
const source = audioContext.createBufferSource();
const gain = audioContext.createGain();
const filter = audioContext.createBiquadFilter();

// Load audio
const response = await fetch('audio.mp3');
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
source.buffer = audioBuffer;

// Set parameters
gain.gain.value = 0.5; // 50% volume
filter.type = 'lowpass';
filter.frequency.value = 1000; // 1kHz cutoff

// Connect: source -> filter -> gain -> destination
source.connect(filter);
filter.connect(gain);
gain.connect(audioContext.destination);

// Play
source.start();

AudioBuffer

AudioBuffer holds decoded audio data in memory:

// Properties
console.log(audioBuffer.sampleRate); // 44100
console.log(audioBuffer.numberOfChannels); // 2
console.log(audioBuffer.duration); // seconds
console.log(audioBuffer.length); // total samples

// Get channel data
const leftChannel = audioBuffer.getChannelData(0);
const rightChannel = audioBuffer.getChannelData(1);

// Both are Float32Array
console.log(leftChannel instanceof Float32Array); // true
console.log(leftChannel.length); // Number of samples

// Create new AudioBuffer
const newBuffer = audioContext.createBuffer(
    2, // channels
    44100 * 5, // 5 seconds
    44100 // sample rate
);

🎵 MixMind Connection

How MixMind Uses Web Audio API

// Creating the main audio context
class AudioEngine {
    constructor() {
        this.context = new AudioContext();
        this.destination = this.context.destination;
    }
    
    async loadTrack(file) {
        const arrayBuffer = await file.arrayBuffer();
        const audioBuffer = await this.context.decodeAudioData(arrayBuffer);
        return audioBuffer;
    }
    
    playBuffer(audioBuffer) {
        const source = this.context.createBufferSource();
        source.buffer = audioBuffer;
        source.connect(this.destination);
        source.start();
        return source;
    }
    
    // For analysis
    createAnalyser() {
        const analyser = this.context.createAnalyser();
        analyser.fftSize = 2048;
        return analyser;
    }
}

// MixMind's audio processing pipeline
const engine = new AudioEngine();
const buffer = await engine.loadTrack(file);
// Now we can analyze or process this buffer

Exercise 14.1: Practice

Goal: Apply what you've learned in this chapter

Try the concepts from this chapter in your browser's console or a simple HTML file. Experiment with the code examples and modify them to see what happens.

📝 Quick Reference:

Review the key concepts from this chapter and make sure you understand each one before moving to the next chapter.