Audio Resources#
This chapter explains how audio files become playable resources.
In Godot-FmodPlayer, the commonly used resource is FmodAudioStream. You can think of it as the Godot-side object that stores audio data and playback settings. When it is actually played, it creates a Sound under the hood and plays through a Channel managed by a player or by the system.
Choose a Loading Mode First#
There is one main choice: use Stream for long audio, and Sample for short sound effects.
Sound type |
Recommended mode |
Reason |
|---|---|---|
Background music |
|
The file is usually large, so reading while playing saves memory. |
Long narration or long ambience |
|
The playback time is long, so loading everything into memory is not ideal. |
UI sounds and button sounds |
|
The file is short and should respond quickly. |
Weapons, footsteps, and pickup sounds |
|
They may trigger frequently, so low latency matters more. |
Very short sounds that play only once |
Either can work |
Choose based on your project’s memory and latency needs. |
See also Stream and Sample for these concepts.
FmodAudioStream#
FmodAudioStream is the most commonly used audio resource class. It stores audio data and the creation mode, such as whether the sound streams, loads as a sample, or loops.
Common Creation Modes#
Flag |
Description |
|---|---|
|
Streams audio, suitable for music and long audio. |
|
Sample playback, suitable for short sound effects and low-latency playback. |
|
Loops playback. |
|
Bidirectional looping, similar to playing back and forth. |
These flags can be combined with |:
var flags := FmodAudioStream.MODE_STREAM | FmodAudioStream.MODE_LOOP
Load from a File#
Prefer res:// paths so exported projects stay consistent.
var music := FmodAudioStream.load_from_file(
"res://music/bgm.ogg",
FmodAudioStream.MODE_STREAM | FmodAudioStream.MODE_LOOP
)
var hit := FmodAudioStream.load_from_file(
"res://sfx/hit.wav",
FmodAudioStream.MODE_SAMPLE
)
After loading, you can assign it directly to a player:
@onready var music_player := $FmodAudioStreamPlayer
func _ready():
music_player.stream = music
music_player.bus = "Music"
music_player.play()
Load from Memory#
If audio comes from an encrypted package, the network, a save file, or your own loading flow, put the binary data into audio_data.
func load_from_bytes(data: PackedByteArray) -> FmodAudioStream:
var stream := FmodAudioStream.new()
stream.audio_data = data
stream.mode_flags = FmodAudioStream.MODE_SAMPLE
return stream
When using this method, keep the resource object alive while the sound is playing. Do not free the object that stores the data before playback finishes.
Preload Common Sound Effects#
Short sound effects are often played repeatedly. You can load them when the scene starts and reuse them later.
extends Node
var sfx := {}
func _ready():
sfx["hit"] = FmodAudioStream.load_from_file(
"res://sfx/hit.wav",
FmodAudioStream.MODE_SAMPLE
)
sfx["pickup"] = FmodAudioStream.load_from_file(
"res://sfx/pickup.wav",
FmodAudioStream.MODE_SAMPLE
)
func play_sfx(name: String):
if not sfx.has(name):
push_error("SFX not found: " + name)
return
var player := FmodAudioStreamPlayer.new()
add_child(player)
player.stream = sfx[name]
player.bus = "SFX"
player.play()
await get_tree().create_timer(3.0).timeout
player.queue_free()
If your project plays many overlapping short sound effects, you can go further and use a player object pool. For beginners, the approach above is easier to understand.
Background Music Playlist#
Music usually uses MODE_STREAM. Add MODE_LOOP when it needs to loop.
extends Node
@onready var player := $FmodAudioStreamPlayer
var tracks: Array[FmodAudioStream] = []
var current_index := 0
func _ready():
tracks.append(FmodAudioStream.load_from_file(
"res://music/track_0.ogg",
FmodAudioStream.MODE_STREAM
))
tracks.append(FmodAudioStream.load_from_file(
"res://music/track_1.ogg",
FmodAudioStream.MODE_STREAM
))
play_track(0)
func play_track(index: int):
current_index = index
player.stream = tracks[index]
player.bus = "Music"
player.play()
Query Audio Information#
FmodAudioStream can query length and access the underlying Sound.
func print_stream_info(stream: FmodAudioStream):
print("loaded: ", stream.is_data_loaded())
print("length: ", stream.get_length())
var sound := stream.get_sound()
if sound:
print("sound length: ", sound.get_length())
Normal playback usually does not require direct access to FmodSound. Get it only when you need lower-level information, callbacks, or special playback control.
Supported Formats#
Common formats include .wav, .ogg, .mp3, .flac, .aiff, and some module music formats such as .mod, .xm, .s3m, and .it.
Practical suggestions:
Prefer
oggormp3for music.Prefer
wavfor short sound effects.When seamless looping matters, test loop points with
oggorwavfirst.Always test special formats on the target platform before export.
Common Issues#
The first playback of a sound effect has latency#
Load short sound effects with MODE_SAMPLE and preload them before entering the scene.
Music uses too much memory#
Check whether the music was loaded with MODE_SAMPLE. Long music should usually use MODE_STREAM.
Looping does not work#
Make sure the creation mode includes MODE_LOOP:
stream.mode_flags = FmodAudioStream.MODE_STREAM | FmodAudioStream.MODE_LOOP
File cannot be found after packaging#
Prefer res:// paths and make sure the audio files are included by Godot’s export rules.
Recommendations#
Long music and long ambience:
MODE_STREAM.Short sound effects, UI sounds, and frequently triggered sounds:
MODE_SAMPLE.Load common short sound effects ahead of time to avoid a stall on first playback.
Use playback nodes first when possible. Touch Sound and Channel only when you need lower-level control.