16. Sound

As with many other operations, you can add and control sounds to your game either by ObjectPascal code, or by editing your data files. This gives flexibility both to a programmer and the content designer. It's your choice which approach you use — usually it's better to keep as much as possible in data files, and use ObjectPascal only when necessary for non-trivial situations.

Loading and playing sound inside VRML/X3D

First, get a sample sound file and place it within your game data. You can find some sample files inside examples/fps_game/data/sounds/, or in our demo VRML/X3D models (subdirectory sound/), or on websites like OpenGameArt.org.

To add a looping sound to your VRML/X3D file in classic encoding (xxx.x3dv files) add this:

Sound {
  source AudioClip { url "sample.wav" loop TRUE }

Remember that URL "sample.wav" is specified relative to the location of your xxx.x3dv file. In the simplest case, just place both xxx.x3dv and sample.wav in the same directory, and you're fine.

Loading and playing sound inside ObjectPascal code

To play a sound using direct code, do this:

// add this to your uses clause:
uses ..., CastleSoundEngine;
// use this at initialization:
  Buffer: TSoundBuffer;
procedure LoadSoundBuffers;
  Buffer := SoundEngine.LoadBuffer(ApplicationData('sample.wav'));
// during the game, call this to play a sound:

See SoundEngine.PlaySound docs for the description of parameters.

You can free the buffer once the sound has stopped. It's not important for simple programs, as we will take care to always free it before closing OpenAL context.

Sounds repository

Larger games may find it comfortable to define a repository of sounds. You do it by creating an XML file, for example named sounds.xml, looking like this:

<?xml version="1.0"?>
  <sound name="sample" url="sample.wav" />
  <!-- Actually, you can omit the url, by default it's the same
    as sound name with .wav extension. -->

See creating game sounds guide for detailed specification about sound XML files. See TRepoSoundEngine docs and examples/fps_game/ for example. You have to initialize the sound repository inside your game code like this:

SoundEngine.RepositoryURL := ApplicationData('sounds/index.xml');

After this, you can refer to your sound names from files like resource.xml (for creatures/items sounds) or material_properties.xml (for footsteps) or level.xml (for level music). See creating game data guide for reference of these files.

You can also play named sounds from ObjectPascal code:

  SoundType: TSoundType;
  SoundType := SoundEngine.SoundFromName('sample');
  SoundEngine.Sound3D(SoundType, Vector3Single(1, 2, 3), false { looping });
  SoundEngine.Sound(SoundType, false { looping }); // non-3D sound

The SoundEngine.Sound3D and SoundEngine.Sound are a little easier to use than SoundEngine.PlaySound, they have fewer parameters. That is because the default sound properties (it's individual gain, importance (priority), URL and other stuff) is already recorded in the sounds XML file. That's one advantage of using the sounds repository: all your sounds properties are centrally stored in the sounds XML file.


For more advanced uses, you can use the return value of SoundEngine.PlaySound, SoundEngine.Sound3D or SoundEngine.Sound. It's either nil (if no OpenAL resources were available to play this sound, and it's priority doesn't allow overriding other sounds) or it's a TSound instance. If you have TSound instance, you can save it to a variable and use for various purposes. For example you can update sound parameters during the game, e.g. changing TSound.Position, TSound.Gain and such. You can use it's TSound.OnRelease event to be notified when source stops playing. You can stop playing the sound by TSound.Release.

Predefined sounds

Some engine components already define some sound names. To make them defined, just use the appropriate names in your sounds XML file described above. They will be automatically found and played by engine components.

See "Common sounds" section in CastleSoundEngine unit sources for a current list of predefined sound names.