Need Game Art? Edit Game Trailers Launch Your Dev Site Sell Your Merch
Need Game Art? Sell Your Merch

Spatial Audio in Browser Games

Updated July 2026
Spatial audio makes sounds come from specific positions in your game world. An enemy growling to the left plays louder in the left speaker. A waterfall in the distance sounds quieter and more reverberant. The Web Audio API's PannerNode and AudioListener handle all of this with built-in 3D positioning, distance attenuation, and optional HRTF processing for headphone playback.

The Audio Listener and Panner Model

The Web Audio API's spatial system has two halves. The AudioListener, accessible via ctx.listener, represents the player's ears. It has a position and orientation in 3D space. The PannerNode represents a sound source with its own 3D position. The API automatically calculates the spatial relationship between each PannerNode and the listener, applying appropriate stereo panning, volume attenuation, and filtering.

In a 3D game, you update the listener position and orientation every frame to match the camera. In a first-person game, the listener moves with the player character. In a third-person game, you might position the listener at the camera or at the character depending on which feels more natural for your game.

Setting the listener position uses either the deprecated setPosition(x, y, z) method or the newer AudioParam-based properties: ctx.listener.positionX.value, ctx.listener.positionY.value, ctx.listener.positionZ.value. The AudioParam approach is preferred because it supports smooth interpolation and scheduled changes, though both work in all current browsers.

The listener's orientation is defined by two vectors: a forward vector (where the listener is facing) and an up vector (which direction is "up"). These use ctx.listener.forwardX/Y/Z and ctx.listener.upX/Y/Z AudioParams, or the deprecated setOrientation() method. For most games, the forward vector matches the camera's look direction and the up vector is (0, 1, 0).

Creating Spatialized Sound Sources

To make a sound come from a specific world position, route it through a PannerNode before connecting to the output. Create the PannerNode, set its position to the sound source's world coordinates, connect your audio source to the PannerNode, and connect the PannerNode to the gain chain and destination.

The PannerNode position is set similarly to the listener: panner.positionX.value = worldX, panner.positionY.value = worldY, panner.positionZ.value = worldZ. For moving sound sources (a car driving past, a projectile flying overhead), update these values every frame in your game loop. The AudioParam approach handles smooth interpolation between frames automatically.

Each PannerNode adds processing overhead, so do not create one for every sound in your game. UI sounds, music, and ambient background tracks should bypass the PannerNode entirely and connect directly to their gain nodes. Only gameplay sounds that exist at specific world positions, such as enemy sounds, environmental objects, and player weapon audio, need spatial processing.

A PannerNode is reusable across multiple source nodes. If an enemy at position (10, 0, 5) plays several different sounds, those source nodes can all connect to the same PannerNode. This saves processing compared to creating a new PannerNode for each sound.

Distance Models

The PannerNode's distanceModel property controls how volume changes with distance between the source and the listener. Three models are available:

Linear decreases volume linearly between refDistance (full volume) and maxDistance (silence). The formula is straightforward: gain = 1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance). This model is easy to reason about and predictable, but it does not sound realistic because real-world sound does not attenuate linearly.

Inverse uses an inverse relationship where volume drops quickly near the source and gradually at greater distances. The formula is gain = refDistance / (refDistance + rolloffFactor * (distance - refDistance)). This is more physically accurate and is the default model. A rolloffFactor of 1.0 simulates real-world inverse-square attenuation. Values above 1.0 make sounds drop off faster, which is useful for keeping sounds localized to small areas.

Exponential uses an exponential curve for even faster falloff: gain = (distance / refDistance) ^ (-rolloffFactor). This creates tight sound bubbles where audio is loud near the source and drops to near-silence quickly. It is useful for point sources like torches, machinery, or NPCs where you want sound audible only within a specific radius.

Tuning these parameters requires matching them to your game world's scale. If your world units are meters, a refDistance of 1 and maxDistance of 50 works for most environmental sounds. If your world uses arbitrary units, scale accordingly. The rolloffFactor is your fine-tuning knob: higher values make sounds more localized, lower values make them carry further.

Stereo Panning for 2D Games

For 2D games, the full 3D PannerNode is overkill. The StereoPannerNode provides simple left-right panning with a single pan parameter ranging from -1 (full left) to 0 (center) to 1 (full right). It is computationally cheaper than PannerNode and maps naturally to 2D game worlds.

Map the sound source's X position relative to the player to the pan value. If the player is at X=100 and a sound source is at X=200, with a hearing range of 500 units, the pan value is (200-100)/500 = 0.2, placing the sound slightly right of center. Clamp the result to the -1 to 1 range.

For distance attenuation in 2D, calculate the distance between the source and the player, then manually set a GainNode's value based on a distance formula. A simple linear falloff: gain = Math.max(0, 1 - distance / maxDistance). An inverse falloff: gain = refDistance / (refDistance + distance). This gives you the same distance models as PannerNode but with manual calculation.

Some 2D games with a top-down perspective benefit from subtle use of the full PannerNode with Y set to 0 for all sources. This allows sources to pan left/right and also above/below the listener when using HRTF, which adds surprising depth to a 2D soundscape.

HRTF vs. Equal Power Panning

The PannerNode's panningModel property offers two modes. "equalpower" distributes the signal between left and right channels using a simple equal-power curve. It provides basic left-right positioning but no sense of front/back or above/below. It is computationally cheap and works well with speakers.

"HRTF" (Head-Related Transfer Function) applies frequency-dependent filtering that simulates how human ears perceive sound direction. Sound arriving from behind is filtered differently than sound from the front, creating a convincing sense of direction even on stereo headphones. This is the same technology used in VR and WebXR audio.

HRTF sounds dramatically better on headphones. Players can genuinely tell when a sound is behind, above, or below them. On speakers, the effect is less pronounced because the room's acoustics interfere. For web games, default to "equalpower" for broad compatibility and offer an "HRTF" option in audio settings for headphone users.

The computational cost of HRTF is significant. Each HRTF-processed source requires convolution with an impulse response at the current source angle, which is expensive per-source. On mobile, limit HRTF sources to 4-8 simultaneous sounds. On desktop, 16-24 is typically comfortable. Always profile on your target devices.

Sound Cones

PannerNodes support directional sound through cone parameters. A sound with a defined cone radiates primarily in one direction, like a speaker facing forward. The coneInnerAngle defines the full-volume cone in degrees. coneOuterAngle defines where the volume starts falling off. coneOuterGain sets the volume outside the outer cone (0 for complete silence, or a small value for muffled audio).

Practical uses include PA system speakers (sound only in front), NPC dialogue (louder when facing the player), directional alarms (loud in the hallway, muffled through walls), and vehicle engines (louder behind the exhaust). Set the cone's direction using the PannerNode's orientationX/Y/Z properties, updated each frame to match the game object's facing direction.

Reverb Zones

Spatial audio becomes truly immersive when combined with environment-dependent reverb. A footstep in a bathroom sounds different from the same footstep in an open field. The Web Audio API's ConvolverNode applies convolution reverb using impulse response recordings of real or synthetic spaces.

Load impulse response files (typically .wav recordings under 2 seconds long) and create a ConvolverNode with the decoded buffer. Route sounds through the ConvolverNode to apply the reverb effect. Use a wet/dry mix (two parallel paths: one direct, one through the convolver, each with independent GainNodes) to control the reverb intensity.

Define reverb zones in your game world. When the player enters a cave, crossfade the reverb wet/dry mix to increase reverb. When they exit to an open area, reduce it. For games with distinct rooms, swap the ConvolverNode's buffer when the player moves between spaces, crossfading during the transition.

Free impulse response libraries include the OpenAIR database and the EchoThief collection, which provide recordings of real spaces from small bathrooms to concert halls. For game purposes, short impulse responses (0.5-1.5 seconds) are the most practical, as longer responses consume more CPU per active sound source.

Key Takeaway

Use PannerNode and AudioListener for 3D games to get automatic positioning, distance attenuation, and optional HRTF. Use StereoPannerNode for 2D games with manual distance calculations. Only spatialize gameplay sounds, not music or UI. Combine with ConvolverNode reverb zones for immersive environments.