bw logo

Chapter 5. FMOD

FMOD is a third party library for music and sound effects by Firelight Technologies (www.fmod.org). BigWorld provides sound support via the FMOD sound library. A license to use FMOD is not included with BigWorld. Thus in order to release a title using FMOD, a separate licensing agreement with Firelight Technologies needs to be entered into.

Whilst FMOD is enabled in BigWorld Fantasy Demo, it is disabled in the shipped source by default. To enable FMOD, edit bigworld/src/lib/fmodsound/fmod_config.hpp and set FMOD_SUPPORT to 1 and rebuild the client. If FMOD support has been disabled, the FMOD Python module will still be available, however none of the function calls will succeed.

This documentation provides an overview of how to use the FMOD sound features exposed by BigWorld Technology, which is essentially a thin interface to the FMOD Designer API. For documentation related to general FMOD design principles and sound issues, please see the FMOD documentation itself.

The features exposed by the engine are:

  • Loading of one more more sound banks (preloaded or streamed).

  • Playback of 2D and 3D sound events.

  • Remotely connecting to the BigWorld client using the FMOD Designer in order to tweak event parameters in real time and view profiling metrics.

  • Spatial reverb using reverb presets as defined in the FMOD Designer.

  • Access to the FMOD dynamic music system.

5.1. Overview

5.1.1. Sound Engine Configuration

High level settings can be configured by editing the soundMgr section in the engine_config.xml file. Fantasy Demo provides an engine configuration file which can be used as an example.

The following is a list of available settings.

5.1.1.1. enabled

This controls whether sound support is enabled. When this is set to false, the SoundManager will not be initialised on startup.

5.1.1.2. errorLevel

This can be set to either 'silent', 'warning', or 'exception' to control what happens when FMOD calls (such as Entity.playSound or FMOD.playSound) hit an error.

5.1.1.3. channels

Defines the number of virtual channels to be made available to FMOD. Please see the FMOD documentation for EventSystem::init for a detailed description on channels.

5.1.1.4. mediaPath

The directory inside the res tree where your sound banks reside. Note that FMOD requires that all your sound banks be in the same directory, and so only the first directory in your res path that matches the <mediaPath> will be used for loading sounds.

5.1.1.5. soundBanks

This defines the sound banks to be made available, and which will be preloaded when the engine starts up. This section is made up of one or more project tags. The schema for each project tag is:

<project>
    <name> project_name </name>
    <preload> true|false </preload>
</project>

The project name is the name of the .fdp file located in the mediaPath excluding the extension.

If preload is set to true, then the sound bank will be registered on startup. If it is set to false, then it will only be registered when requested by the BigWorld.loadSoundBankIntoMemory Python API.

5.1.1.6. networkUpdates

Enables/disables whether or not the FMOD Designer tool can connect to the client and make live updates to properties on existing sound events. This is always disabled on consumer release builds.

5.1.1.7. enableProfiler

Enables/disables external access (using FMOD Designer or FMOD Profiler) to view, in real-time, information such as memory usage, CPU usage and the DSP network graph in. This is always disabled on consumer release builds.

5.1.1.8. maxSpeed

This controls the maximum speed for 3D sounds. If the speed exceeds this value, then the sound system will assume the sound source has been teleported. This prevents audio glitches from excessive changes in object speeds, you should set this value to some realistic maximum for your application. If any 3D sound source exceeds this speed the Doppler effect will be zero.

5.1.2. Python API

The FMOD API can be accessed from Python by importing the FMOD module. See the client Python API documentation for a description of what is available in this module.

5.1.2.1. Backwards compatability

For backwards compatability with previous versions of BigWorld, the FMOD module will alias legacy sound functions into the BigWorld module (e.g. FMOD.playSound is the same as calling BigWorld.playSound). To make sure this function aliasing occurs as early as possible, be sure to import the FMOD module at the top of your personality script.

Since these older API functions will be deprecated, we encourage you to use the new FMOD module.

5.2. Loading Sound Banks

To implement sounds in your game, an FMOD sound bank needs to be created using the FMOD Designer tool. A very small example sound bank project is provided, and is located at fantasydemo/audio/fd_sound.fdp. Please see the documentation for FMOD Designer for details on how to create and edit your own sound banks.

Sound banks must be specified in the engine configuration XML file. Multiple sound bank projects can be specified, and can be configured to load on client startup or only by request from the scripts. See Sound Engine Configuration for more detail on this.

Note

If an FMOD sound bank has been configured to stream from disk, it cannot be packed within a zip file system and must reside within an operating system directory.

5.3. Sound Playback

BigWorld provides easy to use functions for playing back sound events defined by the FMOD Designer tool.

See the Client Python API documentation for more details on these functions and the FMOD.Sound object.

5.3.1. Supported Max Playback types

The FMOD Event system provides a variety of max playback behaviour modes. These determine the behvaiour when the maximum number of instances of an event have been generated and then another is requested. The following max playback behaviours are recommended when designing sound events for use with the BigWorld FMOD integration.

Please see the FMOD Designer documentation for more detailed information on these settings.

5.3.1.1. Steal Oldest

Suitable for short sounds (e.g. gun shots or foot steps), this will steal the oldest instance of the event that is currently playing back.

5.3.1.2. Steal Quietest

Suitable for short sounds (e.g. gun shots or foot steps), this will steal the quietest instance of the event that is currently playing back (unless the new instance is the quietest).

5.3.1.3. Just Fail If Quietest

Suitable for longer sounds like ambiences or loops, this playback type causes the next attempt to playback that event will fail if it's the quietest, once the maximum number of concurrent instances of a sound event has been reached. If it is not the quietest, it will succeed by stealing the handle from the quietest instance. The SoundManager will update all these events each frame so that only the quietest ones will be virtual.

In other words, JFIQ ensures that the loudest N instances of the event are audible at any point in time, where N is the max playbacks property of that event. Loudness is determined by the distance from the listener as well as any sound cone/listener angle effects and occlusion geometry. When an event is set to have the behaviour 'just fail if quietest' there is no limit to the number of Sounds which can be placed in the world using that event. Calling the following methods on Sounds which are virtual will return errors: volume, pitch, paused, muted, duration. There is an isVirtual method provided to check if a Sound is virtual or not.

An example of when to use JFIQ would be if you have 100 torches crackling in a room you would only need to hear a few of the nearest (loudest) torches to get the desired effect.

5.3.2. Sound Playback Functions

  • For 2D sound events (e.g. GUI sounds), use FMOD.playSound and pass in the full path to the desired sound event (e.g. "ui/boop"). It returns an FMOD.Sound object representing the sound event being played.

  • For 3D sounds, use:

    • PyModel.playSound, which will play a sound at the location of the model (it will track the model's current position). It will return an FMOD.Sound object representing the sound event being played.

    • FMOD.getSound to retrieve an FMOD.Sound handle, set its position attribute, and then call its play method directly. This technique has the disadvantage that it will not take advantage of the FMOD channel virtualisation features, as a single FMOD.Sound object represents a single virtual sound instance.