We have a new shiny API to play sounds in Castle Game Engine!
I think it’s a major improvement over the previous API (that revolved around TSoundBuffer
and TSound
classes). The new API is easier to use:
- It hides some internal constraints (a limited internal number of sounds that can be mixed simultaneously, or impossibility to change internal buffer contents/streaming after loading). You don’t need to care about that anymore.
-
The lifetime of instances is easier to grasp. You control the lifetime of everything, and there’s no need to deal with
TSound.OnRelease
.
The new API is also perfect to visually set things up in the CGE editor. It uses behaviors for spatial sounds.
The new classes, that you should use now for all sound loading and playing, are:
-
TCastleSound: The most important class, you should use this always when you want to play any sound.
This is a new non-visual component that represents a sound file with some playback parameters. The most important properties are:
-
URL — undoubtedly the most important property, set this to actually load the sound file.
-
Stream — optionally use “streaming”, which is an alternative loading method best suited for longer playing sounds (like music tracks).
-
Volume — how loud the sound is. This is multiplied by volume at
TCastlePlayingSound.Volume
andTCastleSoundSource.Volume
and by spatial calculations. -
Pitch — sound playing speed. As with volume, the volume of
TCastleSound.Pitch
is multiplied by similar parameters controlled atTCastlePlayingSound.Pitch
andTCastleSoundSource.Pitch
.
TCastleSound
by itself doesn’t manage playing the sound. You have to use SoundEngine.Play to play the sound (the simplest way to play, for non-spatial sounds) or TCastleSoundSource (for sounds that can be spatial; assign to TCastleSoundSource.Sound for looping, use TCastleSoundSource.Play for non-looping).TCastleSound
also replaces previousTSoundType
(TSoundType
is now an alias ofTCastleSound
). So reading sounds fromsounds.xml
file and using SoundEngine.SoundFromName just gives you readyTCastleSound
instance. This XML file now becomes a new way to define “a list of TCastleSound instances”. Though you can also now ditch the manually-crafted XML files, and use a new approach we mention below — design a non-visual collection of components likeall_sounds.castle-component
. -
-
TCastleSoundSource: A way to play spatial (3D) sounds.
This is a behavior (see previous post) that enhances any TCastleTransform so that it emits (possibly spatial) sounds.
TCastleSoundSource
refers toTCastleSound
for an actual sound information. You can set TCastleSoundSource.Sound (for looping). Or call TCastleSoundSource.Play (for non-looping). -
TCastlePlayingSound: Optional, use if you need more control before and during the sound playback.
Both TCastleSoundSource
and TCastleSound
can be created, configured and linked in the CGE editor, e.g. when designing your state. You can hear the 3D sounds in the editor. You can also create and control them from code, as all CGE components.
All CGE examples have been upgraded to use the new approach for sounds.
- See all the examples in examples/audio subdirectory.
-
In particular I recommend opening the examples/audio/game_3d_sound demo. Aside from using new sound API, it has also been recently upgraded to use CGE editor and glTF intensively.
-
See also examples/fixed_camera_game for a new approach to design a collection of sounds (a new, better approach than manually crafting XML files). In particular:
-
examples/fixed_camera_game/data/sounds/all_sounds.castle-component
describes all sounds -
examples/fixed_camera_game/code/gamesound.pas
loads them
-
Editor sound features:
- Sound volume, and “auto-mute on play” are now available in the editor settings.
-
Drag-and-drop sound files on the viewport to automatically create a spatial sound:
TCastleTransform
,TCastleSoundSource
,TCastleSound
. -
You can manage a collection of sounds independent of state/UI by simply using
TCastleComponent
as a design root and addingTCastleSound
children. Save the resulting design to a file likeall_sounds.castle-component
. This is a great alternative to previous XML files to describe sounds which will soon be deprecated most likely.You can see an example of using the new approach in examples/fixed_camera_game mentioned above.
Distance model changes:
-
Our previous default SoundEngine.DistanceModel was poor (linear, which is not realistic).
Now it is dmInverse, and corresponds to FMOD default and OpenAL default. It’s the most natural model to play 3D spatial sounds.
-
Our default MaxDistance was poor (1, equal
ReferenceDistance
, which means that there’s no attenuation with linear model at all).Now MaxDistance is 10000 by default (like FMOD). ReferenceDistance remains 1 by default (just like in OpenAL and FMOD).
-
Our possible TSoundDistanceModel were not portable (they reflected OpenAL models closely, and did not reflect FMOD models).
We limit ourselves now to actually useful models, supported by various sound backends (OpenAL and FMOD) now:
dmInverse
anddmLinear
.
Backward compatibility:
The sound API upgrade described here is almost completely backward-compatible. Old classes still work, just make a warning about deprecation at compilation. The breaking changes are:
-
By default we use
dmInverse
model now, as it is much more natural for 3D sounds (and it is default in both OpenAL and FMOD too, for the same reason). If you want the same approach as in previous engine version, setSoundEngine.DistanceModel := dmLinear
. Remember to adjust theTCastleSound.MaxDistance
to sound good. -
Our sounds XML file no longer supports “random aliases”. See the bottom of upgrading wiki page for explanation. I suppose it was quite obscure feature, not used by many, and maintaining it is just too much cost in new API. If you miss this feature, I released a small unit that allows you to bring it back into your game: use and adjust this in your projects.
We also made a fix for sounds defined in X3D files: 3D sounds defined using X3D nodes are now correctly played in world coordinates, i.e. loading an X3D scene with sounds inside TCastleScene
, and then transforming this TCastleScene
makes a proper sound effect.
Our manual chapter about sound has also been updated to reflect the information above. It’s admittedly very brief now, quite similar to this news post, but I hope to extend it into more tutorial-like description soon.