RythmGame/SimpleGame/fmodstudioapi20307linux/doc/FMOD API User Manual/white-papers-virtual-voices.html
2025-06-10 17:40:16 +02:00

115 lines
23 KiB
HTML

<html>
<head>
<title>White Papers | Virtual Voices</title>
<link rel="stylesheet" href="style/docs.css">
<link rel="stylesheet" href="style/code_highlight.css">
<script type="text/javascript" src="scripts/language-selector.js"></script></head>
<body>
<div class="docs-body">
<div class="manual-toc">
<p>FMOD Engine User Manual 2.03</p>
<ul>
<li><a href="welcome.html">Welcome to the FMOD Engine</a></li>
<li><a href="studio-guide.html">Studio API Guide</a></li>
<li><a href="core-guide.html">Core API Guide</a></li>
<li><a href="platforms.html">Platform Details</a></li>
<li class="manual-current-chapter manual-inactive-chapter"><a href="white-papers.html">White Papers</a><ul class="subchapters"><li><a href="white-papers-getting-started.html">Getting Started</a></li><li><a href="white-papers-3d-reverb.html">3D Reverb</a></li><li><a href="white-papers-3d-sounds.html">3D Sounds</a></li><li><a href="white-papers-asynchronous-io.html">Asynchronous I/O</a></li><li><a href="white-papers-cpu-performance.html">CPU Performance</a></li><li><a href="white-papers-dsp-architecture.html">DSP Architecture and Usage</a></li><li><a href="white-papers-dsp-plugin-api.html">DSP Plug-in API</a></li><li><a href="white-papers-handle-system.html">Handle System</a></li><li><a href="white-papers-memory-management.html">Memory Management</a></li><li><a href="white-papers-non-blocking-sound-creation.html">Non-blocking Sound Creation</a></li><li><a href="white-papers-spatial-audio.html">Spatial Audio</a></li><li><a href="white-papers-studio-3d-events.html">Studio API 3D Events</a></li><li><a href="white-papers-studio-threads.html">Studio API Threads</a></li><li><a href="white-papers-threads.html">Threads and Thread Safety</a></li><li><a href="white-papers-transitioning-from-fmodex.html">Transitioning from FMOD Ex</a></li><li><a href="white-papers-using-multiple-reverbs.html">Using Multiple Reverbs</a></li><li class="manual-current-chapter manual-active-chapter"><a href="white-papers-virtual-voices.html">Virtual Voices</a></li></ul></li>
<li><a href="studio-api.html">Studio API Reference</a></li>
<li><a href="core-api.html">Core API Reference</a></li>
<li><a href="fsbank-api.html">FSBank API Reference</a></li>
<li><a href="plugin-api.html">Plug-in API Reference</a></li>
<li><a href="effects-reference.html">Effects Reference</a></li>
<li><a href="troubleshooting.html">Troubleshooting</a></li>
<li><a href="glossary.html">Glossary</a></li>
</ul>
</div>
<div class="manual-content api">
<h1>5. White Papers | Virtual Voices</h1>
<div class="toc">
<ul>
<li><a href="#virtual-voice-system">Virtual Voice System</a><ul>
<li><a href="#core-api-virtual-channels">Core API Virtual Channels</a><ul>
<li><a href="#audibility-calculation">Audibility Calculation</a></li>
<li><a href="#peak-volume">Peak Volume</a></li>
<li><a href="#sound-priority">Sound Priority</a></li>
<li><a href="#vol0-virtual">VOL0 Virtual</a></li>
<li><a href="#software-channels-vs-virtual-channels">Software Channels vs Virtual Channels</a></li>
<li><a href="#virtual-to-real-transition">Virtual to Real Transition</a></li>
</ul>
</li>
<li><a href="#studio-api-voice-control">Studio API Voice Control</a><ul>
<li><a href="#event-polyphony-with-channel-stealing-on">Event Polyphony with Channel Stealing On</a></li>
<li><a href="#event-polyphony-with-channel-stealing-off">Event Polyphony with Channel Stealing Off</a></li>
<li><a href="#interaction-with-core-api-virtual-voice-system">Interaction with Core API Virtual Voice System</a></li>
</ul>
</li>
<li><a href="#core-api-profiler">Core API Profiler</a></li>
</ul>
</li>
</ul>
</div>
<h2 id="virtual-voice-system"><a href="#virtual-voice-system">Virtual Voice System</a></h2>
<p>The Core API includes an efficient virtual voice system. The Studio API adds another layer of control on top of that with event polyphony. This white paper describes how best to take advantage of the virtual voice system.</p>
<h3 id="core-api-virtual-channels"><a href="#core-api-virtual-channels">Core API Virtual Channels</a></h3>
<p>The Core API includes a virtual voice system. It allows you 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. This is because the FMOD Engine dynamically makes <a class="apilink" href="core-api-channel.html">Channel</a>s virtual or real depending on their real time audibility, such that a sound which is playing far off or with a low volume becomes virtual, but changes back to being a real <a class="apilink" href="core-api-channel.html">Channel</a> when it comes closer or becomes louder due to <a class="apilink" href="core-api-channel.html">Channel</a> or <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a> API calls.</p>
<h4 id="audibility-calculation"><a href="#audibility-calculation">Audibility Calculation</a></h4>
<p>The virtual voice system automatically takes into account the following when calculating audibility:</p>
<ul>
<li>The priority of the <a class="apilink" href="core-api-channel.html">Channel</a>. See the "Sound Priority" section for more information.</li>
<li>The underlying peak volume if available. See the "Peak Volume" section for more information.</li>
<li>The volume of the <a class="apilink" href="core-api-channel.html">Channel</a> and any parent <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a>, set via <a class="apilink" href="core-api-channelcontrol.html#channelcontrol_setvolume">ChannelControl::setVolume</a>.</li>
<li>The volume of any applied fade points, set via <a class="apilink" href="core-api-channelcontrol.html#channelcontrol_addfadepoint">ChannelControl::addFadePoint</a>.</li>
<li>Whether the <a class="apilink" href="core-api-channel.html">Channel</a> is paused or muted.</li>
<li>The effect of any <a href="glossary.html#dsp">DSP</a> <a href="effects-reference.html#send">sends</a> and <a href="effects-reference.html#return">returns</a>, including the send volume.</li>
<li>The distance attenuation of <a href="effects-reference.html#pan">DSP panners</a>. This includes any 3D level customization of the <a class="apilink" href="core-api-channel.html">Channel</a> or parent <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a>s, set via <a class="apilink" href="core-api-channelcontrol.html#channelcontrol_set3dlevel">ChannelControl::set3DLevel</a>.</li>
<li>The overall gain reported by any DSP that exposes <a class="apilink" href="plugin-api-dsp.html#fmod_dsp_parameter_data_type_overallgain">FMOD_DSP_PARAMETER_DATA_TYPE_OVERALLGAIN</a>.</li>
<li>The effect of any occluding geometry, set via the <a href="core-api-geometry.html">Geometry API</a> or <a class="apilink" href="core-api-channelcontrol.html#channelcontrol_set3docclusion">ChannelControl::set3DOcclusion</a>.</li>
<li>The audibility calculation will take into account the hierarchy of <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a>s. If a DSP is added to a parent <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a> that exposes a gain parameter, then that will affect all the audibility of all <a class="apilink" href="core-api-channel.html">Channel</a>s that are children of that <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a> directly or indirectly. Child <a class="apilink" href="core-api-channel.html">Channel</a>s and <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a>s will not however affect the audibility of their parent <a class="apilink" href="core-api-channelgroup.html">ChannelGroup</a>.</li>
</ul>
<p>A <a class="apilink" href="core-api-channel.html">Channel</a> can be queried for whether it is virtual with the <a class="apilink" href="core-api-channel.html#channel_isvirtual">Channel::isVirtual</a> 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 <a class="apilink" href="core-api-channel.html">Channel</a> will be preserved. When the <a class="apilink" href="core-api-channel.html">Channel</a> becomes real again, it will resume as if it had been playing properly.</p>
<h4 id="peak-volume"><a href="#peak-volume">Peak Volume</a></h4>
<p>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 be treated as if it had full volume.</p>
<h4 id="sound-priority"><a href="#sound-priority">Sound Priority</a></h4>
<p>FMOD provides a simple and powerful way of controlling which <a class="apilink" href="core-api-channel.html">Channel</a>s go virtual, by using a <a class="apilink" href="core-api-channel.html">Channel</a> priority. <a class="apilink" href="core-api-channel.html">Channel</a> priority set with <a class="apilink" href="core-api-channel.html#channel_setpriority">Channel::setPriority</a> or <a class="apilink" href="core-api-sound.html#sound_setdefaults">Sound::setDefaults</a>, where a smaller integer value corresponds to a higher (more important) priority. If a <a class="apilink" href="core-api-channel.html">Channel</a> is a higher priority than another, then it will always take precedence regardless of its volume, distance, or gain calculation. <a class="apilink" href="core-api-channel.html">Channel</a>s with a high priority will never be stolen by those with a lower priority, ever. The only time a <a class="apilink" href="core-api-channel.html">Channel</a> with a high priority will go virtual is if other <a class="apilink" href="core-api-channel.html">Channel</a>s with an equal or even higher priority are playing, or if <a class="apilink" href="core-api-system.html#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> has been specified and the sound is effectively silent.</p>
<p>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.</p>
<h4 id="vol0-virtual"><a href="#vol0-virtual">VOL0 Virtual</a></h4>
<p>An important part of the virtual voice system is the <a class="apilink" href="core-api-system.html#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> flag. When this flag is enabled, <a class="apilink" href="core-api-channel.html">Channel</a>s 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.</p>
<p>It is strongly recommended that <a class="apilink" href="core-api-system.html#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> is specified in <a class="apilink" href="core-api-system.html#system_init">System::init</a> or <a class="apilink" href="studio-api-system.html#studio_system_initialize">Studio::System::initialize</a>, and that the <a class="apilink" href="core-api-system.html#fmod_advancedsettings_vol0virtualvol">FMOD_ADVANCEDSETTINGS::vol0virtualvol</a> field is set to a small non-zero amount, such as 0.001. If you're using the Studio API, <a class="apilink" href="core-api-system.html#system_setadvancedsettings">System::setAdvancedSettings</a> can be called by getting the <a class="apilink" href="studio-api-system.html#studio_system_getcoresystem">Studio::System::getCoreSystem</a> after <a class="apilink" href="studio-api-system.html#studio_system_create">Studio::System::create</a> but before <a class="apilink" href="studio-api-system.html#studio_system_initialize">Studio::System::initialize</a>.</p>
<h4 id="software-channels-vs-virtual-channels"><a href="#software-channels-vs-virtual-channels">Software Channels vs Virtual Channels</a></h4>
<p>To set the number of virtual <a class="apilink" href="core-api-channel.html">Channel</a>s FMOD will use, call <a class="apilink" href="core-api-system.html#system_init">System::init</a> with the number of virtual <a class="apilink" href="core-api-channel.html">Channel</a>s specified in the maxchannels parameter. To set the number of software mixed <a class="apilink" href="core-api-channel.html">Channel</a>s available, use <a class="apilink" href="core-api-system.html#system_setsoftwarechannels">System::setSoftwareChannels</a>. A further limit is available per codec by using <a class="apilink" href="core-api-system.html#fmod_advancedsettings">FMOD_ADVANCEDSETTINGS</a>.</p>
<p>If the virtual <a class="apilink" href="core-api-channel.html">Channel</a> limit is hit then <a class="apilink" href="core-api-channel.html">Channel</a>s will be stolen and start returning <a class="apilink" href="core-api-common.html#fmod_err_invalid_handle">FMOD_ERR_INVALID_HANDLE</a>. <a class="apilink" href="core-api-channel.html">Channel</a>s which have had their handle stolen in this way are permanently stopped and will never return.</p>
<p>Assuming the number of playing <a class="apilink" href="core-api-channel.html">Channel</a>s is below the maximum virtual <a class="apilink" href="core-api-channel.html">Channel</a> limit, then the <a class="apilink" href="core-api-channel.html">Channel</a> handle will remain valid, but the <a class="apilink" href="core-api-channel.html">Channel</a> may be virtual or real depending on audibility. The maximum number of real playing <a class="apilink" href="core-api-channel.html">Channel</a>s will be the limit set by <a class="apilink" href="core-api-system.html#system_setsoftwarechannels">System::setSoftwareChannels</a>, or the limits of the codecs set with <a class="apilink" href="core-api-system.html#fmod_advancedsettings">FMOD_ADVANCEDSETTINGS</a>.</p>
<p>For typical games, it is reasonable to set the maxchannels value of <a class="apilink" href="core-api-system.html#system_init">System::init</a> to some high value, from a few hundred up to a thousand or more. The number of real software <a class="apilink" href="core-api-channel.html">Channel</a>s is often set lower, at anywhere from 32 to 128. This allows the game to create and keep track of a large number of <a class="apilink" href="core-api-channel.html">Channel</a>s, but still limit the CPU cost by having a small number actually playing at once.</p>
<h4 id="virtual-to-real-transition"><a href="#virtual-to-real-transition">Virtual to Real Transition</a></h4>
<p>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 behavior, you can either use <a class="apilink" href="core-api-sound.html">Sound</a> or <a class="apilink" href="core-api-channel.html">Channel</a> priorities to stop it going virtual in the first place, or you have the option to have a <a class="apilink" href="core-api-channel.html">Channel</a> start from the beginning instead of half way through, by using the <a class="apilink" href="core-api-common.html#fmod_virtual_playfromstart">FMOD_VIRTUAL_PLAYFROMSTART</a> flag with <a class="apilink" href="core-api-system.html#system_createsound">System::createSound</a>, <a class="apilink" href="core-api-system.html#system_createstream">System::createStream</a>, <a class="apilink" href="core-api-sound.html#sound_setmode">Sound::setMode</a> or <a class="apilink" href="core-api-channelcontrol.html#channelcontrol_setmode">ChannelControl::setMode</a>.</p>
<p>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 <a class="apilink" href="core-api-channel.html">Channel</a>s, and they are all loud, then this behavior could become more noticeable and may sound bad.</p>
<p>Another option is to simply call <a class="apilink" href="core-api-channel.html#channel_isvirtual">Channel::isVirtual</a> and stop the sound, but don't do this until after a <a class="apilink" href="core-api-system.html#system_update">System::update</a>! After <a class="apilink" href="core-api-system.html#system_playsound">System::playSound</a>, the virtual <a class="apilink" href="core-api-channel.html">Channel</a> sorting needs to be done in <a class="apilink" href="core-api-system.html#system_update">System::update</a> to process what is really virtual and what isn't.</p>
<h3 id="studio-api-voice-control"><a href="#studio-api-voice-control">Studio API Voice Control</a></h3>
<p>In addition to the system provided by the Core API, the Studio API also allows you to limit playing <a class="apilink" href="core-api-channel.html">Channel</a>s by using event polyphony: The sound designer can specify a limit to the number of simultaneously playing instances of an event. There are two modes for event polyphony: <a class="apilink" href="core-api-channel.html">Channel</a> stealing on, and channel stealing off.</p>
<h4 id="event-polyphony-with-channel-stealing-on"><a href="#event-polyphony-with-channel-stealing-on">Event Polyphony with Channel Stealing On</a></h4>
<p>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 <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_isvirtual">Studio::EventInstance::isVirtual</a>. A virtual event will mute its master channel group, which will cause any playing <a class="apilink" href="core-api-channel.html">Channel</a>s to go virtual if <a class="apilink" href="core-api-system.html#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> has been specified.</p>
<p>Event virtualization is determined by an event's audibility, which is calculated based on the accumulated gain applied to the event's master track, as well any alterations applied to gain by fades, automation, and <a href="https://fmod.com/docs/2.03/studio/glossary.html#modulator">modulation</a>. This includes:</p>
<ul>
<li>Gain applied by <a href="glossary.html#effect">effects</a>.</li>
<li>The event's master track volume set in FMOD Studio.</li>
<li>Attenuation applied by <a href="https://fmod.com/docs/2.03/studio/glossary.html#spatializer-effect">spatializer effects</a>.</li>
<li>The volume level of sends, which are counted as gain for the purposes of the audibility calculation.</li>
<li>Instance volume set via <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_setvolume">Studio::EventInstance::setVolume</a>.</li>
</ul>
<p>Audibility is only calculated using the event's master channel group; the calculation does not include any gain applied to any child channels or channel groups.</p>
<p>An event which is virtual may become real at a later time if the audibility increases compared to the other playing instances.</p>
<h4 id="event-polyphony-with-channel-stealing-off"><a href="#event-polyphony-with-channel-stealing-off">Event Polyphony with Channel Stealing Off</a></h4>
<p>In this mode, once the instance limit has been met, further instances will not play. Instances can still be created, and <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_start">Studio::EventInstance::start</a> can be called, but they will not actually play. Querying <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_getplaybackstate">Studio::EventInstance::getPlaybackState</a> 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 <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_start">Studio::EventInstance::start</a> called first.</p>
<h4 id="interaction-with-core-api-virtual-voice-system"><a href="#interaction-with-core-api-virtual-voice-system">Interaction with Core API Virtual Voice System</a></h4>
<p>FMOD Studio events ultimately create one or more core <a class="apilink" href="core-api-channel.html">Channel</a> objects to play sound. These <a class="apilink" href="core-api-channel.html">Channel</a>s can go real or virtual based on the max software <a class="apilink" href="core-api-channel.html">Channel</a>s set at initialization time. Therefore, it is possible to have events where <a class="apilink" href="studio-api-eventinstance.html#studio_eventinstance_isvirtual">Studio::EventInstance::isVirtual</a> is false, but some or all of the underlying <a class="apilink" href="core-api-channel.html">Channel</a>s are virtual due to the software <a class="apilink" href="core-api-channel.html">Channel</a> limit. The Core API voice system takes into account the bus set-up, distance attenuation, volume settings, and other <a href="glossary.html#dsp-effect">DSP effects</a> on Studio buses.</p>
<p>Studio Events can influence and override the Core API's virtual voice selection system with the priority value controlled per-event in FMOD Studio. Any <a class="apilink" href="core-api-channel.html">Channel</a>s created by an event have the priority value set for their event in the FMOD Studio Tool - and a higher priority <a class="apilink" href="core-api-channel.html">Channel</a> can never be stolen by a lower priority <a class="apilink" href="core-api-channel.html">Channel</a>, even if it is very quiet. Unlike priorities set in the Core API, FMOD Studio only exposes five potential priority values. This is done deliberately, since priority should not be used in a fine-grained way.</p>
<p>Event Priority is not inherited for nested events. It is therefore possible for a high priority event to have low priority nested events. In such a case, the <a class="apilink" href="core-api-channel.html">Channel</a>s of the nested events may be virtualized, regardless of the parent event's high priority.</p>
<h3 id="core-api-profiler"><a href="#core-api-profiler">Core API Profiler</a></h3>
<p>The <a href="glossary.html#core-api-profiler-tool">Core API profiler tool</a> displays the <a href="glossary.html#dsp-graph">DSP graph</a>, and can be used to quickly see which <a class="apilink" href="core-api-channel.html">Channel</a>s have gone virtual. Consider the Channel Groups Example. If we add <a class="apilink" href="core-api-system.html#fmod_init_profile_enable">FMOD_INIT_PROFILE_ENABLE</a> and add a call to <a class="apilink" href="core-api-system.html#system_setsoftwarechannels">System::setSoftwareChannels</a> with 5, then we see one of the 6 <a class="apilink" href="core-api-channel.html">Channel</a>s has gone virtual:</p>
<p><img alt="Virtual DSP Graph" src="images/virtual-dspgraph.png" /></p></div>
<p class="manual-footer">FMOD Engine User Manual 2.03.07 (2025-04-02). &copy; 2025 Firelight Technologies Pty Ltd.</p>
</body>
</html>
</div>