Firelight Technologies FMOD Studio API
Virtual Voice System
Introduction
FMOD Low Level API includes an efficient virtual voice system. FMOD Studio API adds another layer of control on top of that with event polyphony. The following sections describe how best to take advantage of the virtual voice system.
Low Level Virtual Voices
FMOD Low Level includes a virtual voice system. It allows the developer to play hundreds or even thousands of sounds at once, but only have a small number actually producing sound. For example a dungeon may have 200 torches burning on the wall in various places but only the loudest will be really playing. FMOD will dynamically make voices virtual or real depending on real time audibility. A sound which is playing far off or with a low volume will become virtual, but will change to a real voice when it comes closer or becomes louder due to Channel or ChannelGroup API calls.
Audibility Calculation
The virtual voice system automatically takes into account the following when calculating audibility:
- The priority of the channel. See the "Peak Volume" section for more information.
- The underlying sound peak volume if available. See the "Sound Priority" section for more information.
- The volume of the channel and any parent channel group, set via ChannelControl::setVolume.
- The volume of any applied fade points, set via ChannelControl::addFadePoint.
- Whether the channel is paused or muted.
- The effect of any DSP sends and returns, including the send volume.
- The distance effect for DSP panners.
- Any DSP that exposes FMOD_DSP_PARAMETER_DATA_TYPE_OVERALLGAIN will contribute to audibility.
The audibility calculation will take into account the hierarchy of ChannelGroups. If a DSP is added to a parent ChannelGroup that exposes a gain parameter, then that will affect all the audibility of all Channels that are children of that ChannelGroup directly or indirectly.
A Channel can be queried for whether it is virtual with the Channel::isVirtual function. When going virtual, the sound's time will still be ticked and any fade points will still continue to interpolate. Any additional DSPs attached to the channel will be preserved. When the channel becomes real again, it will resume as if it had been playing properly.
Peak Volume
Peak volume is available for sounds that are exported via FSBank as long as the "Write peak volume" option is enabled. FMOD Studio tool always enables this flag when exporting banks, so FMOD Studio sounds will always have a peak volume. If the peak volume is not present (such as a loose wav file), then the sound will treated as if it had full volume.
Sound Priority
FMOD provides a simple and powerful way of controlling which voices go virtual, by using a channel priority. Channel priority set with Channel::setPriority or Sound::setDefaults, where a smaller integer value corresponds to a higher (more important) priority. If a sound is a higher priority than another, then it will always take precedence regardless of its volume, distance, or gain calculation. Channels with a high priority will never be stolen by those with a lower priority, ever. The only time a channel with a high priority will go virtual is if other channels with an equal or even higher priority are playing, or if FMOD_INIT_VOL0_BECOMES_VIRTUAL has been specified and the sound is effectively silent.
Important sounds should have higher priority and it is up to the user to decide if some sounds should be more important than others. An example of an important sound might be a 2D menu or GUI sound or beep that needs to be heard above all other sounds. Avoid using too many priority levels in a fine-grained way. If a sound has a higher priority it will never be stolen, even if it is very quiet compared to a lower priority sound.
VOL0 Virtual
An important part of the virtual voice system is the FMOD_INIT_VOL0_BECOMES_VIRTUAL flag. When this flag is enabled, channels will automatically go virtual when their audibility drops below the limit specified in the FMOD_ADVANCEDSETTINGS vol0virtualvol field. This is useful to remove sounds which are effectively silent, which is both a performance and quality improvement. Since it is only removing silent sounds, there should be no perceived difference in sound output when enabling this flag.
It is strongly recommended that FMOD_INIT_VOL0_BECOMES_VIRTUAL is specified in System::init or Studio::System::initialize, and that the vol0virtualvol field is set to a small non-zero amount, such as 0.001. For users of FMOD Studio API, System::setAdvancedSettings can be called by getting the Studio::System::getLowLevelSystem after Studio::System::create but before Studio::System::initialize.
Software Voices vs Virtual Voices
To set the number of virtual voices FMOD will use, call System::init with the number of virtual voices specified in the maxchannels parameter. To set the number of software mixed channels available, use System::setSoftwareChannels. A further limit is available per codec by using FMOD_ADVANCEDSETTINGS.
If the virtual voice limit is hit then Channels will be stolen and start returning FMOD_ERR_INVALID_HANDLE. Channels which have had their handle stolen in this way are permanently stopped and will never return.
Assuming the number of playing Channels is below the maximum virtual voice limit, then the channel handle will remain valid, but the Channel may be virtual or real depending on audibility. The maximum number of real playing channels will be the limit set by setSoftwareChannels, or the limits of the codecs set with FMOD_ADVANCEDSETTINGS.
For typical games, it is reasonable to set the maxchannels value of System::init to some high value, from a few hundred up to a thousand or more. The number of real software channels is often set lower, at anywhere from 32 to 128. This allows the game to create and keep track of a large number of Channels, but still limit the CPU cost by having a small number actually playing at once.
Virtual to Real Transition
The way the virtual voice system works is that when sounds become real they resume from their proper place, halfway through the sound. To change this behaviour, you can either use Sound or Channel priorities to stop it going virtual in the first place, or you have the option to have a voice start a from the beginning instead of half way through, by using the FMOD_VIRTUAL_PLAYFROMSTART flag with System::createSound, System::createStream, Sound::setMode or Channel::setMode.
As described above, only the quietest, least important sounds should be swapping in and out, so you shouldn't notice sounds 'swapping in', but if you have a low number of real voices, and they are all loud, then this behaviour could become more noticable and may sound bad.
Another option is to simply call Channel::isVirtual and stop the sound, but don't do this until after a System::update! After System::playSound, the virtual voice sorting needs to be done in System::update to process what is really virtual and what isn't.
FMOD Studio API Voice Control
FMOD Studio API provides further ways of limiting playing voices on top of the system provided by the Low Level, by using event polyphony. The sound designer can specify a limit to the number of simultaneously playing instances of an event at once. There are currently two modes for event polyphony - voice stealing on or off.
Event Polyphony with Voice Stealing On
In this mode, once more instances are playing than the limit, then some will become virtual. Whether an event has become virtual can be queried with Studio::EventInstance::isVirtual. A virtual event will mute its master channel group, which will cause any playing Channels to go virtual if FMOD_INIT_VOL0_BECOMES_VIRTUAL has been specified. Event virtualization is determined by the following factors:
- Instance volume set via Studio::EventInstance::setVolume.
- Master track volume set in FMOD Studio, including automation and modulation.
- Attenuation from the event's 3D panner.
An event which is virtual may become real at a later time if the audibility increases compared to the other playing instances.
Event Polyphony with Voice Stealing Off
In this mode, once the instance limit has been met, further instances will not play. Instances can still be created, and Studio::EventInstance::start can be called, but they will not actually play. Querying Studio::EventInstance::getPlaybackState will show that the extra instances are not in the playing state. Once instances fail to play then they will not start at a later time, regardless of what happens to the other instances. In this mode, event audibility has no affect on which instances play, it is simply based on which had Studio::EventInstance::start called first.
Interaction with Low Level Virtual Voice System
FMOD Studio events will ultimately create one or more low level Channel objects to play sound. These Channels can go real or virtual based on the max software channels set at initialization time. Therefore it is possible to have events where Studio::EventInstance::isVirtual is false, but some or all of the underlying Channels are virtual due to the software channel limit. The Low Level voice system will correctly take into account the bus set-up, distance attenuation, volume settings, and other DSP effects on Studio buses.
Studio Events can affect the Low Level Virtual Voice selection system with the priority value controlled per-event in the FMOD Studio tool. Any Channels created by an Event will have the priority value exported from the FMOD Studio Tool. Unlike the Low Level API, the Studio tool only exposes 5 different values. This is done deliberately, since priority should not be used in a fine-grained way. Keep in mind that a higher priority voice will never be stolen by a lower priority voice, even if it is very quiet.
Another factor to keep in mind is that Event Priority is not inherited for nested events. It is possible to have a very high priority event that has a bunch of low priority nested events. In that case, the sounds may not play even though ultimately the parent event is set to a high priority.
Low Level Profiler
The FMOD Low Level profiler tool displays the DSP graph, and can be used to quickly see which channels have gone virtual. Consider the Channel Groups Example. If we add FMOD_INIT_PROFILE_ENABLE and add a call to System::setSoftwareChannels with 5, then we see one of the 6 channels has gone virtual: