634 lines
54 KiB
HTML
634 lines
54 KiB
HTML
<html>
|
|
<head>
|
|
<title>Platform Details | HTML5</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 class="manual-current-chapter manual-inactive-chapter"><a href="platforms.html">Platform Details</a><ul class="subchapters"><li><a href="platforms-win.html">Windows</a></li><li><a href="platforms-mac.html">Mac</a></li><li><a href="platforms-linux.html">Linux</a></li><li><a href="platforms-ios.html">iOS</a></li><li><a href="platforms-android.html">Android</a></li><li><a href="platforms-openharmony.html">Open Harmony</a></li><li><a href="platforms-uwp.html">Universal Windows Platform</a></li><li class="manual-current-chapter manual-active-chapter"><a href="platforms-html5.html">HTML5</a></li></ul></li>
|
|
<li><a href="white-papers.html">White Papers</a></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>4. Platform Details | HTML5</h1>
|
|
<div class="toc">
|
|
<ul>
|
|
<li><a href="#html5-specific-starter-guide">HTML5 Specific Starter Guide</a><ul>
|
|
<li><a href="#sdk-version">SDK Version</a></li>
|
|
<li><a href="#compatibility">Compatibility</a></li>
|
|
<li><a href="#limitations">Limitations</a><ul>
|
|
<li><a href="#multi-threading">Multi-threading</a></li>
|
|
<li><a href="#networking">Networking</a></li>
|
|
<li><a href="#performance">Performance</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#libraries">Libraries</a><ul>
|
|
<li><a href="#technology-choice">Technology choice</a></li>
|
|
<li><a href="#wasm">WASM</a></li>
|
|
<li><a href="#js">JS</a></li>
|
|
<li><a href="#w32">W32</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#building-a-cc-program-that-uses-fmod-libraries">Building a C/C++ program that uses FMOD libraries</a></li>
|
|
<li><a href="#browser-compatibility">Browser Compatibility</a></li>
|
|
<li><a href="#output-modes">Output Modes</a></li>
|
|
<li><a href="#essential-startup-information">Essential Startup Information</a><ul>
|
|
<li><a href="#start-up-code">Start up code</a></li>
|
|
<li><a href="#user-interaction-requirement">User interaction requirement</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#reduced-feature-build">Reduced Feature build</a><ul>
|
|
<li><a href="#overview">Overview</a></li>
|
|
<li><a href="#codec-support">Codec Support</a></li>
|
|
<li><a href="#dsp-effect-support">DSP Effect support</a></li>
|
|
<li><a href="#speaker-mode-support">Speaker mode support</a></li>
|
|
<li><a href="#feature-support">Feature support</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#api-javascript-port-of-a-cc-api-differences">API - JavaScript port of a C/C++ API. Differences.</a><ul>
|
|
<li><a href="#setting-and-getting">Setting and getting.</a></li>
|
|
<li><a href="#constants-that-started-with-fmod_-in-cc">Constants that started with FMOD_ in C/C++</a></li>
|
|
<li><a href="#using-structures">Using structures</a></li>
|
|
<li><a href="#api-differences">API differences</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#file-access">File Access</a><ul>
|
|
<li><a href="#direct-from-host-via-fmods-filesystem">Direct from host, via FMOD's filesystem</a></li>
|
|
<li><a href="#via-memory">Via memory</a></li>
|
|
<li><a href="#via-callbacks">Via callbacks</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#javascript-specific-functions-for-fmod">JavaScript specific functions for FMOD</a><ul>
|
|
<li><a href="#helper-functions">Helper functions</a></li>
|
|
<li><a href="#system">System</a></li>
|
|
<li><a href="#file">File</a></li>
|
|
<li><a href="#misc">Misc</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#linking-fmod-for-html5-in-a-c-program-that-is-to-be-converted-via-emscripten">Linking FMOD for HTML5 in a C program that is to be converted via emscripten</a></li>
|
|
<li><a href="#performance-and-memory">Performance and Memory</a><ul>
|
|
<li><a href="#cpu-overhead">CPU Overhead</a></li>
|
|
<li><a href="#audio-stability-stuttering">Audio Stability (Stuttering)</a></li>
|
|
<li><a href="#threads">Threads</a></li>
|
|
<li><a href="#heap-memory">'Heap' Memory</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#limitations_1">Limitations</a><ul>
|
|
<li><a href="#non-blocking-loading">Non-blocking loading</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#known-issues">Known Issues</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<h2 id="html5-specific-starter-guide"><a href="#html5-specific-starter-guide">HTML5 Specific Starter Guide</a></h2>
|
|
<p>Running FMOD as HTML5 on the web is made possible by having a web server host and deliver the JavaScript content to the client web browser. In a production environment this would be hosted using a professional web server such as Apache, but during development we recommend an easy to set up local server such as <a href="https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb">Web Server for Chrome</a></p>
|
|
<h3 id="sdk-version"><a href="#sdk-version">SDK Version</a></h3>
|
|
<p>FMOD is compiled using the following tools.</p>
|
|
<ul>
|
|
<li><strong>Emscripten</strong> - 3.1.67</li>
|
|
</ul>
|
|
<h3 id="compatibility"><a href="#compatibility">Compatibility</a></h3>
|
|
<p>FMOD supports the following minimum browser versions.</p>
|
|
<ul>
|
|
<li>Firefox: 79</li>
|
|
<li>Safari: 14.1.0</li>
|
|
<li>Chrome: 85</li>
|
|
</ul>
|
|
<h3 id="limitations"><a href="#limitations">Limitations</a></h3>
|
|
<p>The web presents a unique set of challenges that make this implementation less than perfect when compared to other platforms supported by the FMOD Engine.</p>
|
|
<h4 id="multi-threading"><a href="#multi-threading">Multi-threading</a></h4>
|
|
<p>One significant disadvantage is the lack of multi-threading, or more specifically, limited browser support of features such as <a href="https://caniuse.com/#feat=sharedarraybuffer">SharedArrayBuffer</a> that prevent our toolchain from implementing <a href="https://emscripten.org/docs/porting/pthreads.html">pthread support</a>. This limitation means we must run mixing, streaming and loading all in the game thread requiring added latency to hide the additional CPU cost.</p>
|
|
<h4 id="networking"><a href="#networking">Networking</a></h4>
|
|
<p>Another disadvantage of the web platform is the lack of networking sockets. There are <a href="https://emscripten.org/docs/porting/networking.html">alternatives</a> provided by our toolchain, however they require additional servers running as a proxy. This limitation means we cannot implement Live Update and Profiling features between the running code and <a href="glossary.html#fmod-studio">FMOD Studio</a>. Additionally this means we cannot support internet streaming of audio (netstreams).</p>
|
|
<h4 id="performance"><a href="#performance">Performance</a></h4>
|
|
<p>Many platforms benefit from targeted instruction level optimization known as SIMD (single instruction multiple data), these optimizations allow FMOD to perform several times faster than with standard C code instructions alone. Unfortunately development of <a href="https://emscripten.org/docs/porting/simd.html">SIMD for the web</a> is an ongoing process and not ready for us to consume. This coupled with the fact the native FMOD C code has been converted to run in a browser means you will experience worse performance than the equivalent application running natively (outside the browser).</p>
|
|
<h3 id="libraries"><a href="#libraries">Libraries</a></h3>
|
|
<p>There are a large number of binaries for HTML5 covering different runtime formats and compatibility.</p>
|
|
<p>The folder structure we use represents the choices you must make following this pattern: <code>/api/{fmod-api}/lib/{binary-format}/*</code></p>
|
|
<ul>
|
|
<li><code>{fmod-api}</code> Select either core or studio depending on which API you wish to use. For HTML5 (unlike other platforms) studio already contains the core library so including the core library separately is not necessary.</li>
|
|
<li><code>{binary-format}</code> Select wasm for the most performant feature-rich version targeting modern browsers or js for compatibility with older browsers.<ul>
|
|
<li>If you are developing in HTML / Javascript your choices are:<ul>
|
|
<li><a href="#wasm">WASM</a></li>
|
|
<li><a href="#js">JS</a></li>
|
|
</ul>
|
|
</li>
|
|
<li>If you are developing in C / C++ your choices are:<ul>
|
|
<li><a href="#w32">W32</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p>To include FMOD using JavaScript in a html file, refer to the following example in your HTML. Filename will vary based on what HTML technology or logging/reduced variant you might be using.</p>
|
|
<p>Core API Only:</p>
|
|
<div class="highlight language-html"><pre><span></span><span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> <span class="na">src</span><span class="o">=</span><span class="s">"fmod.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
</pre></div>
|
|
|
|
<p>Studio API:</p>
|
|
<div class="highlight language-html"><pre><span></span><span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> <span class="na">src</span><span class="o">=</span><span class="s">"fmodstudio.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
</pre></div>
|
|
|
|
<h4 id="technology-choice"><a href="#technology-choice">Technology choice</a></h4>
|
|
<p>Select from below for your technology choice, and refer to the table for the folder the FMOD libraries are located in, and any accompanying files that must be copied in with them to your project folder.</p>
|
|
<hr />
|
|
<h4 id="wasm"><a href="#wasm">WASM</a></h4>
|
|
<p>Faster (approximately 30%) and uses half the memory of Javascript, but requires the web browser to support the WASM technology, and also a web server that understands the .wasm 'application/wasm' mime type.</p>
|
|
<p><strong>Core API libraries</strong> - Located in /api/core/lib/wasm/</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Core API file</th>
|
|
<th>Companion file (put in same folder)</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmod.js</td>
|
|
<td>fmod.wasm</td>
|
|
<td>Release library for production code</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodL.js</td>
|
|
<td>fmodL.wasm</td>
|
|
<td>Release library with logging output, use for debugging</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmod_reduced.js</td>
|
|
<td>fmod_reduced.wasm</td>
|
|
<td>Smaller release library for production code, with <a href="#reduced-feature-build">reduced</a> features</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><strong>Studio API libraries</strong> - Located in /api/studio/lib/wasm/. The Studio API files already contain the Core API, so you do not need to include the Core API files as well.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Studio API file</th>
|
|
<th>Companion file (put in same folder)</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmodstudio.js</td>
|
|
<td>fmodstudio.wasm</td>
|
|
<td>Release library for production code. Includes fmod_reduced.js</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodstudioL.js</td>
|
|
<td>fmodstudioL.wasm</td>
|
|
<td>Release library with logging output, use for debugging</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<hr />
|
|
<h4 id="js"><a href="#js">JS</a></h4>
|
|
<p>Older Javascript compiled. Slower and uses more memory, but best for compatibility.</p>
|
|
<p><strong>Core API libraries</strong> - Located in /api/core/lib/js/</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Core API file</th>
|
|
<th>Companion file (put in same folder)</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmod.js</td>
|
|
<td>fmod.js.mem</td>
|
|
<td>Release library for production code</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodL.js</td>
|
|
<td>fmodL.js.mem</td>
|
|
<td>Release library with logging output, use for debugging</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmod_reduced.js</td>
|
|
<td>fmod_reduced.js.mem</td>
|
|
<td>Smaller release library for production code, with <a href="#reduced-feature-build">reduced</a> features</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><strong>Studio API libraries</strong> - Located in /api/studio/lib/js/. The Studio API files already contain the Core API, so you do not need to include the Core API files as well.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Studio API file</th>
|
|
<th>Companion file (put in same folder)</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmodstudio.js</td>
|
|
<td>fmodstudio.js.mem</td>
|
|
<td>Release library for production code. Contains fmod_reduced.js</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodstudioL.js</td>
|
|
<td>fmodstudioL.js.mem</td>
|
|
<td>Release library with logging output, use for debugging. Contains fmodL.js</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<hr />
|
|
<h4 id="w32"><a href="#w32">W32</a></h4>
|
|
<p>For using Emscripten with your own C/C++ code to convert to JavaScript. W32 is an intermediate format.</p>
|
|
<p><strong>Core API libraries</strong> - Located in /api/core/lib/w32/</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Core API file</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmod.a</td>
|
|
<td>Release binary for production code</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodL.a</td>
|
|
<td>Release binary with logging enabled for development</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmod_reduced.a</td>
|
|
<td>Smaller release binary with <a href="#reduced-feature-build">reduced</a> features, for production code.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><strong>Studio API libraries</strong> - Located in /api/studio/lib/w32/. The Studio API files already contain the Core API, so you do not need to include the Core API files as well.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Studio API file</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>fmodstudio.a</td>
|
|
<td>Release binary for production code. Contains fmod_reduced.a</td>
|
|
</tr>
|
|
<tr>
|
|
<td>fmodstudioL.a</td>
|
|
<td>Release binary with logging enabled for development. Contains fmodL.a</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><strong>Note</strong>: The fmodstudio versions of the library include the <strong>fmod_reduced</strong> version of the core, so accessing things like .ogg/.mp3 (see <a href="#reduced-feature-build">reduced</a> ) through <a class="apilink" href="studio-api-system.html#studio_system_getcoresystem">Studio::System::getCoreSystem</a> are not supported. Use the fmodstudioL version to get full access to all features.</p>
|
|
<h3 id="building-a-cc-program-that-uses-fmod-libraries"><a href="#building-a-cc-program-that-uses-fmod-libraries">Building a C/C++ program that uses FMOD libraries</a></h3>
|
|
<p>If you have a C/C++ program that uses FMOD and are converting it to JavaScript using Emscripten, you will need to link the relevant FMOD binaries as per the <a href="https://emscripten.org/docs/compiling/Building-Projects.html#using-libraries">Emscripten Documentation</a>, and ensure the following flag is added in your Emscripten compilation arguments:</p>
|
|
<div class="highlight language-text"><pre><span></span>-s EXPORTED_RUNTIME_METHODS=ccall,cwrap,setValue,getValue
|
|
</pre></div>
|
|
|
|
<h3 id="browser-compatibility"><a href="#browser-compatibility">Browser Compatibility</a></h3>
|
|
<ul>
|
|
<li>FMOD requires a browser to support web-audio to be compatible, this is supported by all current browsers, see details <a href="https://caniuse.com/#feat=audio-api">here</a>.</li>
|
|
<li>For using the WASM version of FMOD there are additional restrictions, however most mainstream browsers have support, see details <a href="https://caniuse.com/#feat=wasm">here</a>.</li>
|
|
<li>Browser support for 5.1 / surround sound is supported but maybe limited to certain browsers, and was adopted early by Mozilla Firefox verified in version 50.1.0.</li>
|
|
<li>Modern browsers require user interaction to initiate audio, see "Essential Startup Information" below for details.</li>
|
|
<li>Browsers that support AudioWorkletNode will automatically use <a class="apilink" href="core-api-system.html#fmod_outputtype_audioworklet">FMOD_OUTPUTTYPE_AUDIOWORKLET</a> for this functionality.</li>
|
|
<li>If AudioWorkletNode is supported, a fast code path using <a href="https://caniuse.com/#feat=sharedarraybuffer">SharedArrayBuffer</a> can be set from the server header, using "Cross-Origin-Opener-Policy: same-origin" and "Cross-Origin-Embedder-Policy: require-corp" policies. Please follow this <a href="https://web.dev/cross-origin-isolation-guide/">guide</a> for further information on how this is done. </li>
|
|
<li>Presently there is a bug where AudioWorkletNode functionality will not download from the web if your website uses http but https works correctly. If it fails to download FMOD will default to <a class="apilink" href="core-api-system.html#fmod_outputtype_webaudio">FMOD_OUTPUTTYPE_WEBAUDIO</a>. </li>
|
|
</ul>
|
|
<h3 id="output-modes"><a href="#output-modes">Output Modes</a></h3>
|
|
<p>The FMOD engine supports two <a class="apilink" href="core-api-system.html#fmod_outputtype">FMOD_OUTPUTTYPE</a> modes for Web Audio.</p>
|
|
<ul>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_outputtype_webaudio">FMOD_OUTPUTTYPE_WEBAUDIO</a> - at the code level this uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode">ScriptProcessorNode</a> which is now deprecated. This output mode will only be used as legacy or a last resort fallback. </li>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_outputtype_audioworklet">FMOD_OUTPUTTYPE_AUDIOWORKLET</a> - at the code level this uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletNode">AudioWorkletNode</a>. FMOD will always default to this if the browser supports this functionality. FMOD also relies on the Worklet <a href="https://developer.mozilla.org/en-US/docs/Web/API/Worklet/addModule">addModule</a> function to be supported as well. If none of that functionality is supported FMOD will default to using <a class="apilink" href="core-api-system.html#fmod_outputtype_webaudio">FMOD_OUTPUTTYPE_WEBAUDIO</a>. <a class="apilink" href="core-api-system.html#fmod_outputtype_audioworklet">FMOD_OUTPUTTYPE_AUDIOWORKLET</a> coupled with <a href="https://caniuse.com/#feat=sharedarraybuffer">SharedArrayBuffer</a> gives the best performance.</li>
|
|
</ul>
|
|
<h3 id="essential-startup-information"><a href="#essential-startup-information">Essential Startup Information</a></h3>
|
|
<h4 id="start-up-code"><a href="#start-up-code">Start up code</a></h4>
|
|
<p>To start with FMOD in a JavaScript environment you must initialize a global FMOD object, which you can then call FMOD functions with.</p>
|
|
<p>This involves declaring a variable (ie 'FMOD') then calling a constructor function on it ( 'ie FMODModule(FMOD); )</p>
|
|
<p>Before this constructor is called, some optional user callbacks can be set for pre / post emscripten initialization, as well as the FMOD memory block size for ASM.JS users.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">FMOD</span> <span class="o">=</span> <span class="p">{};</span> <span class="c1">// FMOD global object which must be declared to enable 'main' and 'preRun' and then call the constructor function.</span>
|
|
<span class="nx">FMOD</span><span class="p">[</span><span class="s1">'preRun'</span><span class="p">]</span> <span class="o">=</span> <span class="nx">prerun</span><span class="p">;</span> <span class="c1">// Will be called before FMOD runs, but after the Emscripten runtime has initialized</span>
|
|
<span class="nx">FMOD</span><span class="p">[</span><span class="s1">'onRuntimeInitialized'</span><span class="p">]</span> <span class="o">=</span> <span class="nx">main</span><span class="p">;</span> <span class="c1">// Called when the Emscripten runtime has initialized</span>
|
|
<span class="nx">FMOD</span><span class="p">[</span><span class="s1">'INITIAL_MEMORY'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">64</span><span class="o">*</span><span class="mi">1024</span><span class="o">*</span><span class="mi">1024</span><span class="p">;</span> <span class="c1">// (ASM.JS ONLY) FMOD Heap defaults to 16mb which is enough for this demo, but set it differently here for demonstration (64mb)</span>
|
|
<span class="nx">FMODModule</span><span class="p">(</span><span class="nx">FMOD</span><span class="p">);</span> <span class="c1">// Calling the constructor function with our object</span>
|
|
</pre></div>
|
|
|
|
<h4 id="user-interaction-requirement"><a href="#user-interaction-requirement">User interaction requirement</a></h4>
|
|
<p>Most browsers have a user interaction requirement, or audio will not be audible.<br />
|
|
This was implemented to stop unscrupulous websites from auto playing audio in things like advertisements.</p>
|
|
<p>FMOD output will become audible upon detecting a user interaction.</p>
|
|
<h3 id="reduced-feature-build"><a href="#reduced-feature-build">Reduced Feature build</a></h3>
|
|
<p>fmod_reduced.js and fmodstudio.js feature removal</p>
|
|
<h4 id="overview"><a href="#overview">Overview</a></h4>
|
|
<p>The fmod_reduced library is a smaller subset of features. The following is a list of what is removed.</p>
|
|
<p>fmodstudio.js includes fmod_reduced.js by default. To get the full feature set use fmodstudioL.js instead.</p>
|
|
<h4 id="codec-support"><a href="#codec-support">Codec Support</a></h4>
|
|
<p>The following are removed in favour of .FSB only. .FSB support includes vorbis, FADPCM and pcm compression formats.</p>
|
|
<ul>
|
|
<li>AIFF file format support</li>
|
|
<li>DLS file format support</li>
|
|
<li>FLAC file format support</li>
|
|
<li>WAV file format support</li>
|
|
<li>MOD file format support</li>
|
|
<li>S3M file format support</li>
|
|
<li>XM file format support</li>
|
|
<li>IT file format support</li>
|
|
<li>MID/MIDI file format support</li>
|
|
<li>MP2/MP3 file format support</li>
|
|
<li>OGG file format support</li>
|
|
<li>PLS/M3U file format support</li>
|
|
<li>DLS file format support</li>
|
|
</ul>
|
|
<h4 id="dsp-effect-support"><a href="#dsp-effect-support">DSP Effect support</a></h4>
|
|
<p>The following are removed due to relative expensiveness of the <a href="glossary.html#effect">effect</a> and usage rates being below other types of effects.</p>
|
|
<ul>
|
|
<li>Envelope follower <a href="glossary.html#dsp">DSP</a> support</li>
|
|
<li>Cubic / Spline and 'none' interpolation support. Linear interpolation only.</li>
|
|
</ul>
|
|
<h4 id="speaker-mode-support"><a href="#speaker-mode-support">Speaker mode support</a></h4>
|
|
<ul>
|
|
<li>5.1 / 7.1 etc support is supported on certain browsers.</li>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_outputtype_webaudio">FMOD_OUTPUTTYPE_WEBAUDIO</a> - <a class="apilink" href="core-api-system.html#system_setsoftwareformat">System::setSoftwareFormat</a> must be used to set the right speaker mode.</li>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_outputtype_audioworklet">FMOD_OUTPUTTYPE_AUDIOWORKLET</a> - This will automatically select the speaker mode from the computer's OS speaker settings. </li>
|
|
<li>Not all browsers support 5.1. See the table at the top of this document for tested working browsers.</li>
|
|
</ul>
|
|
<h4 id="feature-support"><a href="#feature-support">Feature support</a></h4>
|
|
<p>The following features have been removed</p>
|
|
<ul>
|
|
<li>3D Geometry occlusion processing (via polygons).</li>
|
|
</ul>
|
|
<h3 id="api-javascript-port-of-a-cc-api-differences"><a href="#api-javascript-port-of-a-cc-api-differences">API - JavaScript port of a C/C++ API. Differences.</a></h3>
|
|
<h4 id="setting-and-getting"><a href="#setting-and-getting">Setting and getting.</a></h4>
|
|
<p>This is an important section if coming from knowledge of a C/C++ background of the FMOD API.</p>
|
|
<p>Javascript parameters are passed by value, therefore when you pass one to a function, it makes the concept of a 'getter' function difficult.<br />
|
|
The variable's value cannot be changed by the function from the caller's perspective, but it can add a new member to the variable, which is the mechanism FMOD always uses when 'getting' data from a function.</p>
|
|
<p>In C the variable can be altered as it would be passed by <strong>reference</strong> (using pointers).<br />
|
|
In FMOD for JavaScript, the variable you pass in gets a <strong>new member called val</strong> which contains the new data.<br />
|
|
i.e.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">outval</span><span class="p">;</span> <span class="c1">// generic variable to reuse and be passed to FMOD functions.</span>
|
|
<span class="kd">var</span> <span class="nx">name</span><span class="p">;</span> <span class="c1">// to store name of sound.</span>
|
|
|
|
<span class="nx">sound</span><span class="p">.</span><span class="nx">getName</span><span class="p">(</span><span class="nx">outval</span><span class="p">);</span>
|
|
<span class="nx">name</span> <span class="o">=</span> <span class="nx">outval</span><span class="p">.</span><span class="nx">val</span><span class="p">;</span> <span class="c1">// 'val' contains the data. Pass it to the variable we want to keep.</span>
|
|
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<p>All FMOD functions that produce data in a variable after calling a function return data this way.</p>
|
|
<h4 id="constants-that-started-with-fmod_-in-cc"><a href="#constants-that-started-with-fmod_-in-cc">Constants that started with FMOD_ in C/C++</a></h4>
|
|
<p>In FMOD for JavaScript the enumerated values are members of the object declared at the top of the file.<br />
|
|
As this would normally be a variable called <strong>'FMOD'</strong> it would be redundant to keep the FMOD_ as part of the constant name, so it is removed to avoid duplication.<br />
|
|
For example, instead of</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">FMOD_OK</span>
|
|
</pre></div>
|
|
|
|
<p>in FMOD for HTML5 it becomes:</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">OK</span>
|
|
</pre></div>
|
|
|
|
<p>similarly</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD_INIT_NORMAL</span>
|
|
<span class="nx">FMOD_DEFAULT</span>
|
|
<span class="nx">FMOD_ERR_FILE_NOTFOUND</span>
|
|
<span class="nx">FMOD_GUID</span>
|
|
<span class="nx">FMOD_3D_ATTRIBUTES</span>
|
|
<span class="nx">etc</span>
|
|
</pre></div>
|
|
|
|
<p>becomes</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">INIT_NORMAL</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">DEFAULT</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">ERR_FILE_NOTFOUND</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">GUID</span><span class="p">()</span>
|
|
<span class="nx">etc</span>
|
|
</pre></div>
|
|
|
|
<p>Not that for attributes that start with a number after the FMOD namespace, it has to start with an underscore.<br />
|
|
For example.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">_3D</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">_2D</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">_3D_ATTRIBUTES</span><span class="p">()</span>
|
|
</pre></div>
|
|
|
|
<h4 id="using-structures"><a href="#using-structures">Using structures</a></h4>
|
|
<p>In the above example you may notice that () is used to 'construct' a javascript object which represents a C structure in the FMOD API.<br />
|
|
When using a structure to pass information to FMOD, a helper/constuctor function must be called to create the structure before using it/filling in its members, so that FMOD can understand what is being passed to it.<br />
|
|
If these constructor functions are not used, the function it is being passed to will probably result in a 'binding' error (in the browser debug/log console/window).</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">guid</span> <span class="o">=</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">GUID</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">info</span> <span class="o">=</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">STUDIO_BANK_INFO</span><span class="p">();</span>
|
|
</pre></div>
|
|
|
|
<h4 id="api-differences"><a href="#api-differences">API differences</a></h4>
|
|
<p>Some API constructs are redundant for JavaScript, so are removed from the API.</p>
|
|
<p>Examples are 'cbsize' inside a struct. The JavaScript version of a struct already knows its own size, so it is removed/redundant here.</p>
|
|
<p>Structures like <a class="apilink" href="core-api-system.html#fmod_createsoundexinfo">FMOD_CREATESOUNDEXINFO</a>, <a class="apilink" href="core-api-system.html#fmod_advancedsettings">FMOD_ADVANCEDSETTINGS</a> and <a class="apilink" href="studio-api-system.html#fmod_studio_advancedsettings">FMOD_STUDIO_ADVANCEDSETTINGS</a> have these members, it can just be left out.</p>
|
|
<h3 id="file-access"><a href="#file-access">File Access</a></h3>
|
|
<p>FMOD lets you load data from the host in a few different ways, depending on your setup.</p>
|
|
<h4 id="direct-from-host-via-fmods-filesystem"><a href="#direct-from-host-via-fmods-filesystem">Direct from host, via FMOD's filesystem</a></h4>
|
|
<p>FMOD exposes an emscripten mechanism to mount/pre-load files in the 'prerun()' function, that is described above in the <a href="#essential-startup-information">"Essential Startup Information"</a> section of this document.<br />
|
|
Call FMOD.FS_createPreloadedFile to register your files so that FMOD can use filenames in file related functions. See <a href="https://emscripten.org/docs/api_reference/Filesystem-API.html#FS.createPreloadedFile">Emscripten docs</a> for more on this function.<br />
|
|
For example the <strong>playsound</strong> example</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="c1">// Will be called before FMOD runs, but after the Emscripten runtime has initialized</span>
|
|
<span class="c1">// Call FMOD file preloading functions here to mount local files. Otherwise load custom data from memory or use own file system.</span>
|
|
<span class="kd">function</span> <span class="nx">prerun</span><span class="p">()</span>
|
|
<span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">fileUrl</span> <span class="o">=</span> <span class="s2">"/public/js/"</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">fileName</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">folderName</span> <span class="o">=</span> <span class="s2">"/"</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">canRead</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">canWrite</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
|
|
<span class="nx">fileName</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="s2">"dog.wav"</span><span class="p">,</span>
|
|
<span class="s2">"lion.wav"</span><span class="p">,</span>
|
|
<span class="s2">"wave.mp3"</span>
|
|
<span class="p">];</span>
|
|
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">count</span> <span class="o"><</span> <span class="nx">fileName</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">count</span><span class="o">++</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">FS_createPreloadedFile</span><span class="p">(</span><span class="nx">folderName</span><span class="p">,</span> <span class="nx">fileName</span><span class="p">[</span><span class="nx">count</span><span class="p">],</span> <span class="nx">fileUrl</span> <span class="o">+</span> <span class="nx">fileName</span><span class="p">[</span><span class="nx">count</span><span class="p">],</span> <span class="nx">canRead</span><span class="p">,</span> <span class="nx">canWrite</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
<p>Then later in your app you can simply reference a file by path/filename.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">createSound</span><span class="p">(</span><span class="s2">"/lion.wav"</span><span class="p">,</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">LOOP_OFF</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">outval</span><span class="p">);</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<h4 id="via-memory"><a href="#via-memory">Via memory</a></h4>
|
|
<p>If you have raw data in memory that you want to pass to FMOD , you can. Warning though, javascript passes data by value, so the memory usage will temporarily double for the sound data when it is passed to fmod.<br />
|
|
The <strong>load_from_memory</strong> has an example of this</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">chars</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Uint8Array</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">outval</span> <span class="o">=</span> <span class="p">{};</span>
|
|
<span class="kd">var</span> <span class="nx">result</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">exinfo</span> <span class="o">=</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">CREATESOUNDEXINFO</span><span class="p">();</span>
|
|
<span class="nx">exinfo</span><span class="p">.</span><span class="nx">length</span> <span class="o">=</span> <span class="nx">chars</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
|
|
|
|
<span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">createStream</span><span class="p">(</span><span class="nx">chars</span><span class="p">.</span><span class="nx">buffer</span><span class="p">,</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">LOOP_OFF</span> <span class="o">|</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">OPENMEMORY</span><span class="p">,</span> <span class="nx">exinfo</span><span class="p">,</span> <span class="nx">outval</span><span class="p">);</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<h4 id="via-callbacks"><a href="#via-callbacks">Via callbacks</a></h4>
|
|
<p>If you have a file system you can use file callbacks to load data into FMOD. See <a class="apilink" href="core-api-system.html#system_setfilesystem">System::setFileSystem</a>, or <a class="apilink" href="studio-api-system.html#studio_system_loadbankcustom">Studio::System::loadBankCustom</a><br />
|
|
In <strong>load_bank</strong> example, there is a demonstration of this</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">info</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">STUDIO_BANK_INFO</span><span class="p">();</span>
|
|
|
|
<span class="nx">info</span><span class="p">.</span><span class="nx">opencallback</span> <span class="o">=</span> <span class="nx">customFileOpen</span><span class="p">;</span>
|
|
<span class="nx">info</span><span class="p">.</span><span class="nx">closecallback</span> <span class="o">=</span> <span class="nx">customFileClose</span><span class="p">;</span>
|
|
<span class="nx">info</span><span class="p">.</span><span class="nx">readcallback</span> <span class="o">=</span> <span class="nx">customFileRead</span><span class="p">;</span>
|
|
<span class="nx">info</span><span class="p">.</span><span class="nx">seekcallback</span> <span class="o">=</span> <span class="nx">customFileSeek</span><span class="p">;</span>
|
|
<span class="nx">info</span><span class="p">.</span><span class="nx">userdata</span> <span class="o">=</span> <span class="nx">filename</span><span class="p">;</span>
|
|
|
|
<span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">loadBankCustom</span><span class="p">(</span><span class="nx">info</span><span class="p">,</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">STUDIO_LOAD_BANK_NONBLOCKING</span><span class="p">,</span> <span class="nx">outval</span><span class="p">);</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<p>In this case the filename is passed as userdata to let the callback get information for what file to load.<br />
|
|
Here is the customFileOpen callback getting the filename and opening a file handle.<br />
|
|
The file is opened in this case with a special FMOD provided file API. Replace this with your own API.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">function</span> <span class="nx">customFileOpen</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">filesize</span><span class="p">,</span> <span class="nx">handle</span><span class="p">,</span> <span class="nx">userdata</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">filesize_outval</span> <span class="o">=</span> <span class="p">{};</span>
|
|
<span class="kd">var</span> <span class="nx">handle_outval</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="c1">// We pass the filename into our callbacks via userdata in the custom info struct</span>
|
|
<span class="kd">var</span> <span class="nx">filename</span> <span class="o">=</span> <span class="nx">userdata</span><span class="p">;</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_open</span><span class="p">(</span><span class="nx">gSystemLowLevel</span><span class="p">,</span> <span class="nx">filename</span><span class="p">,</span> <span class="nx">filesize_outval</span><span class="p">,</span> <span class="nx">handle_outval</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span> <span class="o">==</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">OK</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">filesize</span><span class="p">.</span><span class="nx">val</span> <span class="o">=</span> <span class="nx">filesize_outval</span><span class="p">.</span><span class="nx">val</span><span class="p">;</span>
|
|
<span class="nx">handle</span><span class="p">.</span><span class="nx">val</span> <span class="o">=</span> <span class="nx">handle_outval</span><span class="p">.</span><span class="nx">val</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
<p>To read data in the callback, into the buffer that FMOD has provided, FMOD has used a special technique where it passes the memory address, instead of a javascript buffer.<br />
|
|
This means to write data to FMOD's buffer you <strong>must</strong> use FMOD.setValue using the buffer address, writing the data in a loop, a byte at a time. This could be optimized somewhat by using i32 to write 4 bytes at a time.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">function</span> <span class="nx">customFileRead</span><span class="p">(</span><span class="nx">handle</span><span class="p">,</span> <span class="nx">buffer</span><span class="p">,</span> <span class="nx">sizebytes</span><span class="p">,</span> <span class="nx">bytesread</span><span class="p">,</span> <span class="nx">userdata</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">bytesread_outval</span> <span class="o">=</span> <span class="p">{};</span>
|
|
<span class="kd">var</span> <span class="nx">buffer_outval</span> <span class="o">=</span> <span class="p">{};</span>
|
|
|
|
<span class="c1">// Read from the file into a new buffer. This part can be swapped for your own file system.</span>
|
|
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_read</span><span class="p">(</span><span class="nx">handle</span><span class="p">,</span> <span class="nx">buffer_outval</span><span class="p">,</span> <span class="nx">sizebytes</span><span class="p">,</span> <span class="nx">bytesread_outval</span><span class="p">)</span> <span class="c1">// read produces a new array with data.</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span> <span class="o">==</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">OK</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">bytesread</span><span class="p">.</span><span class="nx">val</span> <span class="o">=</span> <span class="nx">bytesread_outval</span><span class="p">.</span><span class="nx">val</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1">// Copy the new buffer contents into the buffer that is passed into the callback. 'buffer' is a memory address, so we can only write to it with FMOD.setValue</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">count</span> <span class="o"><</span> <span class="nx">bytesread</span><span class="p">.</span><span class="nx">val</span><span class="p">;</span> <span class="nx">count</span><span class="o">++</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="nx">buffer</span> <span class="o">+</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">buffer_outval</span><span class="p">.</span><span class="nx">val</span><span class="p">[</span><span class="nx">count</span><span class="p">],</span> <span class="s1">'i8'</span><span class="p">);</span> <span class="c1">// See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#accessing-memory for docs on setValue.</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
<h3 id="javascript-specific-functions-for-fmod"><a href="#javascript-specific-functions-for-fmod">JavaScript specific functions for FMOD</a></h3>
|
|
<h4 id="helper-functions"><a href="#helper-functions">Helper functions</a></h4>
|
|
<p>FMOD comes with some functions to aid with reading file data and writing to memory buffers.<br />
|
|
Here is the list of functions that are provided.</p>
|
|
<h4 id="system"><a href="#system">System</a></h4>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">[</span><span class="s1">'preRun'</span><span class="p">]</span> <span class="o">=</span> <span class="nx">callback</span> <span class="c1">// Variable to assign a function callback to. Will be called before FMOD runs, but after the Emscripten runtime has initialized</span>
|
|
<span class="nx">FMOD</span><span class="p">[</span><span class="s1">'onRuntimeInitialized'</span><span class="p">]</span> <span class="o">=</span> <span class="nx">callback</span> <span class="c1">// Assign a function to this member of FMOD, pre Called when the Emscripten runtime has initialized **</span>
|
|
<span class="nx">FMODModule</span><span class="p">(</span><span class="nx">fmodobject</span><span class="p">)</span> <span class="c1">// Constructor function to set up FMOD object before use. fmodobject = the main FMOD object you will use throughout the application lifetime.</span>
|
|
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">FS_createPreloadedFile</span> <span class="c1">// Mounts a local file so that FMOD can recognize it when calling a function that uses a filename (ie loadBank/createSound). See https://emscripten.org/docs/api_reference/Filesystem-API.html#FS.createPreloadedFile for more on this function.</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">System_Create</span> <span class="c1">// Only exported in FMOD.JS or FMODL.JS (Only use this function if using pure Core API). See docs for System_Create</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">Studio_System_Create</span> <span class="c1">// Only exported in FMODSTUDIO.JS or FMODSTUDIOL.JS (Only use this function if using Studio API). See docs for Studio::System_Create</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">ReadFile</span> <span class="c1">// Read the entire contents of a file into a memory variable, as preloaded by FMOD.FS_createPreloadedFile. Call FMOD.Memory_Free on the variable after using it. NOTE: output variable has 'val' and 'length' as the JS members to use as parameters to System::loadBankMemory.</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">Memory_Free</span> <span class="c1">// Free memory allocated by FMOD internally in FMOD.ReadFile</span>
|
|
</pre></div>
|
|
|
|
<h4 id="file"><a href="#file">File</a></h4>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_open</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_close</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_read</span>
|
|
<span class="nx">FMOD</span><span class="p">.</span><span class="nx">file_seek</span>
|
|
</pre></div>
|
|
|
|
<h4 id="misc"><a href="#misc">Misc</a></h4>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">.</span><span class="nx">setValue</span> <span class="c1">// See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#accessing-memory for docs on setValue.</span>
|
|
</pre></div>
|
|
|
|
<h3 id="linking-fmod-for-html5-in-a-c-program-that-is-to-be-converted-via-emscripten"><a href="#linking-fmod-for-html5-in-a-c-program-that-is-to-be-converted-via-emscripten">Linking FMOD for HTML5 in a C program that is to be converted via emscripten</a></h3>
|
|
<p>You should be able to port existing C code with no special HTML5 related functionality. Link the fmod.bc file or the fmodstudio.bc file (not both!) into your application to get it to link.<br />
|
|
As mentioned previously <a class="apilink" href="core-api-common.html#fmod_nonblocking">FMOD_NONBLOCKING</a> will not be needed, so your program might hang if <a class="apilink" href="core-api-system.html#system_update">System::update</a> is not processed during any logic that waits on a getState function.</p>
|
|
<h3 id="performance-and-memory"><a href="#performance-and-memory">Performance and Memory</a></h3>
|
|
<h4 id="cpu-overhead"><a href="#cpu-overhead">CPU Overhead</a></h4>
|
|
<p>By default FMOD mixes at 48000hz. If the browser is not running at that rate, it will introduce a resampler to convert the rate, which consumes CPU time and adds a DSP block worth of latency.<br />
|
|
This can be solved by querying the hardware's rate before <a class="apilink" href="core-api-system.html#system_init">System::init</a>, and calling <a class="apilink" href="core-api-system.html#system_setsoftwareformat">System::setSoftwareFormat</a> to the same rate as the output. Here is an example (from the PlaySound example):</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="kd">var</span> <span class="nx">outval</span> <span class="o">=</span> <span class="p">{};</span>
|
|
<span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">getDriverInfo</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">outval</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
<span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">setSoftwareFormat</span><span class="p">(</span><span class="nx">outval</span><span class="p">.</span><span class="nx">val</span><span class="p">,</span> <span class="nx">FMOD</span><span class="p">.</span><span class="nx">SPEAKERMODE_DEFAULT</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<h4 id="audio-stability-stuttering"><a href="#audio-stability-stuttering">Audio Stability (Stuttering)</a></h4>
|
|
<p>Some devices cannot handle the default buffer size of 4 blocks of 1024 samples (4096 samples) without stuttering, so to avoid this set the buffer size in your application to 2 blocks of 2048.<br />
|
|
Here is an example</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">result</span> <span class="o">=</span> <span class="nx">gSystem</span><span class="p">.</span><span class="nx">setDSPBufferSize</span><span class="p">(</span><span class="mi">2048</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="nx">CHECK_RESULT</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
|
|
</pre></div>
|
|
|
|
<h4 id="threads"><a href="#threads">Threads</a></h4>
|
|
<p>As stated in the introduction, FMOD for HTML5 does not have access to any threads so any loading/mixing/decoding/streaming/dsp has to be run in a blocking mode, from the main application loop.</p>
|
|
<p>Keep this in mind when loading sounds, or implementing DSP that may take a large time slice. If the application pre-loads sounds, and has a fast enough framerate that the FMOD mixing can execute in the same frame (with time left over) then there should be no audible glitching or frame rate glitching.</p>
|
|
<h4 id="heap-memory"><a href="#heap-memory">'Heap' Memory</a></h4>
|
|
<p>FMOD defaults to 16mb of memory to load sounds with and create FMOD objects with. Use the following global before calling the main FMOD constructor object, to control how much memory to use.</p>
|
|
<div class="highlight language-javascript"><pre><span></span><span class="nx">FMOD</span><span class="p">[</span><span class="s1">'INITIAL_MEMORY'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">64</span><span class="o">*</span><span class="mi">1024</span><span class="o">*</span><span class="mi">1024</span><span class="p">;</span> <span class="c1">// (ASM.JS ONLY) FMOD Heap defaults to 16mb which is enough for this demo, but set it differently here for demonstration (64mb)</span>
|
|
</pre></div>
|
|
|
|
<p>For WASM support, FMOD uses ALLOW_MEMORY_GROWTH, which will allow memory to grow dynamically from INITIAL_MEMORY up to a maximum of 2GB.</p>
|
|
<h3 id="limitations_1"><a href="#limitations_1">Limitations</a></h3>
|
|
<h4 id="non-blocking-loading"><a href="#non-blocking-loading">Non-blocking loading</a></h4>
|
|
<p><a class="apilink" href="core-api-common.html#fmod_nonblocking">FMOD_NONBLOCKING</a> and <a class="apilink" href="studio-api-system.html#fmod_studio_load_bank_nonblocking">FMOD_STUDIO_LOAD_BANK_NONBLOCKING</a> do not allow sound to load in the background, but it will process loading from the update loop instead.</p>
|
|
<p>Streaming is executed from the main thread. This may impact performance, so pre-loading sounds is preferred.</p>
|
|
<p>Streaming infers that the source is being loaded from 'disk' which is not usually done with HTML5, because data is usually pre-packaged with the javascript file, or streamed over http (from an external URL) so loading sounds into memory might make more sense here.</p>
|
|
<h3 id="known-issues"><a href="#known-issues">Known Issues</a></h3>
|
|
<p>The following functions are not supported.<br />
|
|
Some have no place in JavaScript (ie loadPlugin) but others are incomplete at this point and can be added in a later point release.</p>
|
|
<ul>
|
|
<li><a class="apilink" href="core-api-system.html#system_loadplugin">System::loadPlugin</a></li>
|
|
<li><a class="apilink" href="core-api-geometry.html#geometry_addpolygon">Geometry::addPolygon</a></li>
|
|
<li><a class="apilink" href="core-api-geometry.html#geometry_save">Geometry::save</a></li>
|
|
</ul>
|
|
<p>The following callbacks remain unimplemented at this point, so they will not work.</p>
|
|
<ul>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_file_asyncread_callback">FMOD_FILE_ASYNCREAD_CALLBACK</a></li>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_file_asynccancel_callback">FMOD_FILE_ASYNCCANCEL_CALLBACK</a></li>
|
|
<li><a class="apilink" href="core-api-system.html#fmod_3d_rolloff_callback">FMOD_3D_ROLLOFF_CALLBACK</a></li>
|
|
<li><a class="apilink" href="studio-api-commandreplay.html#fmod_studio_commandreplay_frame_callback">FMOD_STUDIO_COMMANDREPLAY_FRAME_CALLBACK</a></li>
|
|
<li><a class="apilink" href="studio-api-commandreplay.html#fmod_studio_commandreplay_load_bank_callback">FMOD_STUDIO_COMMANDREPLAY_LOAD_BANK_CALLBACK</a></li>
|
|
<li><a class="apilink" href="studio-api-commandreplay.html#fmod_studio_commandreplay_create_instance_callback">FMOD_STUDIO_COMMANDREPLAY_CREATE_INSTANCE_CALLBACK</a></li>
|
|
</ul></div>
|
|
|
|
<p class="manual-footer">FMOD Engine User Manual 2.03.07 (2025-04-02). © 2025 Firelight Technologies Pty Ltd.</p>
|
|
</body>
|
|
</html>
|
|
|
|
</div>
|