Back to Blog
Web AudioThree.jsGame Audio

Building EvilAudio.js: A Complete Audio Engine for Three.js & WebGL

An in-depth look at building a professional audio engine for the web.

EvilAudio.js is an audio engine I'm building specifically for Three.js and WebGL applications. It brings game-engine-quality audio features to the browser—3D spatial audio, adaptive music, real-time parameter control, and beat-accurate transitions—all in a lightweight, web-first package.

Why Build Another Audio Engine?

Existing solutions either export bloated Unity/Babylon packages or lack the features needed for immersive experiences. EvilAudio.js aims to fill that gap: professional-grade audio that's built specifically for browser constraints.

Core Architecture

The engine is built around six main components that work together through a central AudioEngine controller.

AudioEngine (Main Controller)

The central hub that manages everything:

  • Initializes and manages the Web Audio Context
  • Handles browser autoplay unlocking
  • Manages master volume/gain
  • Tracks all active sounds and music
  • Runs the update loop for parameters and transitions
  • Manages the listener (the 3D audio "ear")

Sound (3D Sound Effects)

Individual sound effects with full spatial audio support:

  • 3D positioning via PannerNode
  • Doppler effect calculation based on velocity
  • Distance attenuation
  • Reverb/environmental audio
  • Parameter mappings (RTPC)
  • Looping and playback controls

Music (Single-File Music System)

Music playback with BPM awareness and region support:

  • Single audio file with defined regions
  • User-provided BPM tracking
  • Loop points (start/end in seconds)
  • Lead-in/intro sections
  • Markers for musical sections
  • Beat-synced transitions
  • Crossfade capabilities

AdaptiveMusic (Multi-Stem System)

Layer-based adaptive music for dynamic soundtracks:

  • Multiple synchronized audio stems
  • Layer mixing (fade stems in/out)
  • Vertical remixing based on parameters
  • Horizontal re-sequencing between variations
  • All stems stay in sync via shared clock

Parameter (RTPC System)

Real-time parameter control that drives audio properties:

  • Create parameters with min/max ranges
  • Map to volume, pitch, filter, layer volumes
  • Define curves (linear, logarithmic, custom)
  • Engine automatically updates mapped properties

Listener (3D Audio Ear)

The "camera" for audio—where the player hears from:

  • Tracks position and orientation in 3D space
  • Syncs with Three.js camera
  • Used by all 3D sounds for positioning calculations

Beat-Accurate Scheduling

One of the trickiest parts of web audio is timing. The engine uses a lookahead scheduling system:

  • Track current playback position in beats, not seconds
  • Calculate when the next beat/bar occurs
  • Schedule transitions ~100ms ahead
  • Web Audio executes at the precise time

This ensures musical transitions happen exactly on beat, not whenever JavaScript gets around to it.

Usage Example

// Initialize engine
const engine = new AudioEngine();

// Set listener to Three.js camera engine.setListener(camera);

// Create a 3D sound effect const footstep = engine.createSound('footstep', { file: 'footstep.mp3', position: {x: 0, y: 0, z: 0}, loop: false });

// Create parameter for player speed const speed = engine.createParameter('speed', 0, 100); footstep.mapParameter('speed', 'volume', linearCurve);

// Create adaptive music with stems const adaptiveMusic = engine.createAdaptiveMusic('exploration', { bpm: 120, stems: [ { name: 'ambient', file: 'ambient.mp3' }, { name: 'drums', file: 'drums.mp3' }, { name: 'melody', file: 'melody.mp3' } ] });

// In animation loop: function animate() { engine.update(deltaTime); speed.setValue(camera.velocity.length()); footstep.setPosition(player.position); requestAnimationFrame(animate); } ```

Key Features

  • **3D Spatial Audio** — Doppler, reverb, distance attenuation
  • **RTPC System** — Map any parameter to any audio property
  • **Adaptive Music** — Single-file or multi-stem with BPM sync
  • **Beat-Accurate Transitions** — Lookahead scheduling
  • **Framework Agnostic** — Works with Three.js, Babylon.js, vanilla WebGL
  • **Lightweight** — Much smaller than Unity/Babylon exports
  • **Web-First** — Built specifically for browser constraints

What's Next

I'm currently working on the parameter curve system and testing the adaptive music stem synchronization. More updates to come as the engine develops.