Update website.

This commit is contained in:
David Reid
2021-12-18 21:23:14 +10:00
parent e3f8e79328
commit cb16120484
23 changed files with 7376 additions and 465 deletions
+7 -5
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Custom Backend</h1><p>
This example show how a custom backend can be implemented.
</p>
@@ -551,7 +551,8 @@ ma_format ma_format_from_sdl(MA_SDL_AudioFormat format)
tempDeviceID = ((MA_PFN_SDL_OpenAudioDevice)pContextEx-&gt;sdl.SDL_OpenAudioDevice)(pDeviceName, (deviceType == ma_device_type_playback) ? 0 : 1, &amp;desiredSpec, &amp;obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
<span style="color:#0033ff">if</span> (tempDeviceID == 0) {
<span style="color:#0033ff">return</span> ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, <span style="color:#cc3300">&quot;Failed to open SDL device.&quot;</span>, MA_FAILED_TO_OPEN_BACKEND_DEVICE);
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, <span style="color:#cc3300">&quot;Failed to open SDL device.&quot;</span>);
<span style="color:#0033ff">return</span> MA_FAILED_TO_OPEN_BACKEND_DEVICE;
}
((MA_PFN_SDL_CloseAudioDevice)pContextEx-&gt;sdl.SDL_CloseAudioDevice)(tempDeviceID);
@@ -658,7 +659,8 @@ ma_format ma_format_from_sdl(MA_SDL_AudioFormat format)
deviceID = ((MA_PFN_SDL_OpenAudioDevice)pContextEx-&gt;sdl.SDL_OpenAudioDevice)(pDeviceName, (pConfig-&gt;deviceType == ma_device_type_playback) ? 0 : 1, &amp;desiredSpec, &amp;obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
<span style="color:#0033ff">if</span> (deviceID == 0) {
<span style="color:#0033ff">return</span> ma_post_error((<span style="color:#0099cc">ma_device</span>*)pDeviceEx, MA_LOG_LEVEL_ERROR, <span style="color:#cc3300">&quot;Failed to open SDL2 device.&quot;</span>, MA_FAILED_TO_OPEN_BACKEND_DEVICE);
ma_log_postf(ma_device_get_log((<span style="color:#0099cc">ma_device</span>*)pDeviceEx), MA_LOG_LEVEL_ERROR, <span style="color:#cc3300">&quot;Failed to open SDL2 device.&quot;</span>);
<span style="color:#0033ff">return</span> MA_FAILED_TO_OPEN_BACKEND_DEVICE;
}
<span style="color:#0033ff">if</span> (pConfig-&gt;deviceType == ma_device_type_playback) {
@@ -671,7 +673,7 @@ ma_format ma_format_from_sdl(MA_SDL_AudioFormat format)
pDescriptor-&gt;format = ma_format_from_sdl(obtainedSpec.format);
pDescriptor-&gt;channels = obtainedSpec.channels;
pDescriptor-&gt;sampleRate = (<span style="color:#0099cc">ma_uint32</span>)obtainedSpec.freq;
ma_get_standard_channel_map(ma_standard_channel_map_default, pDescriptor-&gt;channels, pDescriptor-&gt;channelMap);
ma_channel_map_init_standard(ma_standard_channel_map_default, pDescriptor-&gt;channelMap, ma_countof(pDescriptor-&gt;channelMap), pDescriptor-&gt;channels);
pDescriptor-&gt;periodSizeInFrames = obtainedSpec.samples;
pDescriptor-&gt;periodCount = 1; <span style="color:#009900">/* SDL doesn&#39;t use the notion of period counts, so just set to 1. */</span>
@@ -903,7 +905,7 @@ Main program starts here.
pSineWave = (<span style="color:#0099cc">ma_waveform</span>*)pDevice-&gt;pUserData;
MA_ASSERT(pSineWave != NULL);
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount);
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount, NULL);
}
<span style="color:#0033ff">if</span> (pDevice-&gt;<span style="color:#0033ff">type</span> == ma_device_type_duplex) {
+7 -15
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Custom Decoder</h1><p>
Demonstrates how to implement a custom decoder.
</p>
@@ -255,18 +255,12 @@ This example implements two custom decoders:
</p>
<ul style="overflow:hidden;">
<li>
</li>
</ul>
<ul style="overflow:hidden;">
Vorbis via libvorbis</li>
<li>
Vorbis via libvorbis
</li>
<li>
Opus via libopus
A </li>
Opus via libopus</li>
</ul>
<p>
A custom decoder must implement a data source. In this example, the libvorbis data source is called
<span style="font-family:monospace;">ma_libvorbis</span> and the Opus data source is called <span style="font-family:monospace;">ma_libopus</span>. These two objects are compatible
with the <span style="font-family:monospace;">ma_data_source</span> APIs and can be taken straight from this example and used in real code.
@@ -358,8 +352,7 @@ The <span style="font-family:monospace;">onInitFile</span>, <span style="font-fa
ma_decoding_backend_init_file__libvorbis,
NULL, <span style="color:#009900">/* onInitFileW() */</span>
NULL, <span style="color:#009900">/* onInitMemory() */</span>
ma_decoding_backend_uninit__libvorbis,
ma_decoding_backend_get_channel_map__libvorbis
ma_decoding_backend_uninit__libvorbis
};
@@ -435,8 +428,7 @@ The <span style="font-family:monospace;">onInitFile</span>, <span style="font-fa
ma_decoding_backend_init_file__libopus,
NULL, <span style="color:#009900">/* onInitFileW() */</span>
NULL, <span style="color:#009900">/* onInitMemory() */</span>
ma_decoding_backend_uninit__libopus,
ma_decoding_backend_get_channel_map__libopus
ma_decoding_backend_uninit__libopus
};
@@ -496,7 +488,7 @@ The <span style="font-family:monospace;">onInitFile</span>, <span style="font-fa
<span style="color:#009900">/* Initialize the device. */</span>
result = ma_data_source_get_data_format(&amp;decoder, &amp;format, &amp;channels, &amp;sampleRate);
result = ma_data_source_get_data_format(&amp;decoder, &amp;format, &amp;channels, &amp;sampleRate, NULL, 0);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to retrieve decoder data format.&quot;</span>);
ma_decoder_uninit(&amp;decoder);
+496
View File
@@ -0,0 +1,496 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Custom Decoder Engine</h1><p>
Demonstrates how to implement a custom decoder and use it with the high level API.
</p>
<p>
This is the same as the custom_decoder example, only it&#39;s used with the high level engine API
rather than the low level decoding API. You can use this to add support for Opus to your games, for
example (via libopus).</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MA_NO_VORBIS <span style="color:#009900">/* Disable the built-in Vorbis decoder to ensure the libvorbis decoder is picked. */</span>
<span style="color:#666666">#define</span> MA_NO_OPUS <span style="color:#009900">/* Disable the (not yet implemented) built-in Opus decoder to ensure the libopus decoder is picked. */</span>
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../extras/miniaudio_libvorbis.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../extras/miniaudio_libopus.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&lt;stdio.h&gt;</span>
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_init__libvorbis(<span style="color:#0033ff">void</span>* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, <span style="color:#0033ff">void</span>* pReadSeekTellUserData, <span style="color:#0033ff">const</span> ma_decoding_backend_config* pConfig, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks, <span style="color:#0099cc">ma_data_source</span>** ppBackend)
{
<span style="color:#0099cc">ma_result</span> result;
ma_libvorbis* pVorbis;
(<span style="color:#0033ff">void</span>)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(<span style="color:#0033ff">sizeof</span>(*pVorbis), pAllocationCallbacks);
<span style="color:#0033ff">if</span> (pVorbis == NULL) {
<span style="color:#0033ff">return</span> MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
<span style="color:#0033ff">return</span> result;
}
*ppBackend = pVorbis;
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_init_file__libvorbis(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0033ff">const</span> <span style="color:#0033ff">char</span>* pFilePath, <span style="color:#0033ff">const</span> ma_decoding_backend_config* pConfig, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks, <span style="color:#0099cc">ma_data_source</span>** ppBackend)
{
<span style="color:#0099cc">ma_result</span> result;
ma_libvorbis* pVorbis;
(<span style="color:#0033ff">void</span>)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(<span style="color:#0033ff">sizeof</span>(*pVorbis), pAllocationCallbacks);
<span style="color:#0033ff">if</span> (pVorbis == NULL) {
<span style="color:#0033ff">return</span> MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
<span style="color:#0033ff">return</span> result;
}
*ppBackend = pVorbis;
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
<span style="color:#0033ff">static</span> <span style="color:#0033ff">void</span> ma_decoding_backend_uninit__libvorbis(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0099cc">ma_data_source</span>* pBackend, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
(<span style="color:#0033ff">void</span>)pUserData;
ma_libvorbis_uninit(pVorbis, pAllocationCallbacks);
ma_free(pVorbis, pAllocationCallbacks);
}
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_get_channel_map__libvorbis(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0099cc">ma_data_source</span>* pBackend, <span style="color:#0099cc">ma_channel</span>* pChannelMap, size_t channelMapCap)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
(<span style="color:#0033ff">void</span>)pUserData;
<span style="color:#0033ff">return</span> ma_libvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
}
<span style="color:#0033ff">static</span> ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libvorbis =
{
ma_decoding_backend_init__libvorbis,
ma_decoding_backend_init_file__libvorbis,
NULL, <span style="color:#009900">/* onInitFileW() */</span>
NULL, <span style="color:#009900">/* onInitMemory() */</span>
ma_decoding_backend_uninit__libvorbis
};
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_init__libopus(<span style="color:#0033ff">void</span>* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, <span style="color:#0033ff">void</span>* pReadSeekTellUserData, <span style="color:#0033ff">const</span> ma_decoding_backend_config* pConfig, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks, <span style="color:#0099cc">ma_data_source</span>** ppBackend)
{
<span style="color:#0099cc">ma_result</span> result;
ma_libopus* pOpus;
(<span style="color:#0033ff">void</span>)pUserData;
pOpus = (ma_libopus*)ma_malloc(<span style="color:#0033ff">sizeof</span>(*pOpus), pAllocationCallbacks);
<span style="color:#0033ff">if</span> (pOpus == NULL) {
<span style="color:#0033ff">return</span> MA_OUT_OF_MEMORY;
}
result = ma_libopus_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pOpus);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_free(pOpus, pAllocationCallbacks);
<span style="color:#0033ff">return</span> result;
}
*ppBackend = pOpus;
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_init_file__libopus(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0033ff">const</span> <span style="color:#0033ff">char</span>* pFilePath, <span style="color:#0033ff">const</span> ma_decoding_backend_config* pConfig, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks, <span style="color:#0099cc">ma_data_source</span>** ppBackend)
{
<span style="color:#0099cc">ma_result</span> result;
ma_libopus* pOpus;
(<span style="color:#0033ff">void</span>)pUserData;
pOpus = (ma_libopus*)ma_malloc(<span style="color:#0033ff">sizeof</span>(*pOpus), pAllocationCallbacks);
<span style="color:#0033ff">if</span> (pOpus == NULL) {
<span style="color:#0033ff">return</span> MA_OUT_OF_MEMORY;
}
result = ma_libopus_init_file(pFilePath, pConfig, pAllocationCallbacks, pOpus);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_free(pOpus, pAllocationCallbacks);
<span style="color:#0033ff">return</span> result;
}
*ppBackend = pOpus;
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
<span style="color:#0033ff">static</span> <span style="color:#0033ff">void</span> ma_decoding_backend_uninit__libopus(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0099cc">ma_data_source</span>* pBackend, <span style="color:#0033ff">const</span> ma_allocation_callbacks* pAllocationCallbacks)
{
ma_libopus* pOpus = (ma_libopus*)pBackend;
(<span style="color:#0033ff">void</span>)pUserData;
ma_libopus_uninit(pOpus, pAllocationCallbacks);
ma_free(pOpus, pAllocationCallbacks);
}
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_decoding_backend_get_channel_map__libopus(<span style="color:#0033ff">void</span>* pUserData, <span style="color:#0099cc">ma_data_source</span>* pBackend, <span style="color:#0099cc">ma_channel</span>* pChannelMap, size_t channelMapCap)
{
ma_libopus* pOpus = (ma_libopus*)pBackend;
(<span style="color:#0033ff">void</span>)pUserData;
<span style="color:#0033ff">return</span> ma_libopus_get_data_format(pOpus, NULL, NULL, NULL, pChannelMap, channelMapCap);
}
<span style="color:#0033ff">static</span> ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libopus =
{
ma_decoding_backend_init__libopus,
ma_decoding_backend_init_file__libopus,
NULL, <span style="color:#009900">/* onInitFileW() */</span>
NULL, <span style="color:#009900">/* onInitMemory() */</span>
ma_decoding_backend_uninit__libopus
};
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
ma_resource_manager_config resourceManagerConfig;
ma_resource_manager resourceManager;
ma_engine_config engineConfig;
ma_engine engine;
<span style="color:#009900">/*
Add your custom backend vtables here. The order in the array defines the order of priority. The
vtables will be passed in to the resource manager config.
*/</span>
ma_decoding_backend_vtable* pCustomBackendVTables[] =
{
&amp;g_ma_decoding_backend_vtable_libvorbis,
&amp;g_ma_decoding_backend_vtable_libopus
};
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input file.\n&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Using custom decoding backends requires a resource manager. */</span>
resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.ppCustomDecodingBackendVTables = pCustomBackendVTables;
resourceManagerConfig.customDecodingBackendCount = <span style="color:#0033ff">sizeof</span>(pCustomBackendVTables) / <span style="color:#0033ff">sizeof</span>(pCustomBackendVTables[0]);
resourceManagerConfig.pCustomDecodingBackendUserData = NULL; <span style="color:#009900">/* &lt;-- This will be passed in to the pUserData parameter of each function in the decoding backend vtables. */</span>
result = ma_resource_manager_init(&amp;resourceManagerConfig, &amp;resourceManager);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize resource manager.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Once we have a resource manager we can create the engine. */</span>
engineConfig = ma_engine_config_init();
engineConfig.pResourceManager = &amp;resourceManager;
result = ma_engine_init(&amp;engineConfig, &amp;engine);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize engine.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Now we can play our sound. */</span>
result = ma_engine_play_sound(&amp;engine, argv[1], NULL);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to play sound.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
<span style="color:#0033ff">return</span> 0;
}</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+437
View File
@@ -0,0 +1,437 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Data Source Chaining</h1><p>
Demonstrates one way to chain together a number of data sources so they play back seamlessly
without gaps.
</p>
<p>
This example uses the chaining system built into the <span style="font-family:monospace;">ma_data_source</span> API. It will take every sound
passed onto the command line in order, and then loop back and start again. When looping a chain of
data sources, you need only link the last data source back to the first one.
</p>
<p>
To play a chain of data sources, you first need to set up your chain. To set the data source that
should be played after another, you have two options:
</p>
<ul style="overflow:hidden;">
<li>
Set a pointer to a specific data source</li>
<li>
Set a callback that will fire when the next data source needs to be retrieved</li>
</ul>
<p>
The first option is good for simple scenarios. The second option is useful if you need to perform
some action when the end of a sound is reached. This example will be using both.
</p>
<p>
When reading data from a chain, you always read from the head data source. Internally miniaudio
will track a pointer to the data source in the chain that is currently playing. If you don&#39;t
consistently read from the head data source this state will become inconsistent and things won&#39;t
work correctly. When using a chain, this pointer needs to be reset if you need to play the
chain again from the start:
</p>
<p>
</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
ma_data_source_set_current(&amp;headDataSource, &amp;headDataSource);
ma_data_source_seek_to_pcm_frame(&amp;headDataSource, 0);
</pre></div><p>
The code above is setting the &quot;current&quot; data source in the chain to the head data source, thereby
starting the chain from the start again. It is also seeking the head data source back to the start
so that playback starts from the start as expected. You do not need to seek non-head items back to
the start as miniaudio will do that for you internally.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&lt;stdio.h&gt;</span>
<span style="color:#009900">/*
For simplicity, this example requires the device to use floating point samples.
*/</span>
<span style="color:#666666">#define</span> SAMPLE_FORMAT ma_format_f32
<span style="color:#666666">#define</span> CHANNEL_COUNT 2
<span style="color:#666666">#define</span> SAMPLE_RATE 48000
<span style="color:#0099cc">ma_uint32</span> g_decoderCount;
<span style="color:#0099cc">ma_decoder</span>* g_pDecoders;
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_data_source</span>* next_callback_tail(<span style="color:#0099cc">ma_data_source</span>* pDataSource)
{
MA_ASSERT(g_decoderCount &gt; 0); <span style="color:#009900">/* &lt;-- We check for this in main() so should never happen. */</span>
<span style="color:#009900">/*
This will be fired when the last item in the chain has reached the end. In this example we want
to loop back to the start, so we need only return a pointer back to the head.
*/</span>
<span style="color:#0033ff">return</span> &amp;g_pDecoders[0];
}
<span style="color:#0033ff">static</span> <span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
<span style="color:#009900">/*
We can just read from the first decoder and miniaudio will resolve the chain for us. Note that
if you want to loop the chain, like we&#39;re doing in this example, you need to set the <span style="font-family:monospace;">loop</span>
parameter to false, or else only the current data source will be looped.
*/</span>
ma_data_source_read_pcm_frames(&amp;g_pDecoders[0], pOutput, frameCount, NULL);
<span style="color:#009900">/* Unused in this example. */</span>
(<span style="color:#0033ff">void</span>)pDevice;
(<span style="color:#0033ff">void</span>)pInput;
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result = MA_SUCCESS;
<span style="color:#0099cc">ma_uint32</span> iDecoder;
<span style="color:#0099cc">ma_decoder_config</span> decoderConfig;
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
<span style="color:#0099cc">ma_device</span> device;
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input files.\n&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
g_decoderCount = argc-1;
g_pDecoders = (<span style="color:#0099cc">ma_decoder</span>*)malloc(<span style="color:#0033ff">sizeof</span>(*g_pDecoders) * g_decoderCount);
<span style="color:#009900">/* In this example, all decoders need to have the same output format. */</span>
decoderConfig = ma_decoder_config_init(SAMPLE_FORMAT, CHANNEL_COUNT, SAMPLE_RATE);
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder &lt; g_decoderCount; ++iDecoder) {
result = ma_decoder_init_file(argv[1+iDecoder], &amp;decoderConfig, &amp;g_pDecoders[iDecoder]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0099cc">ma_uint32</span> iDecoder2;
<span style="color:#0033ff">for</span> (iDecoder2 = 0; iDecoder2 &lt; iDecoder; ++iDecoder2) {
ma_decoder_uninit(&amp;g_pDecoders[iDecoder2]);
}
free(g_pDecoders);
printf(<span style="color:#cc3300">&quot;Failed to load %s.\n&quot;</span>, argv[1+iDecoder]);
<span style="color:#0033ff">return</span> -1;
}
}
<span style="color:#009900">/*
We&#39;re going to set up our decoders to run one after the other, but then have the last one loop back
to the first one. For demonstration purposes we&#39;re going to use the callback method for the last
data source.
*/</span>
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder &lt; g_decoderCount-1; iDecoder += 1) {
ma_data_source_set_next(&amp;g_pDecoders[iDecoder], &amp;g_pDecoders[iDecoder+1]);
}
<span style="color:#009900">/*
For the last data source we&#39;ll loop back to the start, but for demonstration purposes we&#39;ll use a
callback to determine the next data source in the chain.
*/</span>
ma_data_source_set_next_callback(&amp;g_pDecoders[g_decoderCount-1], next_callback_tail);
<span style="color:#009900">/*
The data source chain has been established so now we can get the device up and running so we
can listen to it.
*/</span>
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = SAMPLE_FORMAT;
deviceConfig.playback.channels = CHANNEL_COUNT;
deviceConfig.sampleRate = SAMPLE_RATE;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = NULL;
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &amp;deviceConfig, &amp;device) != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to open playback device.\n&quot;</span>);
result = -1;
<span style="color:#0033ff">goto</span> done_decoders;
}
<span style="color:#0033ff">if</span> (ma_device_start(&amp;device) != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to start playback device.\n&quot;</span>);
result = -1;
<span style="color:#0033ff">goto</span> done;
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
done:
ma_device_uninit(&amp;device);
done_decoders:
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder &lt; g_decoderCount; ++iDecoder) {
ma_decoder_uninit(&amp;g_pDecoders[iDecoder]);
}
free(g_pDecoders);
<span style="color:#0033ff">return</span> 0;
}</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+415
View File
@@ -0,0 +1,415 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Duplex Effect</h1><p>
Demonstrates how to apply an effect to a duplex stream using the node graph system.
</p>
<p>
This example applies a vocoder effect to the input stream before outputting it. A custom node
called <span style="font-family:monospace;">ma_vocoder_node</span> is used to achieve the effect which can be found in the extras folder in
the miniaudio repository. The vocoder node uses <a href="https://github.com/blastbay/voclib">https://github.com/blastbay/voclib</a> to achieve the
effect.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../extras/nodes/ma_vocoder_node/ma_vocoder_node.c&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&lt;stdio.h&gt;</span>
<span style="color:#666666">#define</span> DEVICE_FORMAT ma_format_f32; <span style="color:#009900">/* Must always be f32 for this example because the node graph system only works with this. */</span>
<span style="color:#666666">#define</span> DEVICE_CHANNELS 1 <span style="color:#009900">/* For this example, always set to 1. */</span>
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_waveform</span> g_sourceData; <span style="color:#009900">/* The underlying data source of the excite node. */</span>
<span style="color:#0033ff">static</span> ma_audio_buffer_ref g_exciteData; <span style="color:#009900">/* The underlying data source of the source node. */</span>
<span style="color:#0033ff">static</span> ma_data_source_node g_sourceNode; <span style="color:#009900">/* A data source node containing the source data we&#39;ll be sending through to the vocoder. This will be routed into the first bus of the vocoder node. */</span>
<span style="color:#0033ff">static</span> ma_data_source_node g_exciteNode; <span style="color:#009900">/* A data source node containing the excite data we&#39;ll be sending through to the vocoder. This will be routed into the second bus of the vocoder node. */</span>
<span style="color:#0033ff">static</span> ma_vocoder_node g_vocoderNode; <span style="color:#009900">/* The vocoder node. */</span>
<span style="color:#0033ff">static</span> ma_node_graph g_nodeGraph;
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
MA_ASSERT(pDevice-&gt;capture.format == pDevice-&gt;playback.format);
MA_ASSERT(pDevice-&gt;capture.channels == pDevice-&gt;playback.channels);
<span style="color:#009900">/*
The node graph system is a pulling style of API. At the lowest level of the chain will be a
node acting as a data source for the purpose of delivering the initial audio data. In our case,
the data source is our <span style="font-family:monospace;">pInput</span> buffer. We need to update the underlying data source so that it
read data from <span style="font-family:monospace;">pInput</span>.
*/</span>
ma_audio_buffer_ref_set_data(&amp;g_exciteData, pInput, frameCount);
<span style="color:#009900">/* With the source buffer configured we can now read directly from the node graph. */</span>
ma_node_graph_read_pcm_frames(&amp;g_nodeGraph, pOutput, frameCount, NULL);
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
<span style="color:#0099cc">ma_device</span> device;
ma_node_graph_config nodeGraphConfig;
ma_vocoder_node_config vocoderNodeConfig;
ma_data_source_node_config sourceNodeConfig;
ma_data_source_node_config exciteNodeConfig;
<span style="color:#0099cc">ma_waveform_config</span> waveformConfig;
deviceConfig = ma_device_config_init(ma_device_type_duplex);
deviceConfig.capture.pDeviceID = NULL;
deviceConfig.capture.format = DEVICE_FORMAT;
deviceConfig.capture.channels = DEVICE_CHANNELS;
deviceConfig.capture.shareMode = ma_share_mode_shared;
deviceConfig.playback.pDeviceID = NULL;
deviceConfig.playback.format = DEVICE_FORMAT;
deviceConfig.playback.channels = DEVICE_CHANNELS;
deviceConfig.dataCallback = data_callback;
result = ma_device_init(NULL, &amp;deviceConfig, &amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">return</span> result;
}
<span style="color:#009900">/* Now we can setup our node graph. */</span>
nodeGraphConfig = ma_node_graph_config_init(device.capture.channels);
result = ma_node_graph_init(&amp;nodeGraphConfig, NULL, &amp;g_nodeGraph);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize node graph.&quot;</span>);
<span style="color:#0033ff">goto</span> done0;
}
<span style="color:#009900">/* Vocoder. Attached straight to the endpoint. */</span>
vocoderNodeConfig = ma_vocoder_node_config_init(device.capture.channels, device.sampleRate);
result = ma_vocoder_node_init(&amp;g_nodeGraph, &amp;vocoderNodeConfig, NULL, &amp;g_vocoderNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize vocoder node.&quot;</span>);
<span style="color:#0033ff">goto</span> done1;
}
ma_node_attach_output_bus(&amp;g_vocoderNode, 0, ma_node_graph_get_endpoint(&amp;g_nodeGraph), 0);
<span style="color:#009900">/* Amplify the volume of the vocoder output because in my testing it is a bit quiet. */</span>
ma_node_set_output_bus_volume(&amp;g_vocoderNode, 0, 4);
<span style="color:#009900">/* Source/carrier. Attached to input bus 0 of the vocoder node. */</span>
waveformConfig = ma_waveform_config_init(device.capture.format, device.capture.channels, device.sampleRate, ma_waveform_type_sawtooth, 1.0, 50);
result = ma_waveform_init(&amp;waveformConfig, &amp;g_sourceData);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize waveform for excite node.&quot;</span>);
<span style="color:#0033ff">goto</span> done3;
}
sourceNodeConfig = ma_data_source_node_config_init(&amp;g_sourceData);
result = ma_data_source_node_init(&amp;g_nodeGraph, &amp;sourceNodeConfig, NULL, &amp;g_sourceNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize excite node.&quot;</span>);
<span style="color:#0033ff">goto</span> done3;
}
ma_node_attach_output_bus(&amp;g_sourceNode, 0, &amp;g_vocoderNode, 0);
<span style="color:#009900">/* Excite/modulator. Attached to input bus 1 of the vocoder node. */</span>
result = ma_audio_buffer_ref_init(device.capture.format, device.capture.channels, NULL, 0, &amp;g_exciteData);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize audio buffer for source.&quot;</span>);
<span style="color:#0033ff">goto</span> done2;
}
exciteNodeConfig = ma_data_source_node_config_init(&amp;g_exciteData);
result = ma_data_source_node_init(&amp;g_nodeGraph, &amp;exciteNodeConfig, NULL, &amp;g_exciteNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize source node.&quot;</span>);
<span style="color:#0033ff">goto</span> done2;
}
ma_node_attach_output_bus(&amp;g_exciteNode, 0, &amp;g_vocoderNode, 1);
ma_device_start(&amp;device);
printf(<span style="color:#cc3300">&quot;Press Enter to quit...\n&quot;</span>);
getchar();
<span style="color:#009900">/* It&#39;s important that we stop the device first or else we&#39;ll uninitialize the graph from under the device. */</span>
ma_device_stop(&amp;device);
<span style="color:#009900">/*done4:*/</span> ma_data_source_node_uninit(&amp;g_exciteNode, NULL);
done3: ma_data_source_node_uninit(&amp;g_sourceNode, NULL);
done2: ma_vocoder_node_uninit(&amp;g_vocoderNode, NULL);
done1: ma_node_graph_uninit(&amp;g_nodeGraph, NULL);
done0: ma_device_uninit(&amp;device);
(<span style="color:#0033ff">void</span>)argc;
(<span style="color:#0033ff">void</span>)argv;
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+524
View File
@@ -0,0 +1,524 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Engine Advanced</h1><p>
This example demonstrates some of the advanced features of the high level engine API.
</p>
<p>
The following features are demonstrated:
</p>
<ul style="overflow:hidden;">
<li>
Initialization of the engine from a pre-initialized device.</li>
<li>
Self-managed resource managers.</li>
<li>
Multiple engines with a shared resource manager.</li>
<li>
Creation and management of <span style="font-family:monospace;">ma_sound</span> objects.</li>
</ul>
<p>
This example will play the sound that&#39;s passed in on the command line.
</p>
<p>
Using a shared resource manager, as we do in this example, is useful for when you want to user
multiple engines so that you can output to multiple playback devices simultaneoulys. An example
might be a local co-op multiplayer game where each player has their own headphones.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#define</span> MAX_DEVICES 2
<span style="color:#666666">#define</span> MAX_SOUNDS 32
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
(<span style="color:#0033ff">void</span>)pInput;
<span style="color:#009900">/*
Since we&#39;re managing the underlying device ourselves, we need to read from the engine directly.
To do this we need access to the <span style="font-family:monospace;">ma_engine</span> object which we passed in to the user data. One
advantage of this is that you could do your own audio processing in addition to the engine&#39;s
standard processing.
*/</span>
ma_engine_read_pcm_frames((ma_engine*)pDevice-&gt;pUserData, pOutput, frameCount, NULL);
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0099cc">ma_context</span> context;
ma_resource_manager_config resourceManagerConfig;
ma_resource_manager resourceManager;
ma_engine engines[MAX_DEVICES];
<span style="color:#0099cc">ma_device</span> devices[MAX_DEVICES];
<span style="color:#0099cc">ma_uint32</span> engineCount = 0;
<span style="color:#0099cc">ma_uint32</span> iEngine;
<span style="color:#0099cc">ma_device_info</span>* pPlaybackDeviceInfos;
<span style="color:#0099cc">ma_uint32</span> playbackDeviceCount;
<span style="color:#0099cc">ma_uint32</span> iAvailableDevice;
<span style="color:#0099cc">ma_uint32</span> iChosenDevice;
ma_sound sounds[MAX_SOUNDS];
<span style="color:#0099cc">ma_uint32</span> soundCount;
<span style="color:#0099cc">ma_uint32</span> iSound;
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input file.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
We are going to be initializing multiple engines. In order to save on memory usage we can use a self managed
resource manager so we can share a single resource manager across multiple engines.
*/</span>
resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.decodedFormat = ma_format_f32; <span style="color:#009900">/* ma_format_f32 should almost always be used as that&#39;s what the engine (and most everything else) uses for mixing. */</span>
resourceManagerConfig.decodedChannels = 0; <span style="color:#009900">/* Setting the channel count to 0 will cause sounds to use their native channel count. */</span>
resourceManagerConfig.decodedSampleRate = 48000; <span style="color:#009900">/* Using a consistent sample rate is useful for avoiding expensive resampling in the audio thread. This will result in resampling being performed by the loading thread(s). */</span>
result = ma_resource_manager_init(&amp;resourceManagerConfig, &amp;resourceManager);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize resource manager.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* We&#39;re going to want a context so we can enumerate our playback devices. */</span>
result = ma_context_init(NULL, 0, NULL, &amp;context);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize context.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
Now that we have a context we will want to enumerate over each device so we can display them to the user and give
them a chance to select the output devices they want to use.
*/</span>
result = ma_context_get_devices(&amp;context, &amp;pPlaybackDeviceInfos, &amp;playbackDeviceCount, NULL, NULL);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to enumerate playback devices.&quot;</span>);
ma_context_uninit(&amp;context);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* We have our devices, so now we want to get the user to select the devices they want to output to. */</span>
engineCount = 0;
<span style="color:#0033ff">for</span> (iChosenDevice = 0; iChosenDevice &lt; MAX_DEVICES; iChosenDevice += 1) {
<span style="color:#0033ff">int</span> <span style="color:#0033ff">c</span> = 0;
<span style="color:#0033ff">for</span> (;;) {
printf(<span style="color:#cc3300">&quot;Select playback device %d ([%d - %d], Q to quit):\n&quot;</span>, iChosenDevice+1, 0, ma_min((<span style="color:#0033ff">int</span>)playbackDeviceCount, 9));
<span style="color:#0033ff">for</span> (iAvailableDevice = 0; iAvailableDevice &lt; playbackDeviceCount; iAvailableDevice += 1) {
printf(<span style="color:#cc3300">&quot; %d: %s\n&quot;</span>, iAvailableDevice, pPlaybackDeviceInfos[iAvailableDevice].name);
}
<span style="color:#0033ff">for</span> (;;) {
<span style="color:#0033ff">c</span> = getchar();
<span style="color:#0033ff">if</span> (<span style="color:#0033ff">c</span> != <span style="color:#cc3300">&#39;\n&#39;</span>) {
<span style="color:#0033ff">break</span>;
}
}
<span style="color:#0033ff">if</span> (<span style="color:#0033ff">c</span> == <span style="color:#cc3300">&#39;q&#39;</span> || <span style="color:#0033ff">c</span> == <span style="color:#cc3300">&#39;Q&#39;</span>) {
<span style="color:#0033ff">return</span> 0; <span style="color:#009900">/* User aborted. */</span>
}
<span style="color:#0033ff">if</span> (<span style="color:#0033ff">c</span> &gt;= <span style="color:#cc3300">&#39;0&#39;</span> &amp;&amp; <span style="color:#0033ff">c</span> &lt;= <span style="color:#cc3300">&#39;9&#39;</span>) {
<span style="color:#0033ff">c</span> -= <span style="color:#cc3300">&#39;0&#39;</span>;
<span style="color:#0033ff">if</span> (<span style="color:#0033ff">c</span> &lt; (<span style="color:#0033ff">int</span>)playbackDeviceCount) {
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
ma_engine_config engineConfig;
<span style="color:#009900">/*
Create the device first before the engine. We&#39;ll specify the device in the engine&#39;s config. This is optional. When a device is
not pre-initialized the engine will create one for you internally. The device does not need to be started here - the engine will
do that for us in <span style="font-family:monospace;">ma_engine_start()</span>. The device&#39;s format is derived from the resource manager, but can be whatever you want.
It&#39;s useful to keep the format consistent with the resource manager to avoid data conversions costs in the audio callback. In
this example we&#39;re using the resource manager&#39;s sample format and sample rate, but leaving the channel count set to the device&#39;s
native channels. You can use whatever format/channels/rate you like.
*/</span>
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.pDeviceID = &amp;pPlaybackDeviceInfos[<span style="color:#0033ff">c</span>].id;
deviceConfig.playback.format = resourceManager.config.decodedFormat;
deviceConfig.playback.channels = 0;
deviceConfig.sampleRate = resourceManager.config.decodedSampleRate;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &amp;engines[engineCount];
result = ma_device_init(&amp;context, &amp;deviceConfig, &amp;devices[engineCount]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize device for %s.\n&quot;</span>, pPlaybackDeviceInfos[<span style="color:#0033ff">c</span>].name);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Now that we have the device we can initialize the engine. The device is passed into the engine&#39;s config. */</span>
engineConfig = ma_engine_config_init();
engineConfig.pDevice = &amp;devices[engineCount];
engineConfig.pResourceManager = &amp;resourceManager;
engineConfig.noAutoStart = MA_TRUE; <span style="color:#009900">/* Don&#39;t start the engine by default - we&#39;ll do that manually below. */</span>
result = ma_engine_init(&amp;engineConfig, &amp;engines[engineCount]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize engine for %s.\n&quot;</span>, pPlaybackDeviceInfos[<span style="color:#0033ff">c</span>].name);
ma_device_uninit(&amp;devices[engineCount]);
<span style="color:#0033ff">return</span> -1;
}
engineCount += 1;
<span style="color:#0033ff">break</span>;
} <span style="color:#0033ff">else</span> {
printf(<span style="color:#cc3300">&quot;Invalid device number.\n&quot;</span>);
}
} <span style="color:#0033ff">else</span> {
printf(<span style="color:#cc3300">&quot;Invalid device number.\n&quot;</span>);
}
}
printf(<span style="color:#cc3300">&quot;Device %d: %s\n&quot;</span>, iChosenDevice+1, pPlaybackDeviceInfos[<span style="color:#0033ff">c</span>].name);
}
<span style="color:#009900">/* We should now have our engine&#39;s initialized. We can now start them. */</span>
<span style="color:#0033ff">for</span> (iEngine = 0; iEngine &lt; engineCount; iEngine += 1) {
result = ma_engine_start(&amp;engines[iEngine]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;WARNING: Failed to start engine %d.\n&quot;</span>, iEngine);
}
}
<span style="color:#009900">/*
At this point our engine&#39;s are running and outputting nothing but silence. To get them playing something we&#39;ll need
some sounds. In this example we&#39;re just using one sound per engine, but you can create as many as you like. Since
we&#39;re using a shared resource manager, the sound data will only be loaded once. This is how you would implement
multiple listeners.
*/</span>
soundCount = 0;
<span style="color:#0033ff">for</span> (iEngine = 0; iEngine &lt; engineCount; iEngine += 1) {
<span style="color:#009900">/* Just one sound per engine in this example. We&#39;re going to be loading this asynchronously. */</span>
result = ma_sound_init_from_file(&amp;engines[iEngine], argv[1], MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM, NULL, NULL, &amp;sounds[iEngine]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;WARNING: Failed to load sound \&quot;%s\&quot;&quot;</span>, argv[1]);
<span style="color:#0033ff">break</span>;
}
<span style="color:#009900">/*
The sound can be started as soon as ma_sound_init_from_file() returns, even for sounds that are initialized
with MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC. The sound will start playing while it&#39;s being loaded. Note that if the
asynchronous loading process cannot keep up with the rate at which you try reading you&#39;ll end up glitching.
If this is an issue, you need to not load sounds asynchronously.
*/</span>
result = ma_sound_start(&amp;sounds[iEngine]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;WARNING: Failed to start sound.&quot;</span>);
}
soundCount += 1;
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
<span style="color:#0033ff">for</span> (;;) {
<span style="color:#0033ff">int</span> <span style="color:#0033ff">c</span> = getchar();
<span style="color:#0033ff">if</span> (<span style="color:#0033ff">c</span> == <span style="color:#cc3300">&#39;\n&#39;</span>) {
<span style="color:#0033ff">break</span>;
}
}
<span style="color:#009900">/* Teardown. */</span>
<span style="color:#009900">/* The application owns the <span style="font-family:monospace;">ma_sound</span> object which means you&#39;re responsible for uninitializing them. */</span>
<span style="color:#0033ff">for</span> (iSound = 0; iSound &lt; soundCount; iSound += 1) {
ma_sound_uninit(&amp;sounds[iSound]);
}
<span style="color:#009900">/* We can now uninitialize each engine. */</span>
<span style="color:#0033ff">for</span> (iEngine = 0; iEngine &lt; engineCount; iEngine += 1) {
ma_engine_uninit(&amp;engines[iEngine]);
<span style="color:#009900">/*
The engine has been uninitialized so now lets uninitialize the device. Do this first to ensure we don&#39;t
uninitialize the resource manager from under the device while the data callback is running.
*/</span>
ma_device_uninit(&amp;devices[iEngine]);
}
<span style="color:#009900">/*
Do the resource manager last. This way we can guarantee the data callbacks of each device aren&#39;t trying to access
and data managed by the resource manager.
*/</span>
ma_resource_manager_uninit(&amp;resourceManager);
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+374
View File
@@ -0,0 +1,374 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Engine Effects</h1><p>
Demonstrates how to apply an effect to sounds using the high level engine API.
</p>
<p>
This example will load a file from the command line and apply an echo/delay effect to it. It will
show you how to manage <span style="font-family:monospace;">ma_sound</span> objects and how to insert an effect into the graph.
</p>
<p>
The <span style="font-family:monospace;">ma_engine</span> object is a node graph and is compatible with the <span style="font-family:monospace;">ma_node_graph</span> API. The
<span style="font-family:monospace;">ma_sound</span> object is a node within the node and is compatible with the <span style="font-family:monospace;">ma_node</span> API. This means
that applying an effect is as simple as inserting an effect node into the graph and plugging in the
sound&#39;s output into the effect&#39;s input. See the Node Graph example for how to use the node graph.
</p>
<p>
This example is playing only a single sound at a time which means only a single <span style="font-family:monospace;">ma_sound</span> object
it being used. If you want to play multiple sounds at the same time, even if they&#39;re for the same
sound file, you need multiple <span style="font-family:monospace;">ma_sound</span> objects.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#define</span> DELAY_IN_SECONDS 0.2f
<span style="color:#666666">#define</span> DECAY 0.25f <span style="color:#009900">/* Volume falloff for each echo. */</span>
<span style="color:#0033ff">static</span> ma_engine g_engine;
<span style="color:#0033ff">static</span> ma_sound g_sound; <span style="color:#009900">/* This example will play only a single sound at once, so we only need one <span style="font-family:monospace;">ma_sound</span> object. */</span>
<span style="color:#0033ff">static</span> ma_delay_node g_delayNode; <span style="color:#009900">/* The echo effect is achieved using a delay node. */</span>
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input file.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* The engine needs to be initialized first. */</span>
result = ma_engine_init(NULL, &amp;g_engine);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize audio engine.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
We&#39;ll build our graph starting from the end so initialize the delay node now. The output of
this node will be connected straight to the output. You could also attach it to a sound group
or any other node that accepts an input.
Creating a node requires a pointer to the node graph that owns it. The engine itself is a node
graph. In the code below we can get a pointer to the node graph with <span style="font-family:monospace;">ma_engine_get_node_graph()</span>
or we could simple cast the engine to a ma_node_graph* like so:
(ma_node_graph*)&amp;g_engine
The endpoint of the graph can be retrieved with <span style="font-family:monospace;">ma_engine_get_endpoint()</span>.
*/</span>
{
ma_delay_node_config delayNodeConfig;
<span style="color:#0099cc">ma_uint32</span> channels;
<span style="color:#0099cc">ma_uint32</span> sampleRate;
channels = ma_engine_get_channels(&amp;g_engine);
sampleRate = ma_engine_get_sample_rate(&amp;g_engine);
delayNodeConfig = ma_delay_node_config_init(channels, sampleRate, (<span style="color:#0099cc">ma_uint32</span>)(sampleRate * DELAY_IN_SECONDS), DECAY);
result = ma_delay_node_init(ma_engine_get_node_graph(&amp;g_engine), &amp;delayNodeConfig, NULL, &amp;g_delayNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize delay node.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Connect the output of the delay node to the input of the endpoint. */</span>
ma_node_attach_output_bus(&amp;g_delayNode, 0, ma_engine_get_endpoint(&amp;g_engine), 0);
}
<span style="color:#009900">/* Now we can load the sound and connect it to the delay node. */</span>
{
result = ma_sound_init_from_file(&amp;g_engine, argv[1], 0, NULL, NULL, &amp;g_sound);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize sound \&quot;%s\&quot;.&quot;</span>, argv[1]);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Connect the output of the sound to the input of the effect. */</span>
ma_node_attach_output_bus(&amp;g_sound, 0, &amp;g_delayNode, 0);
<span style="color:#009900">/*
Start the sound after it&#39;s applied to the sound. Otherwise there could be a scenario where
the very first part of it is read before the attachment to the effect is made.
*/</span>
ma_sound_start(&amp;g_sound);
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
ma_sound_uninit(&amp;g_sound);
ma_delay_node_uninit(&amp;g_delayNode, NULL);
ma_engine_uninit(&amp;g_engine);
<span style="color:#0033ff">return</span> 0;
}</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+302
View File
@@ -0,0 +1,302 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Engine Hello World</h1><p>
This example demonstrates how to initialize an audio engine and play a sound.
</p>
<p>
This will play the sound specified on the command line.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#include</span> <span style="color:#cc3300">&lt;stdio.h&gt;</span>
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
ma_engine engine;
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input file.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
result = ma_engine_init(NULL, &amp;engine);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize audio engine.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
ma_engine_play_sound(&amp;engine, argv[1], NULL);
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
ma_engine_uninit(&amp;engine);
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+4 -4
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Fixed Size Callback</h1><p>
Shows one way to implement a data callback that is called with a fixed frame count.
</p>
@@ -289,7 +289,7 @@ of data movement.</p>
*/</span>
printf(<span style="color:#cc3300">&quot;frameCount=%d\n&quot;</span>, frameCount);
ma_waveform_read_pcm_frames(&amp;g_sineWave, pOutput, frameCount);
ma_waveform_read_pcm_frames(&amp;g_sineWave, pOutput, frameCount, NULL);
<span style="color:#009900">/* Unused in this example. */</span>
(<span style="color:#0033ff">void</span>)pDevice;
@@ -324,7 +324,7 @@ of data movement.</p>
{
memcpy(pRunningOutput, pReadBuffer, framesToRead * ma_get_bytes_per_frame(pDevice-&gt;playback.format, pDevice-&gt;playback.channels));
}
ma_pcm_rb_commit_read(&amp;g_rb, framesToRead, pReadBuffer);
ma_pcm_rb_commit_read(&amp;g_rb, framesToRead);
pRunningOutput += framesToRead * ma_get_bytes_per_frame(pDevice-&gt;playback.format, pDevice-&gt;playback.channels);
pcmFramesProcessed += framesToRead;
@@ -344,7 +344,7 @@ of data movement.</p>
MA_ASSERT(framesToWrite == PCM_FRAME_CHUNK_SIZE); <span style="color:#009900">/* &lt;-- This should always work in this example because we just reset the ring buffer. */</span>
data_callback_fixed(pDevice, pWriteBuffer, NULL, framesToWrite);
}
ma_pcm_rb_commit_write(&amp;g_rb, framesToWrite, pWriteBuffer);
ma_pcm_rb_commit_write(&amp;g_rb, framesToWrite);
}
}
+3 -3
View File
@@ -245,10 +245,10 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation doc-navigation-active">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation doc-navigation-active">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<div style="text-align:center; padding:1em; padding-bottom:2em;"><div style="text-align:center; overflow:hidden;"><img src="../../img/logo1_large.png" style="width:auto; height:auto; min-height:70px; overflow:hidden;"></div><div style="padding-top:1em; font-weight:bold; font-size:2em; color:#444;">Examples</div><div style="padding-top:0.75em; text-align:center;"><a href="../manual/index.html">Programming Manual</a> - <a href="../api/index.html">API Reference</a> - <a href="https://github.com/mackron/miniaudio">Source Code</a></div></div>
<table style="border:none;"><tr><td style="padding-right:2em;"><a href="custom_backend.html">Custom Backend</a></td><td>This example show how a custom backend can be implemented.</td></tr><tr><td style="padding-right:2em;"><a href="custom_decoder.html">Custom Decoder</a></td><td>Demonstrates how to implement a custom decoder.</td></tr><tr><td style="padding-right:2em;"><a href="data_source_chaining.html">Data Source Chaining</a></td><td>Demonstrates one way to chain together a number of data sources so they play back seamlessly
without gaps.</td></tr><tr><td style="padding-right:2em;"><a href="fixed_size_callback.html">Fixed Size Callback</a></td><td>Shows one way to implement a data callback that is called with a fixed frame count.</td></tr><tr><td style="padding-right:2em;"><a href="simple_capture.html">Simple Capture</a></td><td>Demonstrates how to capture data from a microphone using the low-level API.</td></tr><tr><td style="padding-right:2em;"><a href="simple_duplex.html">Simple Duplex</a></td><td>Demonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.</td></tr><tr><td style="padding-right:2em;"><a href="simple_enumeration.html">Simple Enumeration</a></td><td>Demonstrates how to enumerate over devices.</td></tr><tr><td style="padding-right:2em;"><a href="simple_loopback.html">Simple Loopback</a></td><td>Demonstrates how to implement loopback recording.</td></tr><tr><td style="padding-right:2em;"><a href="simple_looping.html">Simple Looping</a></td><td>Shows one way to handle looping of a sound.</td></tr><tr><td style="padding-right:2em;"><a href="simple_mixing.html">Simple Mixing</a></td><td>Demonstrates one way to load multiple files and play them all back at the same time.</td></tr><tr><td style="padding-right:2em;"><a href="simple_playback.html">Simple Playback</a></td><td>Demonstrates how to load a sound file and play it back using the low-level API.</td></tr><tr><td style="padding-right:2em;"><a href="simple_playback_sine.html">Simple Playback Sine</a></td><td>Demonstrates playback of a sine wave.</td></tr></table></td>
<table style="border:none;"><tr><td style="padding-right:2em;"><a href="custom_backend.html">Custom Backend</a></td><td>This example show how a custom backend can be implemented.</td></tr><tr><td style="padding-right:2em;"><a href="custom_decoder.html">Custom Decoder</a></td><td>Demonstrates how to implement a custom decoder.</td></tr><tr><td style="padding-right:2em;"><a href="custom_decoder_engine.html">Custom Decoder Engine</a></td><td>Demonstrates how to implement a custom decoder and use it with the high level API.</td></tr><tr><td style="padding-right:2em;"><a href="data_source_chaining.html">Data Source Chaining</a></td><td>Demonstrates one way to chain together a number of data sources so they play back seamlessly
without gaps.</td></tr><tr><td style="padding-right:2em;"><a href="duplex_effect.html">Duplex Effect</a></td><td>Demonstrates how to apply an effect to a duplex stream using the node graph system.</td></tr><tr><td style="padding-right:2em;"><a href="engine_advanced.html">Engine Advanced</a></td><td>This example demonstrates some of the advanced features of the high level engine API.</td></tr><tr><td style="padding-right:2em;"><a href="engine_effects.html">Engine Effects</a></td><td>Demonstrates how to apply an effect to sounds using the high level engine API.</td></tr><tr><td style="padding-right:2em;"><a href="engine_hello_world.html">Engine Hello World</a></td><td>This example demonstrates how to initialize an audio engine and play a sound.</td></tr><tr><td style="padding-right:2em;"><a href="fixed_size_callback.html">Fixed Size Callback</a></td><td>Shows one way to implement a data callback that is called with a fixed frame count.</td></tr><tr><td style="padding-right:2em;"><a href="node_graph.html">Node Graph</a></td><td>This example shows how to use the node graph system.</td></tr><tr><td style="padding-right:2em;"><a href="resource_manager.html">Resource Manager</a></td><td>Demonstrates how you can use the resource manager to manage loaded sounds.</td></tr><tr><td style="padding-right:2em;"><a href="resource_manager_advanced.html">Resource Manager Advanced</a></td><td>Demonstrates how you can use the resource manager to manage loaded sounds.</td></tr><tr><td style="padding-right:2em;"><a href="simple_capture.html">Simple Capture</a></td><td>Demonstrates how to capture data from a microphone using the low-level API.</td></tr><tr><td style="padding-right:2em;"><a href="simple_duplex.html">Simple Duplex</a></td><td>Demonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.</td></tr><tr><td style="padding-right:2em;"><a href="simple_enumeration.html">Simple Enumeration</a></td><td>Demonstrates how to enumerate over devices.</td></tr><tr><td style="padding-right:2em;"><a href="simple_loopback.html">Simple Loopback</a></td><td>Demonstrates how to implement loopback recording.</td></tr><tr><td style="padding-right:2em;"><a href="simple_looping.html">Simple Looping</a></td><td>Shows one way to handle looping of a sound.</td></tr><tr><td style="padding-right:2em;"><a href="simple_mixing.html">Simple Mixing</a></td><td>Demonstrates one way to load multiple files and play them all back at the same time.</td></tr><tr><td style="padding-right:2em;"><a href="simple_playback.html">Simple Playback</a></td><td>Demonstrates how to load a sound file and play it back using the low-level API.</td></tr><tr><td style="padding-right:2em;"><a href="simple_playback_sine.html">Simple Playback Sine</a></td><td>Demonstrates playback of a sine wave.</td></tr></table></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
+534
View File
@@ -0,0 +1,534 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Node Graph</h1><p>
This example shows how to use the node graph system.
</p>
<p>
The node graph system can be used for doing complex mixing and effect processing. The idea is that
you have a number of nodes that are connected to each other to form a graph. At the end of the
graph is an endpoint which all nodes eventually connect to.
</p>
<p>
A node is used to do some kind of processing on zero or more input streams and produce one or more
output streams. Each node can have a number of inputs and outputs. Each of these is called a bus in
miniaudio. Some nodes, particularly data source nodes, have no inputs and instead generate their
outputs dynamically. All nodes will have at least one output or else it&#39;ll be disconnected from the
graph and will never get processed. Each output bus of a node will be connected to an input bus of
another node, but they don&#39;t all need to connect to the same input node. For example, a splitter
node has 1 input bus and 2 output buses and is used to duplicate a signal. You could then branch
off and have one output bus connected to one input node and the other connected to a different
input node, and then have two different effects process for each of the duplicated branches.
</p>
<p>
Any number of output buses can be connected to an input bus in which case the output buses will be
mixed before processing by the input node. This is how you would achieve the mixing part of the
node graph.
</p>
<p>
This example will be using the following node graph set up:
</p>
<p>
</p>
<div style="font-family:monospace; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Data flows left to right &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
+---------------+ +-----------------+
| Data Source 1 =----+ +----------+ +----= Low Pass Filter =----+
+---------------+ | | =----+ +-----------------+ | +----------+
+----= Splitter | +----= ENDPOINT |
+---------------+ | | =----+ +-----------------+ | +----------+
| Data Source 2 =----+ +----------+ +----= Echo / Delay =----+
+---------------+ +-----------------+
</pre></div><p>
This does not represent a realistic real-world scenario, but it demonstrates how to make use of
mixing, multiple outputs and multiple effects.
</p>
<p>
The data source nodes are connected to the input of the splitter. They&#39;ll be mixed before being
processed by the splitter. The splitter has two output buses. In the graph above, one bus will be
routed to a low pass filter, whereas the other bus will be routed to an echo effect. Then, the
outputs of these two effects will be connected to the input bus of the endpoint. Because both of
the outputs are connected to the same input bus, they&#39;ll be mixed at that point.
</p>
<p>
The two data sources at the start of the graph have no inputs. They&#39;ll instead generate their
output by reading from a data source. The data source in this case will be one <span style="font-family:monospace;">ma_decoder</span> for
each input file specified on the command line.
</p>
<p>
You can also control the volume of an output bus. In this example, we set the volumes of the low
pass and echo effects so that one of them becomes more obvious than the other.
</p>
<p>
When you want to read from the graph, you simply call <span style="font-family:monospace;">ma_node_graph_read_pcm_frames()</span>.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#009900">/* Data Format */</span>
<span style="color:#666666">#define</span> FORMAT ma_format_f32 <span style="color:#009900">/* Must always be f32. */</span>
<span style="color:#666666">#define</span> CHANNELS 2
<span style="color:#666666">#define</span> SAMPLE_RATE 48000
<span style="color:#009900">/* Effect Properties */</span>
<span style="color:#666666">#define</span> LPF_BIAS 0.9f <span style="color:#009900">/* Higher values means more bias towards the low pass filter (the low pass filter will be more audible). Lower values means more bias towards the echo. Must be between 0 and 1. */</span>
<span style="color:#666666">#define</span> LPF_CUTOFF_FACTOR 80 <span style="color:#009900">/* High values = more filter. */</span>
<span style="color:#666666">#define</span> LPF_ORDER 8
<span style="color:#666666">#define</span> DELAY_IN_SECONDS 0.2f
<span style="color:#666666">#define</span> DECAY 0.5f <span style="color:#009900">/* Volume falloff for each echo. */</span>
<span style="color:#0033ff">typedef</span> <span style="color:#0033ff">struct</span>
{
ma_data_source_node node; <span style="color:#009900">/* If you make this the first member, you can pass a pointer to this struct into any <span style="font-family:monospace;">ma_node_*</span> API and it will &quot;Just Work&quot;. */</span>
<span style="color:#0099cc">ma_decoder</span> decoder;
} sound_node;
<span style="color:#0033ff">static</span> ma_node_graph g_nodeGraph;
<span style="color:#0033ff">static</span> ma_lpf_node g_lpfNode;
<span style="color:#0033ff">static</span> ma_delay_node g_delayNode;
<span style="color:#0033ff">static</span> ma_splitter_node g_splitterNode;
<span style="color:#0033ff">static</span> sound_node* g_pSoundNodes;
<span style="color:#0033ff">static</span> <span style="color:#0033ff">int</span> g_soundNodeCount;
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
MA_ASSERT(pDevice-&gt;playback.channels == CHANNELS);
<span style="color:#009900">/*
Hearing the output of the node graph is as easy as reading straight into the output buffer. You just need to
make sure you use a consistent data format or else you&#39;ll need to do your own conversion.
*/</span>
ma_node_graph_read_pcm_frames(&amp;g_nodeGraph, pOutput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pInput; <span style="color:#009900">/* Unused. */</span>
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0033ff">int</span> iarg;
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#009900">/* We&#39;ll set up our nodes starting from the end and working our way back to the start. We&#39;ll need to set up the graph first. */</span>
{
ma_node_graph_config nodeGraphConfig = ma_node_graph_config_init(CHANNELS);
result = ma_node_graph_init(&amp;nodeGraphConfig, NULL, &amp;g_nodeGraph);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;ERROR: Failed to initialize node graph.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
}
<span style="color:#009900">/* Low Pass Filter. */</span>
{
ma_lpf_node_config lpfNodeConfig = ma_lpf_node_config_init(CHANNELS, SAMPLE_RATE, SAMPLE_RATE / LPF_CUTOFF_FACTOR, LPF_ORDER);
result = ma_lpf_node_init(&amp;g_nodeGraph, &amp;lpfNodeConfig, NULL, &amp;g_lpfNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;ERROR: Failed to initialize low pass filter node.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Connect the output bus of the low pass filter node to the input bus of the endpoint. */</span>
ma_node_attach_output_bus(&amp;g_lpfNode, 0, ma_node_graph_get_endpoint(&amp;g_nodeGraph), 0);
<span style="color:#009900">/* Set the volume of the low pass filter to make it more of less impactful. */</span>
ma_node_set_output_bus_volume(&amp;g_lpfNode, 0, LPF_BIAS);
}
<span style="color:#009900">/* Echo / Delay. */</span>
{
ma_delay_node_config delayNodeConfig = ma_delay_node_config_init(CHANNELS, SAMPLE_RATE, (<span style="color:#0099cc">ma_uint32</span>)(SAMPLE_RATE * DELAY_IN_SECONDS), DECAY);
result = ma_delay_node_init(&amp;g_nodeGraph, &amp;delayNodeConfig, NULL, &amp;g_delayNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;ERROR: Failed to initialize delay node.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Connect the output bus of the delay node to the input bus of the endpoint. */</span>
ma_node_attach_output_bus(&amp;g_delayNode, 0, ma_node_graph_get_endpoint(&amp;g_nodeGraph), 0);
<span style="color:#009900">/* Set the volume of the delay filter to make it more of less impactful. */</span>
ma_node_set_output_bus_volume(&amp;g_delayNode, 0, 1 - LPF_BIAS);
}
<span style="color:#009900">/* Splitter. */</span>
{
ma_splitter_node_config splitterNodeConfig = ma_splitter_node_config_init(CHANNELS);
result = ma_splitter_node_init(&amp;g_nodeGraph, &amp;splitterNodeConfig, NULL, &amp;g_splitterNode);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;ERROR: Failed to initialize splitter node.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Connect output bus 0 to the input bus of the low pass filter node, and output bus 1 to the input bus of the delay node. */</span>
ma_node_attach_output_bus(&amp;g_splitterNode, 0, &amp;g_lpfNode, 0);
ma_node_attach_output_bus(&amp;g_splitterNode, 1, &amp;g_delayNode, 0);
}
<span style="color:#009900">/* Data sources. Ignore any that cannot be loaded. */</span>
g_pSoundNodes = (sound_node*)ma_malloc(<span style="color:#0033ff">sizeof</span>(*g_pSoundNodes) * argc-1, NULL);
<span style="color:#0033ff">if</span> (g_pSoundNodes == NULL) {
printf(<span style="color:#cc3300">&quot;Failed to allocate memory for sounds.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
g_soundNodeCount = 0;
<span style="color:#0033ff">for</span> (iarg = 1; iarg &lt; argc; iarg += 1) {
<span style="color:#0099cc">ma_decoder_config</span> decoderConfig = ma_decoder_config_init(FORMAT, CHANNELS, SAMPLE_RATE);
result = ma_decoder_init_file(argv[iarg], &amp;decoderConfig, &amp;g_pSoundNodes[g_soundNodeCount].decoder);
<span style="color:#0033ff">if</span> (result == MA_SUCCESS) {
ma_data_source_node_config dataSourceNodeConfig = ma_data_source_node_config_init(&amp;g_pSoundNodes[g_soundNodeCount].decoder);
result = ma_data_source_node_init(&amp;g_nodeGraph, &amp;dataSourceNodeConfig, NULL, &amp;g_pSoundNodes[g_soundNodeCount].node);
<span style="color:#0033ff">if</span> (result == MA_SUCCESS) {
<span style="color:#009900">/* The data source node has been created successfully. Attach it to the splitter. */</span>
ma_node_attach_output_bus(&amp;g_pSoundNodes[g_soundNodeCount].node, 0, &amp;g_splitterNode, 0);
g_soundNodeCount += 1;
} <span style="color:#0033ff">else</span> {
printf(<span style="color:#cc3300">&quot;WARNING: Failed to init data source node for sound \&quot;%s\&quot;. Ignoring.&quot;</span>, argv[iarg]);
ma_decoder_uninit(&amp;g_pSoundNodes[g_soundNodeCount].decoder);
}
} <span style="color:#0033ff">else</span> {
printf(<span style="color:#cc3300">&quot;WARNING: Failed to load sound \&quot;%s\&quot;. Ignoring.&quot;</span>, argv[iarg]);
}
}
<span style="color:#009900">/* Everything has been initialized successfully so now we can set up a playback device so we can listen to the result. */</span>
{
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
<span style="color:#0099cc">ma_device</span> device;
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = FORMAT;
deviceConfig.playback.channels = CHANNELS;
deviceConfig.sampleRate = SAMPLE_RATE;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = NULL;
result = ma_device_init(NULL, &amp;deviceConfig, &amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;ERROR: Failed to initialize device.&quot;</span>);
<span style="color:#0033ff">goto</span> cleanup_graph;
}
result = ma_device_start(&amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_device_uninit(&amp;device);
<span style="color:#0033ff">goto</span> cleanup_graph;
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...\n&quot;</span>);
getchar();
<span style="color:#009900">/* We&#39;re done. Clean up the device. */</span>
ma_device_uninit(&amp;device);
}
cleanup_graph:
{
<span style="color:#009900">/* It&#39;s good practice to tear down the graph from the lowest level nodes first. */</span>
<span style="color:#0033ff">int</span> iSound;
<span style="color:#009900">/* Sounds. */</span>
<span style="color:#0033ff">for</span> (iSound = 0; iSound &lt; g_soundNodeCount; iSound += 1) {
ma_data_source_node_uninit(&amp;g_pSoundNodes[iSound].node, NULL);
ma_decoder_uninit(&amp;g_pSoundNodes[iSound].decoder);
}
<span style="color:#009900">/* Splitter. */</span>
ma_splitter_node_uninit(&amp;g_splitterNode, NULL);
<span style="color:#009900">/* Echo / Delay */</span>
ma_delay_node_uninit(&amp;g_delayNode, NULL);
<span style="color:#009900">/* Low Pass Filter */</span>
ma_lpf_node_uninit(&amp;g_lpfNode, NULL);
<span style="color:#009900">/* Node Graph */</span>
ma_node_graph_uninit(&amp;g_nodeGraph, NULL);
}
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+430
View File
@@ -0,0 +1,430 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Resource Manager</h1><p>
Demonstrates how you can use the resource manager to manage loaded sounds.
</p>
<p>
This example loads the first sound specified on the command line via the resource manager and then plays it using the
low level API.
</p>
<p>
You can control whether or not you want to load the sound asynchronously and whether or not you want to store the data
in-memory or stream it. When storing the sound in-memory you can also control whether or not it is decoded. To do this,
specify a combination of the following options in <span style="font-family:monospace;">ma_resource_manager_data_source_init()</span>:
</p>
<ul style="overflow:hidden;">
<li>
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC - Load asynchronously.</li>
<li>
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE - Store the sound in-memory in uncompressed/decoded format.</li>
<li>
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM - Stream the sound from disk rather than storing entirely in memory. Useful for music.</li>
</ul>
<p>
The object returned by the resource manager is just a standard data source which means it can be plugged into any of
<span style="font-family:monospace;">ma_data_source_*()</span> APIs just like any other data source and it should just work.
</p>
<p>
Internally, there&#39;s a background thread that&#39;s used to process jobs and enable asynchronicity. By default there is only
a single job thread, but this can be configured in the resource manager config. You can also implement your own threads
for processing jobs. That is more advanced, and beyond the scope of this example.
</p>
<p>
When you initialize a resource manager you can specify the sample format, channels and sample rate to use when reading
data from the data source. This means the resource manager will ensure all sounds will have a standard format. When not
set, each sound will have their own formats and you&#39;ll need to do the necessary data conversion yourself.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MA_NO_ENGINE <span style="color:#009900">/* We&#39;re intentionally not using the ma_engine API here. */</span>
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
<span style="color:#666666">#include</span> <span style="color:#cc3300">&lt;emscripten.h&gt;</span>
<span style="color:#0033ff">void</span> main_loop__em(<span style="color:#0033ff">void</span>* pUserData)
{
ma_resource_manager* pResourceManager = (ma_resource_manager*)pUserData;
MA_ASSERT(pResourceManager != NULL);
<span style="color:#009900">/*
The Emscripten build does not support threading which means we need to process jobs manually. If
there are no jobs needing to be processed this will return immediately with MA_NO_DATA_AVAILABLE.
*/</span>
ma_resource_manager_process_next_job(pResourceManager);
}
<span style="color:#666666">#endif</span>
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
ma_data_source_read_pcm_frames((<span style="color:#0099cc">ma_data_source</span>*)pDevice-&gt;pUserData, pOutput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pInput;
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
<span style="color:#0099cc">ma_device</span> device;
ma_resource_manager_config resourceManagerConfig;
ma_resource_manager resourceManager;
ma_resource_manager_data_source dataSource;
<span style="color:#0033ff">if</span> (argc &lt; 2) {
printf(<span style="color:#cc3300">&quot;No input file.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* We&#39;ll initialize the device first. */</span>
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &amp;dataSource; <span style="color:#009900">/* &lt;-- We&#39;ll be reading from this in the data callback. */</span>
result = ma_device_init(NULL, &amp;deviceConfig, &amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize device.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
We have the device so now we want to initialize the resource manager. We&#39;ll use the resource manager to load a
sound based on the command line.
*/</span>
resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.decodedFormat = device.playback.format;
resourceManagerConfig.decodedChannels = device.playback.channels;
resourceManagerConfig.decodedSampleRate = device.sampleRate;
<span style="color:#009900">/*
We&#39;re not supporting threading with Emscripten so go ahead and disable threading. It&#39;s important
that we set the appropriate flag and also the job thread count to 0.
*/</span>
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
resourceManagerConfig.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
resourceManagerConfig.jobThreadCount = 0;
<span style="color:#666666">#endif</span>
result = ma_resource_manager_init(&amp;resourceManagerConfig, &amp;resourceManager);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_device_uninit(&amp;device);
printf(<span style="color:#cc3300">&quot;Failed to initialize the resource manager.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* Now that we have a resource manager we can load a sound. */</span>
result = ma_resource_manager_data_source_init(
&amp;resourceManager,
argv[1],
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM,
NULL, <span style="color:#009900">/* Async notification. */</span>
&amp;dataSource);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to load sound \&quot;%s\&quot;.&quot;</span>, argv[1]);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* In this example we&#39;ll enable looping. */</span>
ma_data_source_set_looping(&amp;dataSource, MA_TRUE);
<span style="color:#009900">/* Now that we have a sound we can start the device. */</span>
result = ma_device_start(&amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_device_uninit(&amp;device);
printf(<span style="color:#cc3300">&quot;Failed to start device.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
emscripten_set_main_loop_arg(main_loop__em, &amp;resourceManager, 0, 1);
<span style="color:#666666">#else</span>
printf(<span style="color:#cc3300">&quot;Press Enter to quit...\n&quot;</span>);
getchar();
<span style="color:#666666">#endif</span>
<span style="color:#009900">/* Teardown. */</span>
<span style="color:#009900">/* Uninitialize the device first to ensure the data callback is stopped and doesn&#39;t try to access any data. */</span>
ma_device_uninit(&amp;device);
<span style="color:#009900">/*
Before uninitializing the resource manager we need to uninitialize every data source. The data source is owned by
the caller which means you&#39;re responsible for uninitializing it.
*/</span>
ma_resource_manager_data_source_uninit(&amp;dataSource);
<span style="color:#009900">/* Uninitialize the resource manager after each data source. */</span>
ma_resource_manager_uninit(&amp;resourceManager);
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
@@ -0,0 +1,602 @@
<!DOCTYPE html>
<html>
<head>
<title>miniaudio - A single file audio playback and capture library.</title>
<meta name="description" content="miniaudio is a single file audio playback and capture library written in C.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="../../img/favicon.png">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-81135233-2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-81135233-2');
</script>
<style>
body {
font-family:sans-serif;
font-size:11pt;
line-height:18pt;
background-color:#003800;
}
h1,h2 {
color:#333;
line-height:0.2em;
margin-bottom:0;
padding:0;
}
h1.man {
margin-top:2em;
}
h2.man {
margin-top:1.5em;
}
a {
text-decoration:none;
color:#28f;
}
a:hover {
text-decoration:underline;
color:#26d;
}
.a-download {
text-decoration:none;
color:#ddd;
border:solid 1px #000;
border-radius:4px;
padding:16px 32px;
background-color:#003800;
}
.a-download:hover {
background-color:#003000;
text-decoration:none;
color:#ddd;
}
.a-sublink {
font-size:11pt;
}
#preview {
font-family:monospace;
font-size:10pt;
text-align:left;
}
.footer-links {
margin: 0px;
margin-bottom: 10px;
padding: 0px;
}
.footer-links li {
display: inline;
padding: 0 2px;
}
.footer-links li:first-child {
padding-left: 0;
}
.feature-header {
color:#666;
font-size: 24pt;
font-weight:bold;
}
.feature-header2 {
color:#444;
font-size: 1.5em;
font-weight:bold;
/*margin-bottom:1em;*/
line-height: 1em;
text-align:left;
}
.header-link-table {
}
.header-link-table td {
padding-right:1em;
vertical-align:center;
line-height:0;
/*border:solid 1px #f00;*/
}
.header-link-table a {
/*color:#e0d7cf;*/
color:#dddddd;
text-decoration:none;
}
.header-link-table a:hover {
color:#ffffff;
}
.footer-link {
color:#e0d7cf;
text-decoration:none;
}
.footer-link:hover {
color:#ffffff;
}
.mobile-main-link {
text-align:left;
background-color:#e0d7cf;
color:#036;
border-bottom:solid 1px #333;
padding-left:16px;
}
.mobile-main-link a {
display:block;
padding-top:8px;
padding-bottom:8px;
color:#036;
width:100%;
height:100%;
max-width:100%;
}
table.doc {
border:solid 0px #333;
border-collapse:collapse;
}
th.doc, td.doc {
padding:0.5em;
}
th.doc {
border:solid 1px #003800;
background-color:#003800;
color:#FFF;
text-align:left;
}
td.doc {
border:solid 1px #666;
}
td.doc p, th.doc p {
padding:0;
margin:0;
}
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
</style>
</head>
<body style="margin:0; padding:0">
<div style="background-color:#003800; color:#bfa792;">
<div style="max-width:100%; width:100%; margin:0 auto;">
<table class="header-link-table" style="border-collapse:collapse; border-spacing:0; padding:0; padding-right:1em;">
<tr>
<td style="padding:0.75em; width:100%; text-align:left;">
<table class="header-link-table" style="border-collapse:collapse; margin:0; padding:0">
<tr>
<td style="vertical-align:bottom; padding:0em; padding-right:2em;"><a href="../../index.html"><img src="../../img/logo1_large_white.png" style="height:24px; min-width:100%;"></a></td>
<td><a href="../manual/index.html">Documentation</a></td>
<td><a href="index.html">Examples</a></td>
</tr>
</table>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="margin:0; padding:0; height:32px; width:32px;"></a>
</td>
<td style="padding:0.1em; padding-right:1em; width:25%; text-align:right; vertical-align:center;">
<a href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="margin:0; padding:0; height:24px; width:24px;"></a>
</td>
</tr>
</table>
</div>
</div>
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Resource Manager Advanced</h1><p>
Demonstrates how you can use the resource manager to manage loaded sounds.
</p>
<p>
The resource manager can be used to create a data source whose resources are managed internally by miniaudio. The data
sources can then be read just like any other data source such as decoders and audio buffers.
</p>
<p>
In this example we use the resource manager independently of the <span style="font-family:monospace;">ma_engine</span> API so that we can demonstrate how it can
be used by itself without getting it confused with <span style="font-family:monospace;">ma_engine</span>.
</p>
<p>
The main feature of the resource manager is the ability to decode and stream audio data asynchronously. Asynchronicity
is achieved with a job system. The resource manager will issue jobs which are processed by a configurable number of job
threads. You can also implement your own custom job threads which this example also demonstrates.
</p>
<p>
In this example we show how you can create a data source, mix them with other data sources, configure the number of job
threads to manage internally and how to implement your own custom job thread.</p>
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em; width:100%;"><pre style="margin:0.5em 1em; padding:0; line-height:125%; overflow-x:auto;">
<span style="color:#666666">#define</span> MA_NO_ENGINE <span style="color:#009900">/* We&#39;re intentionally not using the ma_engine API here. */</span>
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
<span style="color:#666666">#include</span> <span style="color:#cc3300">&quot;../miniaudio.h&quot;</span>
<span style="color:#0033ff">static</span> ma_resource_manager_data_source g_dataSources[16];
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_uint32</span> g_dataSourceCount;
<span style="color:#009900">/*
TODO: Consider putting these public functions in miniaudio.h. Will depend on ma_mix_pcm_frames_f32()
being merged into miniaudio.h (it&#39;s currently in miniaudio_engine.h).
*/</span>
<span style="color:#0033ff">static</span> <span style="color:#0099cc">ma_result</span> ma_data_source_read_pcm_frames_f32_ex(<span style="color:#0099cc">ma_data_source</span>* pDataSource, <span style="color:#0033ff">float</span>* pFramesOut, <span style="color:#0099cc">ma_uint64</span> frameCount, <span style="color:#0099cc">ma_uint64</span>* pFramesRead, ma_format dataSourceFormat, <span style="color:#0099cc">ma_uint32</span> dataSourceChannels)
{
<span style="color:#009900">/*
This function is intended to be used when the format and channel count of the data source is
known beforehand. The idea is to avoid overhead due to redundant calls to ma_data_source_get_data_format().
*/</span>
MA_ASSERT(pDataSource != NULL);
<span style="color:#0033ff">if</span> (dataSourceFormat == ma_format_f32) {
<span style="color:#009900">/* Fast path. No conversion necessary. */</span>
<span style="color:#0033ff">return</span> ma_data_source_read_pcm_frames(pDataSource, pFramesOut, frameCount, pFramesRead);
} <span style="color:#0033ff">else</span> {
<span style="color:#009900">/* Slow path. Conversion necessary. */</span>
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0099cc">ma_uint64</span> totalFramesRead;
<span style="color:#0099cc">ma_uint8</span> temp[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
<span style="color:#0099cc">ma_uint64</span> tempCapInFrames = <span style="color:#0033ff">sizeof</span>(temp) / ma_get_bytes_per_frame(dataSourceFormat, dataSourceChannels);
totalFramesRead = 0;
<span style="color:#0033ff">while</span> (totalFramesRead &lt; frameCount) {
<span style="color:#0099cc">ma_uint64</span> framesJustRead;
<span style="color:#0099cc">ma_uint64</span> framesToRead = frameCount - totalFramesRead;
<span style="color:#0033ff">if</span> (framesToRead &gt; tempCapInFrames) {
framesToRead = tempCapInFrames;
}
result = ma_data_source_read_pcm_frames(pDataSource, pFramesOut, framesToRead, &amp;framesJustRead);
ma_convert_pcm_frames_format(ma_offset_pcm_frames_ptr_f32(pFramesOut, totalFramesRead, dataSourceChannels), ma_format_f32, temp, dataSourceFormat, framesJustRead, dataSourceChannels, ma_dither_mode_none);
totalFramesRead += framesJustRead;
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">break</span>;
}
}
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
}
MA_API <span style="color:#0099cc">ma_result</span> ma_data_source_read_pcm_frames_f32(<span style="color:#0099cc">ma_data_source</span>* pDataSource, <span style="color:#0033ff">float</span>* pFramesOut, <span style="color:#0099cc">ma_uint64</span> frameCount, <span style="color:#0099cc">ma_uint64</span>* pFramesRead)
{
<span style="color:#0099cc">ma_result</span> result;
ma_format format;
<span style="color:#0099cc">ma_uint32</span> channels;
result = ma_data_source_get_data_format(pDataSource, &amp;format, &amp;channels, NULL, NULL, 0);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">return</span> result; <span style="color:#009900">/* Failed to retrieve the data format of the data source. */</span>
}
<span style="color:#0033ff">return</span> ma_data_source_read_pcm_frames_f32_ex(pDataSource, pFramesOut, frameCount, pFramesRead, format, channels);
}
MA_API <span style="color:#0099cc">ma_result</span> ma_data_source_read_pcm_frames_and_mix_f32(<span style="color:#0099cc">ma_data_source</span>* pDataSource, <span style="color:#0033ff">float</span>* pFramesOut, <span style="color:#0099cc">ma_uint64</span> frameCount, <span style="color:#0099cc">ma_uint64</span>* pFramesRead, <span style="color:#0033ff">float</span> volume)
{
<span style="color:#0099cc">ma_result</span> result;
ma_format format;
<span style="color:#0099cc">ma_uint32</span> channels;
<span style="color:#0099cc">ma_uint64</span> totalFramesRead;
<span style="color:#0033ff">if</span> (pFramesRead != NULL) {
*pFramesRead = 0;
}
<span style="color:#0033ff">if</span> (pDataSource == NULL) {
<span style="color:#0033ff">return</span> MA_INVALID_ARGS;
}
result = ma_data_source_get_data_format(pDataSource, &amp;format, &amp;channels, NULL, NULL, 0);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">return</span> result; <span style="color:#009900">/* Failed to retrieve the data format of the data source. */</span>
}
totalFramesRead = 0;
<span style="color:#0033ff">while</span> (totalFramesRead &lt; frameCount) {
<span style="color:#0033ff">float</span> temp[MA_DATA_CONVERTER_STACK_BUFFER_SIZE/<span style="color:#0033ff">sizeof</span>(<span style="color:#0033ff">float</span>)];
<span style="color:#0099cc">ma_uint64</span> tempCapInFrames = ma_countof(temp) / channels;
<span style="color:#0099cc">ma_uint64</span> framesJustRead;
<span style="color:#0099cc">ma_uint64</span> framesToRead = frameCount - totalFramesRead;
<span style="color:#0033ff">if</span> (framesToRead &gt; tempCapInFrames) {
framesToRead = tempCapInFrames;
}
result = ma_data_source_read_pcm_frames_f32_ex(pDataSource, temp, framesToRead, &amp;framesJustRead, format, channels);
ma_mix_pcm_frames_f32(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), temp, framesJustRead, channels, volume);
totalFramesRead += framesJustRead;
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">break</span>;
}
}
<span style="color:#0033ff">if</span> (pFramesRead != NULL) {
*pFramesRead = totalFramesRead;
}
<span style="color:#0033ff">return</span> MA_SUCCESS;
}
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
<span style="color:#009900">/*
In this example we&#39;re just going to play our data sources layered on top of each other. This
assumes the device&#39;s format is f32 and that the buffer is not pre-silenced.
*/</span>
<span style="color:#0099cc">ma_uint32</span> iDataSource;
MA_ASSERT(pDevice-&gt;playback.format == ma_format_f32);
(<span style="color:#0033ff">void</span>)pInput; <span style="color:#009900">/* Unused. */</span>
<span style="color:#009900">/*
If the device was configured with noPreSilencedOutputBuffer then you would need to silence the
buffer here, or make sure the first data source to be mixed is copied rather than mixed.
*/</span>
<span style="color:#009900">/*ma_silence_pcm_frames(pOutput, frameCount, ma_format_f32, pDevice-&gt;playback.channels);*/</span>
<span style="color:#009900">/* For each sound, mix as much data as we can. */</span>
<span style="color:#0033ff">for</span> (iDataSource = 0; iDataSource &lt; g_dataSourceCount; iDataSource += 1) {
ma_data_source_read_pcm_frames_and_mix_f32(&amp;g_dataSources[iDataSource], (<span style="color:#0033ff">float</span>*)pOutput, frameCount, NULL, <span style="color:#009900">/* volume = */</span>1);
}
}
<span style="color:#0033ff">static</span> ma_thread_result MA_THREADCALL custom_job_thread(<span style="color:#0033ff">void</span>* pUserData)
{
ma_resource_manager* pResourceManager = (ma_resource_manager*)pUserData;
MA_ASSERT(pResourceManager != NULL);
<span style="color:#0033ff">for</span> (;;) {
<span style="color:#0099cc">ma_result</span> result;
ma_resource_manager_job job;
<span style="color:#009900">/*
Retrieve a job from the queue first. This defines what it is you&#39;re about to do. By default this will be
blocking. You can initialize the resource manager with MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING to not block in
which case MA_NO_DATA_AVAILABLE will be returned if no jobs are available.
When the quit job is returned (MA_RESOURCE_MANAGER_JOB_QUIT), the return value will always be MA_CANCELLED. If you don&#39;t want
to check the return value (you should), you can instead check if the job code is MA_RESOURCE_MANAGER_JOB_QUIT and use that
instead.
*/</span>
result = ma_resource_manager_next_job(pResourceManager, &amp;job);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">if</span> (result == MA_CANCELLED) {
printf(<span style="color:#cc3300">&quot;CUSTOM JOB THREAD TERMINATING VIA MA_CANCELLED... &quot;</span>);
} <span style="color:#0033ff">else</span> {
printf(<span style="color:#cc3300">&quot;CUSTOM JOB THREAD ERROR: %s. TERMINATING... &quot;</span>, ma_result_description(result));
}
<span style="color:#0033ff">break</span>;
}
<span style="color:#009900">/*
Terminate if we got a quit message. You don&#39;t need to terminate like this, but&#39;s a bit more robust. You can
just use a global variable or something similar if it&#39;s easier for your particular situation. The quit job
remains in the queue and will continue to be returned by future calls to ma_resource_manager_next_job(). The
reason for this is to give every job thread visibility to the quit job so they have a chance to exit.
We won&#39;t actually be hitting this code because the call above will return MA_CANCELLED when the MA_RESOURCE_MANAGER_JOB_QUIT
event is received which means the <span style="font-family:monospace;">result != MA_SUCCESS</span> logic above will catch it. If you do not check the
return value of ma_resource_manager_next_job() you will want to check for MA_RESOURCE_MANAGER_JOB_QUIT like the code below.
*/</span>
<span style="color:#0033ff">if</span> (job.toc.breakup.code == MA_RESOURCE_MANAGER_JOB_QUIT) {
printf(<span style="color:#cc3300">&quot;CUSTOM JOB THREAD TERMINATING VIA MA_RESOURCE_MANAGER_JOB_QUIT... &quot;</span>);
<span style="color:#0033ff">break</span>;
}
<span style="color:#009900">/* Call ma_resource_manager_process_job() to actually do the work to process the job. */</span>
printf(<span style="color:#cc3300">&quot;PROCESSING IN CUSTOM JOB THREAD: %d\n&quot;</span>, job.toc.breakup.code);
ma_resource_manager_process_job(pResourceManager, &amp;job);
}
printf(<span style="color:#cc3300">&quot;TERMINATED\n&quot;</span>);
<span style="color:#0033ff">return</span> (ma_thread_result)0;
}
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
{
<span style="color:#0099cc">ma_result</span> result;
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
<span style="color:#0099cc">ma_device</span> device;
ma_resource_manager_config resourceManagerConfig;
ma_resource_manager resourceManager;
<span style="color:#0099cc">ma_thread</span> jobThread;
<span style="color:#0033ff">int</span> iFile;
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = ma_format_f32;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = NULL;
result = ma_device_init(NULL, &amp;deviceConfig, &amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize device.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/* We can start the device before loading any sounds. We&#39;ll just end up outputting silence. */</span>
result = ma_device_start(&amp;device);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_device_uninit(&amp;device);
printf(<span style="color:#cc3300">&quot;Failed to start device.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
We have the device so now we want to initialize the resource manager. We&#39;ll use the resource manager to load some
sounds based on the command line.
*/</span>
resourceManagerConfig = ma_resource_manager_config_init();
<span style="color:#009900">/*
We&#39;ll set a standard decoding format to save us to processing time at mixing time. If you&#39;re wanting to use
spatialization with your decoded sounds, you may want to consider leaving this as 0 to ensure the file&#39;s native
channel count is used so you can do proper spatialization.
*/</span>
resourceManagerConfig.decodedFormat = device.playback.format;
resourceManagerConfig.decodedChannels = device.playback.channels;
resourceManagerConfig.decodedSampleRate = device.sampleRate;
<span style="color:#009900">/* The number of job threads to be managed internally. Set this to 0 if you want to self-manage your job threads */</span>
resourceManagerConfig.jobThreadCount = 4;
result = ma_resource_manager_init(&amp;resourceManagerConfig, &amp;resourceManager);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
ma_device_uninit(&amp;device);
printf(<span style="color:#cc3300">&quot;Failed to initialize the resource manager.&quot;</span>);
<span style="color:#0033ff">return</span> -1;
}
<span style="color:#009900">/*
Now that we have a resource manager we can set up our custom job thread. This is optional. Normally when doing
self-managed job threads you would set the internal job thread count to zero. We&#39;re doing both internal and
self-managed job threads in this example just for demonstration purposes.
*/</span>
ma_thread_create(&amp;jobThread, ma_thread_priority_default, 0, custom_job_thread, &amp;resourceManager, NULL);
<span style="color:#009900">/* Create each data source from the resource manager. Note that the caller is the owner. */</span>
<span style="color:#0033ff">for</span> (iFile = 0; iFile &lt; ma_countof(g_dataSources) &amp;&amp; iFile &lt; argc-1; iFile += 1) {
result = ma_resource_manager_data_source_init(
&amp;resourceManager,
argv[iFile+1],
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC <span style="color:#009900">/*| MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM*/</span>,
NULL, <span style="color:#009900">/* Async notification. */</span>
&amp;g_dataSources[iFile]);
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
<span style="color:#0033ff">break</span>;
}
<span style="color:#009900">/* Use looping in this example. */</span>
ma_data_source_set_looping(&amp;g_dataSources[iFile], MA_TRUE);
g_dataSourceCount += 1;
}
printf(<span style="color:#cc3300">&quot;Press Enter to quit...&quot;</span>);
getchar();
<span style="color:#009900">/* Teardown. */</span>
<span style="color:#009900">/*
Uninitialize the device first to ensure the data callback is stopped and doesn&#39;t try to access
any data.
*/</span>
ma_device_uninit(&amp;device);
<span style="color:#009900">/*
Our data sources need to be explicitly uninitialized. ma_resource_manager_uninit() will not do
it for us. This needs to be done before posting the quit event and uninitializing the resource
manager or else we&#39;ll get stuck in a deadlock because ma_resource_manager_data_source_uninit()
will be waiting for the job thread(s) to finish work, which will never happen because they were
just terminated.
*/</span>
<span style="color:#0033ff">for</span> (iFile = 0; (size_t)iFile &lt; g_dataSourceCount; iFile += 1) {
ma_resource_manager_data_source_uninit(&amp;g_dataSources[iFile]);
}
<span style="color:#009900">/*
Before uninitializing the resource manager we need to make sure a quit event has been posted to
ensure we can get out of our custom thread. The call to ma_resource_manager_uninit() will also
do this, but we need to call it explicitly so that our self-managed thread can exit naturally.
You only need to post a quit job if you&#39;re using that as the exit indicator. You can instead
use whatever variable you want to terminate your job thread, but since this example is using a
quit job we need to post one. Note that you don&#39;t need to do this if you&#39;re not managing your
own threads - ma_resource_manager_uninit() alone will suffice in that case.
*/</span>
ma_resource_manager_post_job_quit(&amp;resourceManager);
ma_thread_wait(&amp;jobThread); <span style="color:#009900">/* Wait for the custom job thread to finish so it doesn&#39;t try to access any data. */</span>
<span style="color:#009900">/* Uninitialize the resource manager after each data source. */</span>
ma_resource_manager_uninit(&amp;resourceManager);
<span style="color:#0033ff">return</span> 0;
}
</pre></div></td>
</tr></table>
</div>
<table style="margin:0 auto; padding:1em 0px; text-align:center;">
<tr>
<td style="vertical-align:center;"><a style="padding:0;" href="https://discord.gg/9vpqbjU"><img src="../../img/Discord-Logo-White.svg" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://twitter.com/mackron"><img src="../../img/twitter_white.png" style="padding:0; height:32px; width:32px;"></a></td>
<td style="vertical-align:center;"><a style="padding:0;" href="https://github.com/mackron/miniaudio"><img src="../../img/github_white.png" style="padding:0; height:24px; width:24px;"></a></td>
</tr>
</table>
<div style="color:#e0d7cf; font-size:9pt; padding:2em 0px; text-align:center;">
Copyright &copy; 2021 David Reid<br/>
Developed by David Reid - <a class="footer-link" href="mailto:mackron@gmail.com">mackron@gmail.com</a>
</div>
</body>
</html>
+3 -3
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Capture</h1><p>
Demonstrates how to capture data from a microphone using the low-level API.
</p>
@@ -271,7 +271,7 @@ data received by the microphone straight to a WAV file.</p>
<span style="color:#0099cc">ma_encoder</span>* pEncoder = (<span style="color:#0099cc">ma_encoder</span>*)pDevice-&gt;pUserData;
MA_ASSERT(pEncoder != NULL);
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount);
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pOutput;
}
@@ -289,7 +289,7 @@ data received by the microphone straight to a WAV file.</p>
<span style="color:#0033ff">return</span> -1;
}
encoderConfig = ma_encoder_config_init(ma_resource_format_wav, ma_format_f32, 2, 44100);
encoderConfig = ma_encoder_config_init(ma_encoding_format_wav, ma_format_f32, 2, 44100);
<span style="color:#0033ff">if</span> (ma_encoder_init_file(argv[1], &amp;encoderConfig, &amp;encoder) != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize output file.\n&quot;</span>);
+1 -1
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Duplex</h1><p>
Demonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.
</p>
+1 -1
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Enumeration</h1><p>
Demonstrates how to enumerate over devices.
</p>
+3 -3
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Loopback</h1><p>
Demonstrates how to implement loopback recording.
</p>
@@ -275,7 +275,7 @@ properties. The output buffer in the callback will be null whereas the input buf
<span style="color:#0099cc">ma_encoder</span>* pEncoder = (<span style="color:#0099cc">ma_encoder</span>*)pDevice-&gt;pUserData;
MA_ASSERT(pEncoder != NULL);
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount);
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pOutput;
}
@@ -298,7 +298,7 @@ properties. The output buffer in the callback will be null whereas the input buf
<span style="color:#0033ff">return</span> -1;
}
encoderConfig = ma_encoder_config_init(ma_resource_format_wav, ma_format_f32, 2, 44100);
encoderConfig = ma_encoder_config_init(ma_encoding_format_wav, ma_format_f32, 2, 44100);
<span style="color:#0033ff">if</span> (ma_encoder_init_file(argv[1], &amp;encoderConfig, &amp;encoder) != MA_SUCCESS) {
printf(<span style="color:#cc3300">&quot;Failed to initialize output file.\n&quot;</span>);
+9 -8
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Looping</h1><p>
Shows one way to handle looping of a sound.
</p>
@@ -262,18 +262,13 @@ decoder straight into <span style="font-family:monospace;">ma_data_source_read_p
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
{
<span style="color:#0099cc">ma_bool32</span> isLooping = MA_TRUE;
<span style="color:#0099cc">ma_decoder</span>* pDecoder = (<span style="color:#0099cc">ma_decoder</span>*)pDevice-&gt;pUserData;
<span style="color:#0033ff">if</span> (pDecoder == NULL) {
<span style="color:#0033ff">return</span>;
}
<span style="color:#009900">/*
A decoder is a data source which means you can seemlessly plug it into the ma_data_source API. We can therefore take advantage
of the &quot;loop&quot; parameter of ma_data_source_read_pcm_frames() to handle looping for us.
*/</span>
ma_data_source_read_pcm_frames(pDecoder, pOutput, frameCount, NULL, isLooping);
<span style="color:#009900">/* Reading PCM frames will loop based on what we specified when called ma_data_source_set_looping(). */</span>
ma_data_source_read_pcm_frames(pDecoder, pOutput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pInput;
}
@@ -295,6 +290,12 @@ decoder straight into <span style="font-family:monospace;">ma_data_source_read_p
<span style="color:#0033ff">return</span> -2;
}
<span style="color:#009900">/*
A decoder is a data source which means we just use ma_data_source_set_looping() to set the
looping state. We will read data using ma_data_source_read_pcm_frames() in the data callback.
*/</span>
ma_data_source_set_looping(&amp;decoder, MA_TRUE);
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = decoder.outputFormat;
deviceConfig.playback.channels = decoder.outputChannels;
+2 -2
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Mixing</h1><p>
Demonstrates one way to load multiple files and play them all back at the same time.
</p>
@@ -313,7 +313,7 @@ For simplicity, this example requires the device to use floating point samples.
framesToReadThisIteration = totalFramesRemaining;
}
framesReadThisIteration = (<span style="color:#0099cc">ma_uint32</span>)ma_decoder_read_pcm_frames(pDecoder, temp, framesToReadThisIteration);
framesReadThisIteration = (<span style="color:#0099cc">ma_uint32</span>)ma_decoder_read_pcm_frames(pDecoder, temp, framesToReadThisIteration, NULL);
<span style="color:#0033ff">if</span> (framesReadThisIteration == 0) {
<span style="color:#0033ff">break</span>;
}
+2 -2
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 ">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Playback</h1><p>
Demonstrates how to load a sound file and play it back using the low-level API.
</p>
@@ -274,7 +274,7 @@ the simple_mixing example for how best to do this.</p>
<span style="color:#0033ff">return</span>;
}
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount);
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pInput;
}
+2 -2
View File
@@ -245,7 +245,7 @@ a.doc-navigation-l4 {
<div style="background-color:#fff; padding-bottom:0em; border-top:solid 1px #003800; background-color:#eee;">
<table border="0" style="margin:0 auto; width:100%; border-collapse:collapse; border:solid 0px #000; table-layout:fixed;"><tr>
<td valign="top" style="width:20em; padding:0; margin:0; border-right:solid 0px #000;"><div style="position:relative; height:100%; width:100%; border:solid 0px #000; padding:0; margin:0;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<a href="../index.html" class="doc-navigation">Documentation Home</a><a href="../manual/index.html" class="doc-navigation">Programming Manual</a><a href="index.html" class="doc-navigation ">Examples</a><a href="custom_backend.html" class="doc-navigation doc-navigation-l1 ">Custom Backend</a><a href="custom_decoder.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder</a><a href="custom_decoder_engine.html" class="doc-navigation doc-navigation-l1 ">Custom Decoder Engine</a><a href="data_source_chaining.html" class="doc-navigation doc-navigation-l1 ">Data Source Chaining</a><a href="duplex_effect.html" class="doc-navigation doc-navigation-l1 ">Duplex Effect</a><a href="engine_advanced.html" class="doc-navigation doc-navigation-l1 ">Engine Advanced</a><a href="engine_effects.html" class="doc-navigation doc-navigation-l1 ">Engine Effects</a><a href="engine_hello_world.html" class="doc-navigation doc-navigation-l1 ">Engine Hello World</a><a href="fixed_size_callback.html" class="doc-navigation doc-navigation-l1 ">Fixed Size Callback</a><a href="node_graph.html" class="doc-navigation doc-navigation-l1 ">Node Graph</a><a href="resource_manager.html" class="doc-navigation doc-navigation-l1 ">Resource Manager</a><a href="resource_manager_advanced.html" class="doc-navigation doc-navigation-l1 ">Resource Manager Advanced</a><a href="simple_capture.html" class="doc-navigation doc-navigation-l1 ">Simple Capture</a><a href="simple_duplex.html" class="doc-navigation doc-navigation-l1 ">Simple Duplex</a><a href="simple_enumeration.html" class="doc-navigation doc-navigation-l1 ">Simple Enumeration</a><a href="simple_loopback.html" class="doc-navigation doc-navigation-l1 ">Simple Loopback</a><a href="simple_looping.html" class="doc-navigation doc-navigation-l1 ">Simple Looping</a><a href="simple_mixing.html" class="doc-navigation doc-navigation-l1 ">Simple Mixing</a><a href="simple_playback.html" class="doc-navigation doc-navigation-l1 ">Simple Playback</a><a href="simple_playback_sine.html" class="doc-navigation doc-navigation-l1 doc-navigation-active">Simple Playback Sine</a><a href="../api/index.html" class="doc-navigation" style="border-bottom:none;">API Reference</a></div></td><td valign="top" style="padding:1em; border-left:solid 1px #bbb;">
<h1>Simple Playback Sine</h1><p>
Demonstrates playback of a sine wave.
</p>
@@ -296,7 +296,7 @@ This example works with Emscripten.</p>
pSineWave = (<span style="color:#0099cc">ma_waveform</span>*)pDevice-&gt;pUserData;
MA_ASSERT(pSineWave != NULL);
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount);
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount, NULL);
(<span style="color:#0033ff">void</span>)pInput; <span style="color:#009900">/* Unused. */</span>
}
+3218 -416
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 1.2 KiB