Audio
Sound in the scene: sources that play clips, quieter and panned by distance from a listener, plus clips decoded from WAV files or synthesised in code.
module: awake:scene:audio
module: awake:core:audio
Playback: Desktop
awake:core:audio has clips, WAV decoding, a sound synthesiser and the AudioPlayer contract.
awake:scene:audio has the ECS side: AudioSource, AudioListener and AudioSystem. The scene
DSL functions live in awake:scene:authoring.
Make a clip
An AudioClip is uncompressed PCM in memory. Decode one from WAV bytes, however you load them:
val footstep = WavDecoder.decode(id = "footstep", name = "Footstep", bytes = bytes) // null if it is not an uncompressed PCM WAV
Or synthesise one:
val chime = SoundSynthesizer.build(id = "chime", name = "Chime") {
duration = 0.4f
waveform = Waveform.SINE
startFrequencyHz = 880f
endFrequencyHz = 660f
}
SoundSynthesizer.build also takes waveform (SINE, SQUARE, TRIANGLE, SAWTOOTH, NOISE),
an ADSR envelope, lowPassFilter and volume.
Add a sound source
A looping sound three metres to the side of a camera that hears it.
The scene runtime has no scene document component for audio yet. AwakeKt Studio saves an
audio_source component, but only Studio registers it. Use the scene DSL.
world.scene {
entity("camera") {
transform(z = 5f)
audioListener() // one per scene: spatial sounds are heard from here
}
entity("fountain") {
transform(x = 3f)
audioSource(chime, volume = 0.8f, maxDistance = 20f, loop = true)
}
}
sound(clip, name, volume, maxDistance) spawns a whole emitter entity in one call.
- In the Hierarchy, click Add entity and choose Audio: Audio Source.
- In the Inspector, pick the Audio Asset, then set Volume, Spatial 3D, Max Distance, Auto Play and Loop.
Studio's audio source starts with Auto Play off.
Play it
AudioSystem starts, positions and stops sources through an AudioPlayer:
val player: AudioPlayer = NoOpAudioPlayer() // JvmAudioPlayer() plays through Java Sound on desktop
val audio = AudioSystem(player)
audio.update(world, 1f / 60f) // autoPlay sources start on their first update
Register it as a per-frame system in an app, for example frameSystem("audio") { AudioSystem(player) }.
The player also plays music outside the ECS: playMusic(clip) and stopMusic(), with
masterVolume, sfxVolume and musicVolume to mix them.
Properties
| Property | Type | Default | What it does |
|---|---|---|---|
clip |
AudioClip |
required | The sound to play. |
volume |
number | 1 |
Volume, from 0 to 1. |
isSpatial3D |
boolean | true |
Fade with distance and pan by direction from the listener. Off plays at volume, centred. |
maxDistance |
number | 50 |
Beyond this distance a spatial sound is silent. |
autoPlay |
boolean | true |
Start on the first update. |
loop |
boolean | false |
Repeat until stopped. |
At run time AudioSource.isPlaying says whether it is playing, and stop() stops it.
How it works
Each update, AudioSystem finds the first entity with an AudioListener and a Transform, or uses
the origin if there is none. A spatial source's volume falls off with its distance from the listener
and reaches zero at maxDistance; its pan follows the listener's right-hand direction. A source whose
sound has finished drops its handle, and isPlaying turns false.
| Platform | AudioPlayer |
|---|---|
| Desktop | JvmAudioPlayer, through Java Sound. |
| Android | AndroidAudioPlayer, through AudioTrack. |
| Web | WebAudioPlayer, through Web Audio API. |
| iOS | Supply your own AudioPlayer, or use NoOpAudioPlayer. |
A spatial source out of range never auto-plays
autoPlay gets one attempt, on the first update. If the listener is beyond maxDistance
then, the player returns no sound and the source does not try again. Set hasAutoPlayed back to
false to retry, or place the source within range.
See also
- Physics contact events, for impact sounds.
- Large worlds, for streaming emitters with their cells.