Audio Sources

Learn how to use the AudioSource component to play sounds with volume, pitch, looping, and playback controls.

The AudioSource component enables entities to emit sounds. It supports both 2D ambient audio and 3D spatial audio with full control over playback parameters.

Component Properties#

PropertyTypeDefaultDescription
assetIdnumber0Asset ID of the audio clip to play. Assign from the Assets panel.
playingbooleanfalsePlayback state. Set to true to play, false to pause.
volumenumber1.0Volume level (0.0 to 1.0). Affected by channel mixer volumes.
pitchnumber1.0Playback speed multiplier (0.01 to 4.0). 1.0 is normal speed, 2.0 is double speed.
loopbooleanfalseWhether the sound should loop when it reaches the end.
spatialbooleantrueEnable 3D spatial audio. When false, plays as 2D ambient sound.
spatialBlendnumber1.0Blend between 2D (0.0) and 3D (1.0) audio. Intermediate values create hybrid sounds.
groupAudioChannelSFXAudio channel for routing: SFX (0), Music (1), or Voice (2).
refDistancenumber1.0Reference distance for volume rolloff. Sound is at full volume within this distance.
maxDistancenumber10000Maximum audible distance. Sound is inaudible beyond this distance.
rolloffFactornumber1.0Distance attenuation factor. Higher values make sound drop off faster.

Basic Playback#

To play a simple sound effect:

  1. Create an entity or select an existing one
  2. Add the AudioSource component
  3. Import an audio file and assign it to Asset ID
  4. Set Playing to true
  5. Adjust Volume if needed (0.0 to 1.0)

One-Shot vs Persistent

For one-shot sound effects (explosion, gunshot, footstep), use the SoundManager API from scripts instead of AudioSource. AudioSource is best for persistent, looping sounds like music or ambient effects.

Looping Audio#

Enable the loop property to make sounds repeat continuously:

import { AudioSource } from '@web-engine-dev/core';
// In your update loop or script
export default (api) => {
return {
onStart() {
// Set up looping background music
AudioSource.assetId[api.entity] = musicAssetId;
AudioSource.volume[api.entity] = 0.5;
AudioSource.loop[api.entity] = 1; // Enable looping
AudioSource.playing[api.entity] = 1; // Start playing
AudioSource.group[api.entity] = 1; // Music channel
}
};
};

Looping is perfect for:

  • Background music tracks
  • Ambient environmental sounds (wind, water, fire)
  • Engine sounds for vehicles
  • Continuous machinery or technology sounds

Volume and Pitch Control#

Volume#

The volume property controls the base volume level before channel mixing. The final volume is:

// Final volume calculation
finalVolume = source.volume
* channel.volume // SFX, Music, or Voice
* master.volume // Master volume
* (spatial ? distance attenuation : 1.0)
* (spatial ? LOD multiplier : 1.0);

Volume ranges from 0.0 (silent) to 1.0 (full volume):

  • 1.0 — Full volume (default)
  • 0.7 — Moderate volume (good for background music)
  • 0.5 — Half volume
  • 0.3 — Quiet ambient sounds
  • 0.0 — Muted

Pitch#

The pitch property controls playback speed, which affects both pitch and duration:

  • 2.0 — Double speed, one octave up, half duration
  • 1.5 — 1.5× speed, higher pitch
  • 1.0 — Normal speed (default)
  • 0.75 — Slow motion, lower pitch
  • 0.5 — Half speed, one octave down, double duration
// Randomize pitch for variation
const randomPitch = 0.9 + Math.random() * 0.2; // 0.9 to 1.1
AudioSource.pitch[entity] = randomPitch;
// Gradual pitch shift for engine sounds
const enginePitch = 0.5 + (speed / maxSpeed) * 1.5;
AudioSource.pitch[entity] = enginePitch;

Pitch Clamping

Pitch is clamped to the range 0.01 to 4.0 to prevent extreme values that could cause audio artifacts or performance issues.

Playback Timing#

Control when sounds start and stop by toggling the playingproperty:

export default (api) => {
let soundTimer = 0;
const soundInterval = 3.0; // Play every 3 seconds
return (dt) => {
soundTimer += dt;
if (soundTimer >= soundInterval) {
soundTimer = 0;
// Start playing
AudioSource.playing[api.entity] = 1;
// Stop after 1 second
setTimeout(() => {
AudioSource.playing[api.entity] = 0;
}, 1000);
}
};
};

2D vs 3D Audio#

The spatial property determines whether audio is affected by position and distance:

2D Audio (spatial = false)#

  • Plays at consistent volume regardless of position
  • No panning or distance attenuation
  • Perfect for UI sounds, music, and global effects
  • Lower CPU overhead than 3D audio

3D Audio (spatial = true)#

  • Volume decreases with distance from listener
  • HRTF panning for realistic directional audio
  • Requires AudioListener component on camera
  • Best for environmental sounds and world objects
// 2D UI button click sound
AudioSource.spatial[buttonEntity] = 0;
AudioSource.volume[buttonEntity] = 0.8;
AudioSource.playing[buttonEntity] = 1;
// 3D campfire sound
AudioSource.spatial[campfireEntity] = 1;
AudioSource.refDistance[campfireEntity] = 5.0;
AudioSource.maxDistance[campfireEntity] = 50.0;
AudioSource.loop[campfireEntity] = 1;
AudioSource.playing[campfireEntity] = 1;

Spatial Blend#

The spatialBlend property creates a hybrid between 2D and 3D audio by adjusting how much position affects the sound:

  • 0.0 — Pure 2D audio (no spatial effects)
  • 0.5 — Blend of 2D and 3D (subtle spatial effects)
  • 1.0 — Pure 3D audio (full spatial effects, default)
// Music that has subtle spatial positioning
// but doesn't fade out completely when far away
AudioSource.spatial[musicEntity] = 1;
AudioSource.spatialBlend[musicEntity] = 0.3; // Mostly 2D, slightly 3D
AudioSource.refDistance[musicEntity] = 1000; // Very large ref distance
AudioSource.maxDistance[musicEntity] = 2000;

Use Case

Spatial blend is useful for sounds that should have directionality but remain audible at long distances, like background music or ambient atmosphere.

Channel Routing#

Route audio to different mixer channels using the groupproperty:

  • SFX (0) — Sound effects, impacts, weapons, UI
  • Music (1) — Background music, themes
  • Voice (2) — Dialogue, narration, voice-overs
import { AudioChannel } from '@web-engine-dev/core';
// Sound effect
AudioSource.group[explosionEntity] = AudioChannel.SFX; // 0
// Background music
AudioSource.group[musicEntity] = AudioChannel.Music; // 1
// Character dialogue
AudioSource.group[dialogueEntity] = AudioChannel.Voice; // 2

Channel volumes can be controlled globally through the AudioMixer, allowing players to adjust SFX, Music, and Voice independently.

Best Practices#

  • Use SoundManager for one-shots — Play(), not AudioSource, for single-fire sounds
  • Pool your sounds — Reuse AudioSource entities instead of creating new ones
  • Set appropriate distances — Use realistic refDistance and maxDistance values
  • Choose the right channel — Route sounds to SFX, Music, or Voice appropriately
  • Adjust for gameplay — Lower volume for ambient sounds, higher for important cues
  • Test spatial audio — Move camera around to verify 3D positioning works correctly
  • Use pitch variation — Add randomness to avoid repetitive sounds
Audio | Web Engine Docs | Web Engine Docs