added the readme

This commit is contained in:
2026-06-08 17:07:34 -04:00
commit 6655fd2886
1001 changed files with 253651 additions and 0 deletions
@@ -0,0 +1,256 @@
<html>
<head>
<title>Core API Managing Resources</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="core-api-concepts.html">Core API Key Concepts</a></li>
<li><a href="running-the-core-api.html">Core API Getting Started</a></li>
<li><a href="loading-and-playing-sounds-in-the-core-api.html">Core API Loading and Playing Sounds</a></li>
<li><a href="spatializing-sounds-in-the-core-api.html">Core API Spatializing Sounds</a></li>
<li><a href="mixing-and-routing-in-the-core-api.html">Core API Mixing and Routing</a></li>
<li><a href="using-dsp-effects-in-the-core-api.html">Core API Using DSP Effects</a></li>
<li><a href="effects-reference.html">Core API Effect Reference</a></li>
<li class="manual-current-chapter manual-active-chapter"><a href="managing-resources-in-the-core-api.html">Core API Managing Resources</a><ul>
<li><a href="#virtual-voice-system">Virtual Voice System</a><ul>
<li><a href="#audibility-calculation">Audibility Calculation</a></li>
<li><a href="#peak-volume">Peak Volume</a></li>
<li><a href="#vol0-virtual">VOL0 Virtual</a></li>
<li><a href="#channel-priority">Channel Priority</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>
<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-the-core-api-virtual-voice-system">Interaction with the Core API Virtual Voice System</a></li>
</ul>
</li>
<li><a href="#core-api-profiler">Core API Profiler</a></li>
</ul>
</li>
<li><a href="#non-blocking-loads-threads-and-thread-safety">Non blocking loads, threads and thread safety</a><ul>
<li><a href="#thread-affinity">Thread Affinity</a></li>
<li><a href="#fmod-callback-types">FMOD Callback Types</a></li>
<li><a href="#core-api-thread-safety">Core API Thread Safety</a></li>
<li><a href="#studio-api-thread-safety">Studio API Thread Safety</a></li>
</ul>
</li>
<li><a href="#cpu-performance">CPU Performance</a><ul>
<li><a href="#compression-format">Compression Format</a></li>
<li><a href="#voice-limiting">Voice Limiting</a></li>
<li><a href="#tips-and-tricks">Tips and Tricks</a><ul>
<li><a href="#adjust-sample-rates">Adjust Sample Rates</a></li>
<li><a href="#increase-dsp-block-size">Increase DSP Block Size</a></li>
<li><a href="#reduce-speaker-channel-count">Reduce Speaker Channel Count</a></li>
<li><a href="#choose-inexpensive-dsps">Choose Inexpensive DSPs</a></li>
<li><a href="#take-advantage-of-hardware-decoding">Take Advantage of Hardware Decoding</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#custom-file-systems-and-memory-management">Custom File Systems and Memory Management</a></li>
<li><a href="#memory-management">Memory Management</a><ul>
<li><a href="#use-a-fixed-size-memory-pool">Use a Fixed-size Memory Pool.</a></li>
<li><a href="#lower-sound-instance-overhead">Lower Sound Instance Overhead.</a></li>
<li><a href="#use-compressed-samples">Use Compressed Samples</a></li>
<li><a href="#control-memory-usage-with-settings">Control Memory Usage with Settings</a></li>
<li><a href="#tracking-fmod-memory-usage">Tracking FMOD memory usage.</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="advanced-core-api-topics.html">Core API Advanced Topics</a></li>
<li><a href="core-api.html">Core API Reference</a></li>
<li><a href="studio-api-getting-started.html">Studio API Getting Started</a></li>
<li><a href="studio-guide.html">Studio API Guide</a></li>
<li><a href="studio-api-3d-events.html">Studio API 3D Events</a></li>
<li><a href="studio-api-threads.html">Studio API Threads</a></li>
<li><a href="studio-api.html">Studio API Reference</a></li>
<li><a href="platforms.html">Platform Details</a></li>
<li><a href="dsp-plugin-api-guide.html">Plug-in DSP API Guide</a></li>
<li><a href="plugin-api.html">Plug-in API Reference</a></li>
<li><a href="fsbank-api.html">FSBank API 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>9. Core API Managing Resources</h1>
<p>Measuring and tweaking performance is an important part of developing any application, and being able to scale FMOD from low power portable devices to the very latest in next gen consoles is key to our design. This chapter should give you a solid understanding of how to configure FMOD to fit within your audio budget, no matter which platforms you're targeting.</p>
<h2 id="virtual-voice-system"><a href="#virtual-voice-system">9.1 Virtual Voice System</a></h2>
<p>The Core API includes a 'virtual voice system.' This system allows you to play hundreds or even thousands of <a class="apilink" href="core-api-channel.html">Channel</a>s at once, but to only have a small number of them actually producing sound and consuming resources. The others are 'virtual,' emulated with a simple position and audibility update, and so are not heard and don't consume CPU time. For example: A dungeon may have 200 torches burning on the walls in various places, but at any given time only the loudest of these torches are really audible.</p>
<p>FMOD dynamically makes <a class="apilink" href="core-api-channel.html">Channel</a>s 'virtual' or 'real' depending on real time audibility calculations (based on distance/volume/priority/occlusion). A <a class="apilink" href="core-api-channel.html">Channel</a> which is playing far away or with a low volume becomes virtual, and may change back into a real <a class="apilink" href="core-api-channel.html">Channel</a> when it comes closer or 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>
<p>There are three situations in which a channel may become virtual:</p>
<ul>
<li><strong>The channel's audibility falling below the Vol0 Virtual threshold.</strong> This threshold represents the loudness below which a channel is not audible, and thus the threshold below which it may be automatically virtualized without audibly affecting the mix. For information about Vol0 Virtual, see the <a href="managing-resources-in-the-core-api.html#vol0-virtual">VOL0 Virtual</a> section of this chapter.</li>
<li><strong>The maximum number of software (i.e.: non-virtual) channels channels being exceeded.</strong> When this occurs, the software channel with the lowest priority is automatically virtualized. If multiple software channels share the lowest priority, the least audible of those channels is virtualized. For more information about exceeding the maximum number of software channels, see the <a href="managing-resources-in-the-core-api.html#software-channels-vs-virtual-channels">Software Channels vs Virtual Channels</a> section of this chapter.</li>
<li>If using the Studio API, the channel's event instance being stolen and that event instance's stealing behavior being "virtualize." For more information about Studio API voice control, see the <a href="managing-resources-in-the-core-api.html#studio-api-voice-control">Studio API Voice Control</a> section of this chapter.</li>
</ul>
<h3 id="audibility-calculation"><a href="#audibility-calculation">9.1.1 Audibility Calculation</a></h3>
<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 <a href="managing-resources-in-the-core-api.html#channel-priority">Channel Priority</a> section of this chapter for more information.</li>
<li>The underlying peak volume if available. See the <a href="managing-resources-in-the-core-api.html#peak-volume">Peak Volume</a> section of this chapter 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>.</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 3D level 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_set3dlevel">ChannelControl::set3DLevel</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>
<h3 id="peak-volume"><a href="#peak-volume">9.1.2 Peak Volume</a></h3>
<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 is treated as if it had full volume.</p>
<h3 id="vol0-virtual"><a href="#vol0-virtual">9.1.3 VOL0 Virtual</a></h3>
<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>, 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#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> is automatically set when calling <a class="apilink" href="studio-api-system.html#studio_system_initialize">Studio::System::initialize</a>, and vol0virtualvol can be set in <a class="apilink" href="core-api-system.html#system_setadvancedsettings">System::setAdvancedSettings</a> 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>
<h3 id="channel-priority"><a href="#channel-priority">9.1.4 Channel Priority</a></h3>
<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>It is up to you 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.</p>
<p>We recommend not using too many priority levels in a single game. The benefit of audibility-based virtualization is that it ensures only the quietest and least-noticeable channels are virtualized, making the effect of channel virtualization as subtle and unnoticeable as possible. Having a larger number of channel priorities increases the liklihood of channels being stolen even when they are loud and noticeable, and thus undermines that benefit.</p>
<h3 id="software-channels-vs-virtual-channels"><a href="#software-channels-vs-virtual-channels">9.1.5 Software Channels vs Virtual Channels</a></h3>
<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>
<h3 id="virtual-to-real-transition"><a href="#virtual-to-real-transition">9.1.6 Virtual to Real Transition</a></h3>
<p>When channels stop being virtual, they resume from their proper place, part-way 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">9.1.7 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, some 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 mutes its master channel group; this causes any playing <a class="apilink" href="core-api-channel.html">Channel</a>s to go virtual, as <a class="apilink" href="core-api-system.html#fmod_init_vol0_becomes_virtual">FMOD_INIT_VOL0_BECOMES_VIRTUAL</a> is always set when using the Studio API.</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-the-core-api-virtual-voice-system"><a href="#interaction-with-the-core-api-virtual-voice-system">Interaction with the 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">9.1.8 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>
<h2 id="non-blocking-loads-threads-and-thread-safety"><a href="#non-blocking-loads-threads-and-thread-safety">9.2 Non blocking loads, threads and thread safety</a></h2>
<p>Core API commands are thread safe and queued. They get processed either immediately, or in background threads, depending on the command.</p>
<p>By default, things like initialization and loading a <a class="apilink" href="core-api-sound.html">Sound</a> are processed on the main thread.</p>
<p>Mixing, streaming, geometry processing, file reading and file loading are or can be done in the background, in background threads. Every effort is made to avoid blocking the main application's loop unexpectedly.</p>
<p>One of the slowest operations is loading a <a class="apilink" href="core-api-sound.html">Sound</a>. To place a <a class="apilink" href="core-api-sound.html">Sound</a> load into the background so that it doesn't affect processing in the main application thread, the user can use the <a class="apilink" href="core-api-common.html#fmod_nonblocking">FMOD_NONBLOCKING</a> flag in <a class="apilink" href="core-api-system.html#system_createsound">System::createSound</a> or <a class="apilink" href="core-api-system.html#system_createstream">System::createStream</a>.</p>
<p>FMOD thread types:</p>
<ul>
<li><strong>The Mixer thread.</strong> This thread is the software mixing thread. This is the thread that does the real work of mixing the <a href="glossary.html#dsp-graph">DSP graph</a>. It is created at <a class="apilink" href="core-api-system.html#system_init">System::init</a>.</li>
<li><strong>The stream thread.</strong> This thread is used for decoding streams. It is created the first time a sound is loaded as a stream in System::createSound with <a class="apilink" href="core-api-common.html#fmod_createstream">FMOD_CREATESTREAM</a>, or <a class="apilink" href="core-api-system.html#system_createstream">System::createStream</a>.</li>
<li><strong>The async loading thread.</strong> This thread is created the first time a sound is loaded with the <a class="apilink" href="core-api-common.html#fmod_nonblocking">FMOD_NONBLOCKING</a> flag in <a class="apilink" href="core-api-system.html#system_createsound">System::createSound</a>.</li>
<li><strong>The file reading thread.</strong> This thread is used for reading from disk for streams, to then be decoded (decompressed) by the Stream thread. It is created the first time a sound is loaded as a stream in <a class="apilink" href="core-api-system.html#system_createsound">System::createSound</a> with <a class="apilink" href="core-api-common.html#fmod_createstream">FMOD_CREATESTREAM</a>, or <a class="apilink" href="core-api-system.html#system_createstream">System::createStream</a>.</li>
<li><strong>The Studio thread.</strong> When using the Studio API, this thread processes all Studio API commands and updates Studio events. It is created during <a class="apilink" href="studio-api-system.html#studio_system_initialize">Studio::System::initialize</a> by default, unless <a class="apilink" href="studio-api-system.html#fmod_studio_init_synchronous_update">FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE</a> is specified as an init flag.</li>
</ul>
<h3 id="thread-affinity"><a href="#thread-affinity">9.2.1 Thread Affinity</a></h3>
<p>On some platforms, FMOD thread affinity can be customized. See the platform specific <a href="platforms.html">Platform Details</a> page for more information.</p>
<h3 id="fmod-callback-types"><a href="#fmod-callback-types">9.2.2 FMOD Callback Types</a></h3>
<p>FMOD File and memory callbacks can possibly be called from an FMOD thread. Remember that if you specify file or memory callbacks with FMOD, to make sure that they are thread safe. FMOD may call these callbacks from other threads.</p>
<h3 id="core-api-thread-safety"><a href="#core-api-thread-safety">9.2.3 Core API Thread Safety</a></h3>
<p>By default, the Core API is initialized to be thread safe, which means the API can be called from any game thread at any time. Core API thread safety can be disabled with the <a class="apilink" href="core-api-system.html#fmod_init_thread_unsafe">FMOD_INIT_THREAD_UNSAFE</a> flag 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>. The overhead of thread safety is that there is a mutex lock around the public API functions and (where possible) some commands are enqueued to be executed the next <a href="glossary.html#system">system</a> update. The cases where it is safe to disable thread safety are:</p>
<ul>
<li>The game is using Studio API exclusively, and never issues Core API calls itself.</li>
<li>The game is using the Core API exclusively, and always from a single thread at once.</li>
<li>The game is using Studio API and Core API at the same time, but FMOD Studio is created with <a class="apilink" href="studio-api-system.html#fmod_studio_init_synchronous_update">FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE</a> and the Core API calls are done in the same thread as the Studio API calls.</li>
</ul>
<h3 id="studio-api-thread-safety"><a href="#studio-api-thread-safety">9.2.4 Studio API Thread Safety</a></h3>
<p>By default, the Studio API is completely thread safe, and all commands execute on the Studio API update thread. In the case of a function that returns a handle, that handle is valid as soon as the function returns it, and all functions using that handle are immediately available. As such, if a command is delayed, the delay is not immediately obvious, and does not delay subsequent commands on the thread.</p>
<p>If <a class="apilink" href="studio-api-system.html#studio_system_initialize">Studio::System::initialize</a> is called with <a class="apilink" href="studio-api-system.html#fmod_studio_init_synchronous_update">FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE</a>, then Studio will not be thread-safe as it assumes all calls will be issued from a single thread. Commands in this mode will be queued up to be processed in the next <a class="apilink" href="studio-api-system.html#studio_system_update">Studio::System::update</a> call. This mode is not recommended except for testing or for users who have set up their own asynchronous command queue already and wish to process all calls on a single thread. See the Studio Thread Overview for further information.</p>
<h2 id="cpu-performance"><a href="#cpu-performance">9.3 CPU Performance</a></h2>
<p>Before we jump into the details, let's first consider how performance is measured in the FMOD Engine. The primary metric we use, when discussing how expensive something is, is CPU percentage. We can calculate this by measuring the time spent performing an action and comparing it against a known time window; the most common example of this is <a href="glossary.html#dsp">DSP</a> or mixer performance.</p>
<p>When we talk about mixer performance we are actually talking about the production of audio samples being sent to the output (usually your speakers). At regular intervals, our mixer produces a buffer of samples which represents a fixed amount of time for playback. We call this a DSP block. DSP block size often defaults to 512 samples, which when played back at 48 kHz represents ~10ms of audio.</p>
<p>With a fixed amount of samples being produced regularly, we can now measure how long it takes to produce those samples and receive a percentage. For example, if it took us 5ms of CPU time to produce 10ms of audio, our mixer performance would be 50%. As the CPU time approaches 10ms we risk not delivering the audio in time which results in an audio discontinuity known as stuttering.</p>
<p>Another key performance area is update(). This operation is called regularly to do runtime housekeeping. Our recommendation is you call update() once per render frame, which is often 30 or 60 times per second. Using the 30 or 60 FPS (frames per second) known time frame, we can measure CPU time spent performing this action to get percentages.</p>
<p>Armed with the ability to measure performance, we need to identify the things that cost the bulk of the CPU time. The most commonly quoted contributor is <a class="apilink" href="core-api-channel.html">Channel</a> count, following the logic that playing more <a class="apilink" href="core-api-channel.html">Channel</a>s takes up more CPU time. Following is a list of the main contributors to the cost of sound playback:</p>
<ul>
<li>Decoding compressed audio to PCM.</li>
<li>Resampling the PCM to the appropriate pitch.</li>
<li>Applying <a href="glossary.html#effect">DSP effects</a> to the <a class="apilink" href="core-api-channel.html">Channel</a>.</li>
<li>Mixing the audio with other sounds to produce the final output you hear.</li>
</ul>
<h3 id="compression-format"><a href="#compression-format">9.3.1 Compression Format</a></h3>
<p>Choosing the correct compression format for the kind of audio you want to play and the platform you want to play it on is a big part of controlling the CPU cost. For recommendations on format choice, see the <a href="platforms.html">Platform Details</a> chapter.</p>
<h3 id="voice-limiting"><a href="#voice-limiting">9.3.2 Voice Limiting</a></h3>
<p>Once you've settled on a compression format, you need to decide how many <a class="apilink" href="core-api-channel.html">Channel</a>s of that format you want to be audible at the same time. There are three ways you can use to control the number of <a class="apilink" href="core-api-channel.html">Channel</a>s playable:</p>
<ul>
<li><a class="apilink" href="core-api-system.html#system_init">System::init</a> (maxChannels, ...) The maximum number of <a class="apilink" href="core-api-channel.html">Channel</a>s that can play at once.</li>
<li><a class="apilink" href="core-api-system.html#system_setsoftwarechannels">System::setSoftwareChannels</a> (numSoftwareChannels) The maximum number of software mixed (i.e.: non-virtual) <a class="apilink" href="core-api-channel.html">Channel</a>s that can play once.</li>
<li><a class="apilink" href="core-api-system.html#fmod_advancedsettings">FMOD_ADVANCEDSETTINGS</a> max???Codec The maximum number of decoders that can run at once, where ??? is the compression format.</li>
</ul>
<p>For a deep dive into how the virtual voice system works and ways to further control <a class="apilink" href="core-api-channel.html">Channel</a> count, see the <a href="managing-resources-in-the-core-api.html#virtual-voices] section of this chapter. MaxChannels should be high enough that you don't hit the cap under normal circumstances, so 256, 512 or even 1024 are reasonable choices for most games. Selecting the values for numSoftwareChannels and maxCodecs depends on the platform and format used. To help choose these values we have provided some recommendations and benchmarks in the [Platform Details](platforms.html) chapte">Virtual Voice System</a>.</p>
<h3 id="tips-and-tricks"><a href="#tips-and-tricks">9.3.3 Tips and Tricks</a></h3>
<p>With a correctly configured compression format and appropriate <a class="apilink" href="core-api-channel.html">Channel</a> count, you are well on your way to an efficiently configured set up. Next up is a series of CPU-saving tips to consider for your project. Not all are applicable to every project, but they should be considered if you want to get the best performance from the FMOD Engine.</p>
<h4 id="adjust-sample-rates"><a href="#adjust-sample-rates">Adjust Sample Rates</a></h4>
<p>There are two sample rates you need to think about when optimizing, the <a href="glossary.html#system">system</a> sample rate and the source audio sample rate.</p>
<p>You can control the system sample rate by using <a class="apilink" href="core-api-system.html#system_setsoftwareformat">System::setSoftwareFormat</a> (sampleRate, ...), which by default is 48 kHz. Reducing this can give some big wins in performance because less data is being produced. This setting is a trade off between performance and quality.</p>
<p>To control the source audio rate, you can resample using your favorite audio editor or use the sample rate settings when compressing using the FSBank tool or the FSBankLib API. All audio is sent to a resampler when it is played at runtime. If the source sample rate and the System rate match and there are no pitch / frequency settings applied to the <a class="apilink" href="core-api-channel.html">Channel</a>, the resampler is skipped, saving CPU time. This trick is often good for music and other sounds that rarely require real-time pitch adjustment.</p>
<h4 id="increase-dsp-block-size"><a href="#increase-dsp-block-size">Increase DSP Block Size</a></h4>
<p>As mentioned earlier, the DSP block size represents a fixed amount of samples that are produced regularly to be sent to the speakers. When producing each block of samples, there is a fixed amount of overhead, so making the block size larger reduces the overall CPU cost. You can control this setting with <a class="apilink" href="core-api-system.html#system_setdspbuffersize">System::setDSPBufferSize</a> (blockLength, ...), which often defaults to 512 or 1024 samples, depending on the platform.</p>
<p>The trade off with this setting is CPU against mixer granularity. For more information about the implications of changing this setting, see the <a href="core-api-system.html#system_setdspbuffersize">System::setDSPBufferSize</a> section of the <a href="core-api.html">Core API Reference</a> chapter.</p>
<h4 id="reduce-speaker-channel-count"><a href="#reduce-speaker-channel-count">Reduce Speaker Channel Count</a></h4>
<p>This section refers to channel count in the context of speaker channels as they exist in audio files.</p>
<p>Controlling how many channels of audio are being played can have a big impact on performance. Consider the simple math that a 7.1 surround signal has eight channels, and thus four times as much data to process as a stereo signal. There are a few different places where speaker channel count can be controlled to improve performance.</p>
<p>The source <a href="glossary.html#audio-channel">audio channel</a> count should be carefully chosen. Often mono sources are best, especially for sounds that are positioned in 3D. Reducing the channel count at the source is an easy win, and also decreases the decoding time for that sound.</p>
<p>Setting the system channel count controls how 3D sounds are panned when they are given a position in the world. You set this channel count by specifying a speaker mode that represents a well known speaker configuration, such as 7.1 surround or stereo. To do this, use <a class="apilink" href="core-api-system.html#system_setsoftwareformat">System::setSoftwareFormat</a> (..., speakerMode, ...). The default value of this parameter matches your output device settings.</p>
<p>As a more advanced setting, you can limit the number of speaker channels produced by a sub-mix, or the number of channels entering a particular <a href="glossary.html#dsp-effect">DSP effect</a>. This can be especially useful for limiting the channels into an expensive effect. The API to control this is DSP::setChannelFormat(..., speakerMode). By default, this parameter is the output of the previous DSP unit.</p>
<h4 id="choose-inexpensive-dsps"><a href="#choose-inexpensive-dsps">Choose Inexpensive DSPs</a></h4>
<p>Not all DSPs are created equal. Some are computationally simple and use very little CPU, others can be quite expensive. When deciding to use a particular <a href="glossary.html#effect">effect</a>, it is important to profile on the target platforms' hardware to fully understand the CPU implications.</p>
<p>The positioning of an effect in the <a href="glossary.html#dsp-graph">DSP graph</a> can make a big difference on a game's resource cost. Placing an effect on every <a href="core-api-channel.html">channel</a> routed into a <a href="core-api-channelgroup.html">channel group</a> means it can affect each of those channels differently, but costs a lot more CPU time than placing that effect only on the channel group. There are no strict rules for where each effect should be positioned, but to give an example, <a href="effects-reference.html#multiband-equalizer">multiband equalizer DSP effects</a> are cheap enough that they can often be applied to every channel without straining a game's resource budget, while the <a href="effects-reference.html#sfx-reverb">SFX reverb DSP effect</a> is expensive enough that it's more common to add a single instance of it to a channel group so that it's applied to the sub-mix.</p>
<h4 id="take-advantage-of-hardware-decoding"><a href="#take-advantage-of-hardware-decoding">Take Advantage of Hardware Decoding</a></h4>
<p>Some platforms have access to hardware assisted decoders, which offload the processing from the CPU to dedicated decoding hardware. These can be utilized by building banks with the corresponding platform's format, such as AT9, XMA, or Opus.</p>
<p>When using hardware assisted decoders with <a href="glossary.html#stream">streams</a>, each <a class="apilink" href="core-api-channel.html">Channel</a> reserves a hardware decoder for the lifetime of the Channel. This means that the <a href="managing-resources-in-the-core-api.html#virtual-voice-system">Virtual Voice System</a> is not able to steal any hardware decoders that are in use. As a result, if all hardware decoders are in use, new streamed Channels cannot play until an existing streamed Channel stops and yields its decoder. Therefore, you should not rely on the Virtual Voice System to cull streamed Channels when using hardware decoders. Treat hardware decoders as you would any other limited resource, only using what you need and freeing Channels when they are no longer required.</p>
<h2 id="custom-file-systems-and-memory-management"><a href="#custom-file-systems-and-memory-management">9.4 Custom File Systems and Memory Management</a></h2>
<p>The Core API caters to the needs of applications and their memory and file systems. A file system can be 'plugged in' so that FMOD uses it, and not its own system, as well as memory allocation.</p>
<p>To set up a custom file system is a simple process of calling <a class="apilink" href="core-api-system.html#system_setfilesystem">System::setFileSystem</a>.</p>
<p>The file system handles the normal cases of open, read, seek, close, but adds an extra feature which is useful for prioritized/delayed file systems, FMOD supports the <a class="apilink" href="core-api-system.html#fmod_file_asyncread_callback">FMOD_FILE_ASYNCREAD_CALLBACK</a> callback, for deferred, prioritized loading and reading, which is a common feature in advanced game streaming engines.</p>
<p>An async read callback can immediately return without supplying data, then when the application supplies data at a later time, even in a different thread, it can set the 'done' flag in the <a class="apilink" href="core-api-system.html#fmod_asyncreadinfo">FMOD_ASYNCREADINFO</a> structure to get FMOD to consume it. Consideration has to be made to not wait too long or increase stream buffer sizes, so that streams don't audibly stutter/skip.</p>
<p>To set up a custom memory allocator is done by calling <a class="apilink" href="core-api-common.html#memory_initialize">Memory_Initialize</a>. This is not an FMOD class member function because it needs to be called before any FMOD objects are created, including the System object.</p>
<p>To read more about setting up memory pools or memory environments, see the <a href="managing-resources-in-the-core-api.html#memory-management">Memory Management</a> section of the <a href="managing-resources-in-the-core-api.html">Managing Resources in the Core API</a> chapter.</p>
<h2 id="memory-management"><a href="#memory-management">9.5 Memory Management</a></h2>
<p>The following are some pointers on ways of saving memory in the FMOD Engine.</p>
<h3 id="use-a-fixed-size-memory-pool"><a href="#use-a-fixed-size-memory-pool">9.5.1 Use a Fixed-size Memory Pool.</a></h3>
<p>To make the FMOD Engine stay inside a fixed size memory pool, and not do any external allocs, you can use the <a class="apilink" href="core-api-common.html#memory_initialize">Memory_Initialize</a> function. i.e.:</p>
<div class="highlight language-text"><pre><span></span>result = FMOD::Memory_Initialize(malloc(4*1024*1024), 4*1024*1024, 0,0,0); // allocate 4mb and pass it to the FMOD Engine to use.
ERRCHECK(result);
</pre></div>
<p>Alternatively, you can use this function to specify your own callbacks for alloc and free. If you do, the memory pool pointer and length must be NULL.</p>
<h3 id="lower-sound-instance-overhead"><a href="#lower-sound-instance-overhead">9.5.2 Lower Sound Instance Overhead.</a></h3>
<p>The <a class="apilink" href="core-api-common.html#fmod_lowmem">FMOD_LOWMEM</a> flag can be used to shave some memory off of the sound class. This flag removes memory allocation for certain features which aren't used often in games. For example, it removes the 'name' field, so if Sound::getName is called when this flag is set, it returns "(null)".</p>
<h3 id="use-compressed-samples"><a href="#use-compressed-samples">9.5.3 Use Compressed Samples</a></h3>
<p>The FMOD Engine can play ADPCM, AT9, MP2/MP3, Opus, and XMA data compressed, without needing to decompress them to PCM first. This can save a large amount of memory, at the cost of requiring more CPU time when the sound is played.</p>
<p>To enable this, use the <a class="apilink" href="core-api-common.html#fmod_createcompressedsample">FMOD_CREATECOMPRESSEDSAMPLE</a> flag when calling <a href="core-api-system.html#system_createsound">System::createSound</a>. When using formats other than the ones specified above or platforms that do not support those formats, this flag is ignored.</p>
<p>On platforms that support hardware decoding, using this flag results in the platform hardware decoder decompressing the data without affecting the main CPU. For information about what platforms support hardware decoding and which encoding formats they support, see the <a href="platforms.html">Platform Details</a> chapter.</p>
<p>Using <a class="apilink" href="core-api-common.html#fmod_createcompressedsample">FMOD_CREATECOMPRESSEDSAMPLE</a> incurs a 'one off' memory overhead cost, as it allocates the pool of codecs required to play the encoding format of the sample data. For information on how to control this pool, see <a href="#control-memory-usage-with-settings">the following section</a>.</p>
<h3 id="control-memory-usage-with-settings"><a href="#control-memory-usage-with-settings">9.5.4 Control Memory Usage with Settings</a></h3>
<p>For sounds created with <a class="apilink" href="core-api-common.html#fmod_createcompressedsample">FMOD_CREATECOMPRESSEDSAMPLE</a>, <a class="apilink" href="core-api-system.html#system_setadvancedsettings">System::setAdvancedSettings</a> allows you to reduce the number of simultaneous XMA/ADPCM or MPEG sounds played at once, to save memory. The defaults are specified in the documentation for this function. Lowering them reduces memory consumption. The pool of codecs for each codec type is only allocated when the first sound of that type is loaded, so reducing XMA (for example) to 0 when XMA is never used does not save any memory.</p>
<p>For streams, setting <a class="apilink" href="core-api-system.html#system_setstreambuffersize">System::setStreamBufferSize</a> controls the memory usage for the stream buffer used for each stream. Lowering the size in this function reduces memory consumption, but may also lead to stuttering streams. This is purely based on the type of media the FMOD streamer is reading from (e.g.: a CD-ROM is slower than a hard disk), so you should experiment with your target platforms' hardware to determine whether changing the stream buffer size will cause problems.</p>
<p>Reducing the number of <a class="apilink" href="core-api-channel.html">Channel</a>s used reduces memory consumption. <a class="apilink" href="core-api-system.html#system_init">System::init</a>'s maxchannels parameter sets the maximum number of concurrent voices, and <a class="apilink" href="core-api-system.html#system_setsoftwarechannels">System::setSoftwareChannels</a> sets the maximum number of concurrent real voices. You should specify enough voices though to avoid <a class="apilink" href="core-api-channel.html">Channel</a> stealing.</p>
<h3 id="tracking-fmod-memory-usage"><a href="#tracking-fmod-memory-usage">9.5.5 Tracking FMOD memory usage.</a></h3>
<p>Using Memory_GetStats is a good way to track FMOD memory usage, and also find the highest amount of memory allocated at any time. This information is useful when attempting to trim or adjust your project's memory consumption; for example, when adjusting the fixed memory pool size.</p></div>
<p class="manual-footer">FMOD Engine User Manual 2.03.13 (2026-03-31). &copy; 2026 Firelight Technologies Pty Ltd.</p>
</div>
</body>
</html>