commit f507182c756b3d82fd02fcd59ad45ce46cc681c5
parent 5d572ec5f1c794d5f641f01ef56e0b318861db1c
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Mon, 20 Oct 2014 19:29:36 +0200
Update the spec
Diffstat:
M | spec.html | | | 349 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
M | spec.rst | | | 144 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
2 files changed, 324 insertions(+), 169 deletions(-)
diff --git a/spec.html b/spec.html
@@ -109,73 +109,75 @@ tt.docutils {
<ul class="simple">
<li><a class="reference internal" href="#goals" id="id2">Goals</a><ul>
<li><a class="reference internal" href="#later-goals" id="id3">Later goals</a></li>
+<li><a class="reference internal" href="#design-choice" id="id4">Design choice</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#specification" id="id4">Specification</a><ul>
-<li><a class="reference internal" href="#encoding" id="id5">Encoding</a></li>
-<li><a class="reference internal" href="#plugins-location" id="id6">Plugins location</a><ul>
-<li><a class="reference internal" href="#common" id="id7">Common</a></li>
-<li><a class="reference internal" href="#linux" id="id8">Linux</a></li>
-<li><a class="reference internal" href="#windows" id="id9">Windows</a></li>
-<li><a class="reference internal" href="#mac" id="id10">Mac</a></li>
+<li><a class="reference internal" href="#specification" id="id5">Specification</a><ul>
+<li><a class="reference internal" href="#encoding" id="id6">Encoding</a></li>
+<li><a class="reference internal" href="#plugins-location" id="id7">Plugins location</a><ul>
+<li><a class="reference internal" href="#common" id="id8">Common</a></li>
+<li><a class="reference internal" href="#linux" id="id9">Linux</a></li>
+<li><a class="reference internal" href="#windows" id="id10">Windows</a></li>
+<li><a class="reference internal" href="#mac" id="id11">Mac</a></li>
+<li><a class="reference internal" href="#multi-architecture-conventions" id="id12">Multi-architecture conventions</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#instantiate-a-plugin" id="id11">Instantiate a plugin</a><ul>
-<li><a class="reference internal" href="#precautions" id="id12">Precautions</a></li>
-<li><a class="reference internal" href="#shell-plugins" id="id13">Shell plugins</a><ul>
-<li><a class="reference internal" href="#sample-plugin-loader" id="id14">Sample plugin loader</a></li>
+<li><a class="reference internal" href="#instantiate-a-plugin" id="id13">Instantiate a plugin</a><ul>
+<li><a class="reference internal" href="#precautions" id="id14">Precautions</a></li>
+<li><a class="reference internal" href="#shell-plugins" id="id15">Shell plugins</a><ul>
+<li><a class="reference internal" href="#sample-plugin-loader" id="id16">Sample plugin loader</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#description" id="id15">Description</a></li>
-<li><a class="reference internal" href="#audio-channel-configuration" id="id16">Audio channel configuration</a><ul>
-<li><a class="reference internal" href="#pin-layout" id="id17">Pin layout</a></li>
-<li><a class="reference internal" href="#available-configurations" id="id18">Available configurations</a></li>
-<li><a class="reference internal" href="#selecting-a-configuration" id="id19">Selecting a configuration</a></li>
-<li><a class="reference internal" href="#repeatable-channels" id="id20">Repeatable channels</a></li>
-<li><a class="reference internal" href="#feedback-stream" id="id21">Feedback stream</a></li>
+<li><a class="reference internal" href="#description" id="id17">Description</a></li>
+<li><a class="reference internal" href="#audio-ports-configuration" id="id18">Audio ports configuration</a><ul>
+<li><a class="reference internal" href="#pin-layout" id="id19">Pin layout</a></li>
+<li><a class="reference internal" href="#available-configurations" id="id20">Available configurations</a></li>
+<li><a class="reference internal" href="#selecting-a-configuration" id="id21">Selecting a configuration</a></li>
+<li><a class="reference internal" href="#repeatable-channels" id="id22">Repeatable channels</a></li>
+<li><a class="reference internal" href="#feedback-stream" id="id23">Feedback stream</a></li>
</ul>
</li>
</ul>
</li>
-<li><a class="reference internal" href="#threading" id="id22">Threading</a></li>
-<li><a class="reference internal" href="#activation" id="id23">Activation</a></li>
-<li><a class="reference internal" href="#processing" id="id24">Processing</a><ul>
-<li><a class="reference internal" href="#audio-buffers" id="id25">Audio buffers</a></li>
-<li><a class="reference internal" href="#events" id="id26">Events</a><ul>
-<li><a class="reference internal" href="#notes" id="id27">Notes</a></li>
-<li><a class="reference internal" href="#parameters" id="id28">Parameters</a></li>
-<li><a class="reference internal" href="#pitch" id="id29">Pitch</a></li>
+<li><a class="reference internal" href="#threading" id="id24">Threading</a></li>
+<li><a class="reference internal" href="#activation" id="id25">Activation</a></li>
+<li><a class="reference internal" href="#processing" id="id26">Processing</a><ul>
+<li><a class="reference internal" href="#audio-buffers" id="id27">Audio buffers</a></li>
+<li><a class="reference internal" href="#events" id="id28">Events</a><ul>
+<li><a class="reference internal" href="#notes" id="id29">Notes</a></li>
+<li><a class="reference internal" href="#parameters" id="id30">Parameters</a></li>
+<li><a class="reference internal" href="#pitch" id="id31">Pitch</a></li>
</ul>
</li>
</ul>
</li>
-<li><a class="reference internal" href="#id1" id="id30">Parameters</a><ul>
-<li><a class="reference internal" href="#types" id="id31">Types</a></li>
-<li><a class="reference internal" href="#scales" id="id32">Scales</a></li>
-<li><a class="reference internal" href="#automations" id="id33">Automations</a></li>
+<li><a class="reference internal" href="#id1" id="id32">Parameters</a><ul>
+<li><a class="reference internal" href="#types" id="id33">Types</a></li>
+<li><a class="reference internal" href="#scales" id="id34">Scales</a></li>
+<li><a class="reference internal" href="#automation" id="id35">Automation</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#graphical-user-interface" id="id34">Graphical User Interface</a><ul>
-<li><a class="reference internal" href="#showing-the-gui" id="id35">Showing the GUI</a></li>
-<li><a class="reference internal" href="#sending-events-to-the-host" id="id36">Sending events to the host</a></li>
-<li><a class="reference internal" href="#hiding-the-gui" id="id37">Hiding the GUI</a></li>
+<li><a class="reference internal" href="#graphical-user-interface" id="id36">Graphical User Interface</a><ul>
+<li><a class="reference internal" href="#showing-the-gui" id="id37">Showing the GUI</a></li>
+<li><a class="reference internal" href="#sending-events-to-the-host" id="id38">Sending events to the host</a></li>
+<li><a class="reference internal" href="#hiding-the-gui" id="id39">Hiding the GUI</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#presets" id="id38">Presets</a><ul>
-<li><a class="reference internal" href="#list-plugin-s-presets" id="id39">List plugin's presets</a></li>
-<li><a class="reference internal" href="#load-a-preset" id="id40">Load a preset</a></li>
+<li><a class="reference internal" href="#presets" id="id40">Presets</a><ul>
+<li><a class="reference internal" href="#list-plugin-s-presets" id="id41">List plugin's presets</a></li>
+<li><a class="reference internal" href="#load-a-preset" id="id42">Load a preset</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#save-and-restore-plugin-s-state" id="id41">Save and restore plugin's state</a></li>
-<li><a class="reference internal" href="#extension-system" id="id42">Extension system</a></li>
+<li><a class="reference internal" href="#save-and-restore-plugin-s-state" id="id43">Save and restore plugin's state</a></li>
+<li><a class="reference internal" href="#extension-system" id="id44">Extension system</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#examples" id="id43">Examples</a><ul>
-<li><a class="reference internal" href="#samples-clap-info-c" id="id44">samples/clap-info.c</a></li>
+<li><a class="reference internal" href="#examples" id="id45">Examples</a><ul>
+<li><a class="reference internal" href="#samples-clap-info-c" id="id46">samples/clap-info.c</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#references" id="id45">References</a><ul>
-<li><a class="reference internal" href="#clap-c" id="id46">clap.c</a></li>
+<li><a class="reference internal" href="#references" id="id47">References</a><ul>
+<li><a class="reference internal" href="#clap-c" id="id48">clap.c</a></li>
</ul>
</li>
</ul>
@@ -202,48 +204,111 @@ tt.docutils {
ensure that basic functionnality are working</li>
</ul>
</div>
+<div class="section" id="design-choice">
+<h2><a class="toc-backref" href="#id4">Design choice</a></h2>
+<ul class="simple">
+<li>The plugin and the host interface must be thread-safe.</li>
+<li>Avoid pointer exchange between the host and the plugin
+whenever it is possible. The choose way is to pass a buffer
+as a parameter and let the host/plugin copy/read data from it.
+Rationale: as the host and the plugin can be multi-threaded,
+keeping pointers to the plugin or host internal memory can lead
+to race conditions. Also it can lead to ambiguities about who's
+responsible to free the memory. Also the host and the plugin
+may use custom allocator.</li>
+<li>Use the C language.</li>
+<li>Have support for dynamic configuration, to let a modular plugin
+add new parameters, new outputs/inputs, etc... dynamically.</li>
+</ul>
+</div>
</div>
<div class="section" id="specification">
-<h1><a class="toc-backref" href="#id4">Specification</a></h1>
+<h1><a class="toc-backref" href="#id5">Specification</a></h1>
<div class="section" id="encoding">
-<h2><a class="toc-backref" href="#id5">Encoding</a></h2>
+<h2><a class="toc-backref" href="#id6">Encoding</a></h2>
<p>All the strings exchanged through the CLAP interface must be encoded in UTF-8
and must be valid.</p>
</div>
<div class="section" id="plugins-location">
-<h2><a class="toc-backref" href="#id6">Plugins location</a></h2>
+<h2><a class="toc-backref" href="#id7">Plugins location</a></h2>
<div class="section" id="common">
-<h3><a class="toc-backref" href="#id7">Common</a></h3>
+<h3><a class="toc-backref" href="#id8">Common</a></h3>
<ul class="simple">
-<li>Directories should be scanned recursively</li>
+<li>Directories should be scanned recursively.</li>
</ul>
</div>
<div class="section" id="linux">
-<h3><a class="toc-backref" href="#id8">Linux</a></h3>
+<h3><a class="toc-backref" href="#id9">Linux</a></h3>
<ul class="simple">
-<li>Plugins distrubuted with packages should be installed to: <tt class="docutils literal">/usr/lib/clap/</tt></li>
+<li>Plugins distributed with packages should be installed to: <tt class="docutils literal">/usr/lib/clap/</tt></li>
<li>Plugins installed in the user's home should be installed to: <tt class="docutils literal"><span class="pre">${HOME}/.clap/</span></tt></li>
</ul>
</div>
<div class="section" id="windows">
-<h3><a class="toc-backref" href="#id9">Windows</a></h3>
+<h3><a class="toc-backref" href="#id10">Windows</a></h3>
<p>TBD</p>
</div>
<div class="section" id="mac">
-<h3><a class="toc-backref" href="#id10">Mac</a></h3>
+<h3><a class="toc-backref" href="#id11">Mac</a></h3>
<p>TBD</p>
</div>
+<div class="section" id="multi-architecture-conventions">
+<h3><a class="toc-backref" href="#id12">Multi-architecture conventions</a></h3>
+<p>Let's say that we have a plugin called <tt class="docutils literal">DigitalDragon</tt>. If we distribute
+it for multiple architecture, then the host should be able to identify which
+version is suited for the current architecture by reading its name.</p>
+<p>For example:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="33%" />
+<col width="68%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head">Archtecture</th>
+<th class="head">Filename</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td>x86</td>
+<td>DigitalDragon.x86.so</td>
+</tr>
+<tr><td>x86_64</td>
+<td>DigitalDragon.x86_64.so</td>
+</tr>
+<tr><td>alpha</td>
+<td>DigitalDrapon.alpha.so</td>
+</tr>
+<tr><td>arm</td>
+<td>DigitalDrapon.arm.so</td>
+</tr>
+<tr><td>sparc</td>
+<td>DigitalDrapon.sparc.so</td>
+</tr>
+<tr><td>hppa</td>
+<td>DigitalDrapon.hppa.so</td>
+</tr>
+<tr><td>ppc</td>
+<td>DigitalDrapon.ppc.so</td>
+</tr>
+<tr><td>ppc64</td>
+<td>DigitalDrapon.ppc64.so</td>
+</tr>
+</tbody>
+</table>
+<p>If the name does not contain an indicator, then the plugin should be
+built for the native/current architecture.</p>
+</div>
</div>
<div class="section" id="instantiate-a-plugin">
-<h2><a class="toc-backref" href="#id11">Instantiate a plugin</a></h2>
-<p>Plugin instanciation can be done in a few steps:</p>
+<h2><a class="toc-backref" href="#id13">Instantiate a plugin</a></h2>
+<p>Plugin instantiating can be done in a few steps:</p>
<ul class="simple">
<li>load the plugin library</li>
<li>find the symbol <tt class="docutils literal">clap_create</tt></li>
<li>instantiate the plugin by calling <tt class="docutils literal">clap_create</tt></li>
</ul>
<div class="section" id="precautions">
-<h3><a class="toc-backref" href="#id12">Precautions</a></h3>
+<h3><a class="toc-backref" href="#id14">Precautions</a></h3>
<ul class="simple">
<li>The function <tt class="docutils literal">clap_create</tt> must be thread-safe.</li>
<li>It must not throw exceptions.</li>
@@ -251,19 +316,19 @@ and must be valid.</p>
</ul>
</div>
<div class="section" id="shell-plugins">
-<h3><a class="toc-backref" href="#id13">Shell plugins</a></h3>
+<h3><a class="toc-backref" href="#id15">Shell plugins</a></h3>
<p>A single dynamic library can contains multiple clap plugins.
To list them, you have to call <tt class="docutils literal">clap_create</tt> with an index of 0 and increment
the index until you reach <tt class="docutils literal">plugin_count</tt>.
<tt class="docutils literal">clap_create</tt> returns <tt class="docutils literal">NULL</tt> if the plugin creation failed or if
<tt class="docutils literal">plugin_index >= plugin_count</tt>.</p>
<div class="section" id="sample-plugin-loader">
-<h4><a class="toc-backref" href="#id14">Sample plugin loader</a></h4>
+<h4><a class="toc-backref" href="#id16">Sample plugin loader</a></h4>
<p>See <a class="reference internal" href="#samples-clap-info-c">samples/clap-info.c</a></p>
</div>
</div>
<div class="section" id="description">
-<h3><a class="toc-backref" href="#id15">Description</a></h3>
+<h3><a class="toc-backref" href="#id17">Description</a></h3>
<p>Both the plugin and host have a few attribute giving general plugin description.</p>
<table border="1" class="docutils">
<colgroup>
@@ -310,18 +375,25 @@ should be the same on 32bits or 64bits or whatever.</td>
<tt class="docutils literal"><span class="pre">http://company.com/support</span></tt>.</td>
</tr>
<tr><td>categories</td>
-<td>An array of categories, the plugins fits into. Eg: analogue,
-digital, fm, delay, reverb, compressor, ...</td>
+<td>A string containing a list of categories, joined with <tt class="docutils literal">;</tt>.
+For example: <tt class="docutils literal">fm;analogue;delay</tt>.</td>
</tr>
-<tr><td>plugin_type</td>
+<tr><td>type</td>
<td>Bitfield describing what the plugin does. See
<tt class="docutils literal">enum clap_plugin_type</tt>.</td>
</tr>
+<tr><td>chunk_size</td>
+<td>The process buffer, must have a number of sample multiple of
+<tt class="docutils literal">chunk_size</tt>.</td>
+</tr>
+<tr><td>latency</td>
+<td>The latency introduced by the plugin.</td>
+</tr>
<tr><td>has_gui</td>
<td>True if the plugin can show a graphical user interface</td>
</tr>
-<tr><td>supports_tunning</td>
-<td>True if the plugin supports tunning</td>
+<tr><td>supports_tuning</td>
+<td>True if the plugin supports tuning</td>
</tr>
<tr><td>supports_microtones</td>
<td>True if the plugin supports micro tones</td>
@@ -335,14 +407,14 @@ digital, fm, delay, reverb, compressor, ...</td>
</tbody>
</table>
</div>
-<div class="section" id="audio-channel-configuration">
-<h3><a class="toc-backref" href="#id16">Audio channel configuration</a></h3>
-<p>A plugin may have multiple audio channels, and so multiple audio channels
+<div class="section" id="audio-ports-configuration">
+<h3><a class="toc-backref" href="#id18">Audio ports configuration</a></h3>
+<p>A plugin may have multiple audio ports, and so multiple audio ports
layout or configurations.</p>
-<p>An audio channel has a type: mono, stereo, surround and a role: main
+<p>An audio port has a type: mono, stereo, surround and a role: main
input/output, sidechain, feedback.</p>
<div class="section" id="pin-layout">
-<h4><a class="toc-backref" href="#id17">Pin layout</a></h4>
+<h4><a class="toc-backref" href="#id19">Pin layout</a></h4>
<table border="1" class="docutils">
<colgroup>
<col width="28%" />
@@ -461,61 +533,70 @@ right feedback</td>
</table>
</div>
<div class="section" id="available-configurations">
-<h4><a class="toc-backref" href="#id18">Available configurations</a></h4>
-<p>It is possible to discover a plugin's channel configurations by calling
-<tt class="docutils literal"><span class="pre">plugin->get_channels_configs(plugin);</span></tt>. It returns a newly allocated linked
-list of configurations. It is the responsability of the host to free the list.</p>
+<h4><a class="toc-backref" href="#id20">Available configurations</a></h4>
+<p>It is possible to discover a plugin's port configurations by calling
+<tt class="docutils literal"><span class="pre">plugin->get_ports_configs_count(plugin);</span></tt>. It returns the number of
+configurations. Then for each configuration you have to call
+<tt class="docutils literal"><span class="pre">plugin->get_ports_config(plugin,</span> config_index, &config);</tt> which will
+tell you the number of input and output ports. Then to get the port details,
+you have to call
+<tt class="docutils literal"><span class="pre">plugin->get_port_info(plugin,</span> config_index, port_index, &port);</tt>.</p>
</div>
<div class="section" id="selecting-a-configuration">
-<h4><a class="toc-backref" href="#id19">Selecting a configuration</a></h4>
+<h4><a class="toc-backref" href="#id21">Selecting a configuration</a></h4>
<p>Selecting an audio configuration has to be done when the plugin is deactivated.
-It is done by calling <tt class="docutils literal"><span class="pre">plugin->set_channels_config(plugin,</span> config)</tt>.</p>
-<p>The host should make sure that the config stays allocated/available until
-an other call to <tt class="docutils literal"><span class="pre">plugin->set_channel_config()</span></tt> or
-<tt class="docutils literal"><span class="pre">plugin->destroy(plugin)</span></tt>.</p>
-<p><tt class="docutils literal"><span class="pre">plugin->set_channels_config(plugin,</span> config)</tt> returns <tt class="docutils literal">true</tt> if the
-confiugration is successful, <tt class="docutils literal">false</tt> otherwise.</p>
+It is done by calling <tt class="docutils literal"><span class="pre">plugin->set_port_config(plugin,</span> config_index)</tt>.
+If the call returns false, then the plugin is in failed state.</p>
</div>
<div class="section" id="repeatable-channels">
-<h4><a class="toc-backref" href="#id20">Repeatable channels</a></h4>
+<h4><a class="toc-backref" href="#id22">Repeatable channels</a></h4>
<p>Repeatable channels are a special case. A channel can be identified as
repeatable if <tt class="docutils literal"><span class="pre">channel->is_repeatable</span> == true</tt>.</p>
-<p>A usefull case is for an analyzer. Imagine a spectroscope, to which you want to
+<p>A useful case is for an analyzer. Imagine a spectroscope, to which you want to
plug any number of inputs. Each of those inputs can be named and displayed in
the spectrograph, so it is a convinient way analyze many tracks in the same
spectroscope.</p>
-<p>To repeat a channel, just duplicate it and insert it between the original and
-its next channel. Then call <tt class="docutils literal"><span class="pre">plugin->set_channels_config(plugin,</span> config);</tt>.</p>
+<p>For the special case of repeatable side chain input, the host
+has to tell the plugin how many times the port should be repeated.
+To do that it has to call <tt class="docutils literal"><span class="pre">plugin->set_port_repeat(plugin,</span> port_index, count)</tt>.
+If it returns <tt class="docutils literal">false</tt> then the plugin is in the same state as before
+the call.</p>
</div>
<div class="section" id="feedback-stream">
-<h4><a class="toc-backref" href="#id21">Feedback stream</a></h4>
+<h4><a class="toc-backref" href="#id23">Feedback stream</a></h4>
<p>Feedback stream are used to plug external audio processing into one
of the plugin feedback loop.</p>
<p>A practical usage is to put an effect in a delay feedback loop.</p>
<p>A feedback loop has it's both ends identified by <tt class="docutils literal"><span class="pre">clap_channel->stream_id</span></tt>.</p>
<p>During the audio processing, <tt class="docutils literal">struct clap_process</tt> contains a callback which
-is used to process the feeback stream:</p>
+is used to process the feedback stream:</p>
<pre class="code c literal-block">
<span class="kt">void</span> <span class="nf">my_plugin_process</span><span class="p">(</span><span class="k">struct</span> <span class="n">clap_plugin</span> <span class="o">*</span><span class="n">plugin</span><span class="p">,</span> <span class="k">struct</span> <span class="n">clap_process</span> <span class="o">*</span><span class="n">process</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">uint32_t</span> <span class="n">fb_in</span><span class="p">;</span> <span class="c1">// index to the stereo feedback input buffer
</span> <span class="kt">uint32_t</span> <span class="n">fb_out</span><span class="p">;</span> <span class="c1">// index to the stereo feedback output buffer
</span> <span class="kt">uint32_t</span> <span class="n">stream_id</span><span class="p">;</span> <span class="c1">// the feedback stream id
-</span>
- <span class="c1">// one sample process loop
-</span> <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">process</span><span class="o">-></span><span class="n">nb_samples</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
- <span class="c1">// audio processing
+</span> <span class="kt">uint32_t</span> <span class="n">offset</span><span class="p">;</span>
+
+ <span class="c1">// process all the buffer
+</span> <span class="k">for</span> <span class="p">(</span><span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">offset</span> <span class="o"><</span> <span class="n">process</span><span class="o">-></span><span class="n">nb_samples</span><span class="p">;</span>
+ <span class="n">offset</span> <span class="o">+=</span> <span class="n">process</span><span class="o">-></span><span class="n">feedback_chunk_size</span><span class="p">)</span>
+ <span class="p">{</span>
+
+ <span class="c1">// ...
</span>
<span class="c1">// prepare feedback output buffer
-</span> <span class="n">process</span><span class="o">-></span><span class="n">output</span><span class="p">[</span><span class="n">fb_out</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">XXX</span><span class="p">;</span>
- <span class="n">process</span><span class="o">-></span><span class="n">output</span><span class="p">[</span><span class="n">fb_out</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">XXX</span><span class="p">;</span>
+</span> <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">process</span><span class="o">-></span><span class="n">feedback_chunk_size</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
+ <span class="n">process</span><span class="o">-></span><span class="n">output</span><span class="p">[</span><span class="n">fb_out</span><span class="p">][</span><span class="n">offset</span> <span class="o">+</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">XXX</span><span class="p">;</span>
+ <span class="n">process</span><span class="o">-></span><span class="n">output</span><span class="p">[</span><span class="n">fb_out</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">offset</span> <span class="o">+</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">XXX</span><span class="p">;</span>
+ <span class="p">}</span>
<span class="c1">// process one sample feedback
</span> <span class="n">process</span><span class="o">-></span><span class="n">feedback</span><span class="p">(</span><span class="n">process</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="c1">// audio processing of the feedback values:
-</span> <span class="c1">// process->input[fb_in][i]
-</span> <span class="c1">// process->input[fb_in + 1][i]
+</span> <span class="c1">// process->input[fb_in][offset + i]
+</span> <span class="c1">// process->input[fb_in + 1][offset + i]
</span> <span class="p">}</span>
<span class="p">}</span>
</pre>
@@ -523,11 +604,11 @@ is used to process the feeback stream:</p>
</div>
</div>
<div class="section" id="threading">
-<h2><a class="toc-backref" href="#id22">Threading</a></h2>
+<h2><a class="toc-backref" href="#id24">Threading</a></h2>
<p>The plugin must be thread safe.</p>
</div>
<div class="section" id="activation">
-<h2><a class="toc-backref" href="#id23">Activation</a></h2>
+<h2><a class="toc-backref" href="#id25">Activation</a></h2>
<p>Before doing any processing, the plugin must be activated by calling
<tt class="docutils literal">bool succeed = <span class="pre">plugin->activate(plugin);</span></tt>.</p>
<p>If <tt class="docutils literal">succeed == true</tt> then the activation succeed. If the activation failed,
@@ -546,7 +627,7 @@ not activated.</p>
<p>It is preferable to de-activate the plugin before destroying it.</p>
</div>
<div class="section" id="processing">
-<h2><a class="toc-backref" href="#id24">Processing</a></h2>
+<h2><a class="toc-backref" href="#id26">Processing</a></h2>
<p>The processing is done in one call: <tt class="docutils literal"><span class="pre">plugin->process(plugin,</span> process);</tt>.
The data structure process regroup everything needed by the plugin:</p>
<ul class="simple">
@@ -557,15 +638,15 @@ The data structure process regroup everything needed by the plugin:</p>
<li>more processing needed (out)</li>
</ul>
<div class="section" id="audio-buffers">
-<h3><a class="toc-backref" href="#id25">Audio buffers</a></h3>
+<h3><a class="toc-backref" href="#id27">Audio buffers</a></h3>
<p>The audio buffers are allocated by the host. They must be aligned by the
-maximum requirement of the vector instructions currently avalaible.</p>
+maximum requirement of the vector instructions currently available.</p>
<p>In-place processing is not supported.</p>
<p>There is no minimum number of samples.</p>
<p>See <a class="reference internal" href="#pin-layout">Pin layout</a>.</p>
</div>
<div class="section" id="events">
-<h3><a class="toc-backref" href="#id26">Events</a></h3>
+<h3><a class="toc-backref" href="#id28">Events</a></h3>
<ul class="simple">
<li>Events are relative to <tt class="docutils literal"><span class="pre">process->time_in_samples</span></tt>.</li>
<li>Their time must be within the process duration: positive and included
@@ -577,17 +658,17 @@ into <tt class="docutils literal"><span class="pre">[0..process->nb_samples[<
(<tt class="docutils literal">in_events</tt> and <tt class="docutils literal">out_events</tt>).</li>
</ul>
<div class="section" id="notes">
-<h4><a class="toc-backref" href="#id27">Notes</a></h4>
-<p>Notes are reprensented as a pair <tt class="docutils literal">note, division</tt>.
+<h4><a class="toc-backref" href="#id29">Notes</a></h4>
+<p>Notes are represented as a pair <tt class="docutils literal">note, division</tt>.
Division is the number of intervals between one note and an other note with
half or the double frequency. A division by 12 must be supported.</p>
<p>If a plugin plugin does not support micro tones, it should ignore
-micro-tunned notes.</p>
+micro-tuned notes.</p>
<p>The host should not send micro tones to the plugin if
<tt class="docutils literal"><span class="pre">plugin->supports_microtones</span> == false</tt>.</p>
</div>
<div class="section" id="parameters">
-<h4><a class="toc-backref" href="#id28">Parameters</a></h4>
+<h4><a class="toc-backref" href="#id30">Parameters</a></h4>
<p>Parameters can be automated by the host using <tt class="docutils literal">CLAP_EVENT_PARAM_SET</tt> or
<tt class="docutils literal">CLAP_EVENT_PARAM_RAMP</tt>.</p>
<p>When using <tt class="docutils literal">CLAP_EVENT_PARAM_RAMP</tt>, the value of the parameter has to be
@@ -595,19 +676,19 @@ incremented by <tt class="docutils literal"><span class="pre">event->param.in
occur on this parameter.</p>
</div>
<div class="section" id="pitch">
-<h4><a class="toc-backref" href="#id29">Pitch</a></h4>
+<h4><a class="toc-backref" href="#id31">Pitch</a></h4>
<p>The pitch is the frequency of the note A4. Its default value is 440Hz.
The pitch can be changed by the host using the <tt class="docutils literal">CLAP_EVENT_PITCH_SET</tt> event.</p>
</div>
</div>
</div>
<div class="section" id="id1">
-<h2><a class="toc-backref" href="#id30">Parameters</a></h2>
+<h2><a class="toc-backref" href="#id32">Parameters</a></h2>
<p>The host can get the plugin's parameters tree by calling
<tt class="docutils literal"><span class="pre">plugin->get_params(plugin)</span></tt>. The host is responsible to free the return
value.</p>
<div class="section" id="types">
-<h3><a class="toc-backref" href="#id31">Types</a></h3>
+<h3><a class="toc-backref" href="#id33">Types</a></h3>
<p>There are a few parameter types:</p>
<table border="1" class="docutils">
<colgroup>
@@ -625,7 +706,7 @@ value.</p>
<tr><td>group</td>
<td>none</td>
<td>not a value, but the only parameter which can have
-childs. It should be used to organise parameters in
+child. It should be used to organize parameters in
the host GUI.</td>
</tr>
<tr><td>bool</td>
@@ -649,33 +730,33 @@ should rely on <tt class="docutils literal">display_text</tt> to show its value.
</table>
</div>
<div class="section" id="scales">
-<h3><a class="toc-backref" href="#id32">Scales</a></h3>
+<h3><a class="toc-backref" href="#id34">Scales</a></h3>
<p>The plugin can inform the host, which scale to use for the parameter's UI
(knob, slider, ...). <tt class="docutils literal"><span class="pre">clap_param->scale</span></tt> can be set to <tt class="docutils literal">CLAP_PARAM_LINEAR</tt>
or <tt class="docutils literal">CLAP_PARAM_LOG</tt>. A logarithmic scale is convinient for a frequency
parameter.</p>
</div>
-<div class="section" id="automations">
-<h3><a class="toc-backref" href="#id33">Automations</a></h3>
+<div class="section" id="automation">
+<h3><a class="toc-backref" href="#id35">Automation</a></h3>
<p>When a parameter is modified by the GUI, the plugin should send a
<tt class="docutils literal">CLAP_EVENT_SET</tt> event must be sent to the host, using
<tt class="docutils literal"><span class="pre">host->events(host,</span> plugin, events);</tt> so the host can record the automation.</p>
-<p>When a parameter is modified by an other parameter, for exemple imagine you
+<p>When a parameter is modified by an other parameter, for example imagine you
have a parameter modulating "absolutely" an other one through an XY mapping.
The host should record the modulation source but not the modulation target.
To do that the plugin uses <tt class="docutils literal"><span class="pre">clap_event_param->is_recordable</span></tt>.</p>
</div>
</div>
<div class="section" id="graphical-user-interface">
-<h2><a class="toc-backref" href="#id34">Graphical User Interface</a></h2>
+<h2><a class="toc-backref" href="#id36">Graphical User Interface</a></h2>
<div class="section" id="showing-the-gui">
-<h3><a class="toc-backref" href="#id35">Showing the GUI</a></h3>
+<h3><a class="toc-backref" href="#id37">Showing the GUI</a></h3>
<p>The plugin should show the GUI after a call to <tt class="docutils literal"><span class="pre">plugin->show_gui(plugin)</span></tt>.
If the plugin could successfully show the GUI, it returns <tt class="docutils literal">true</tt>, <tt class="docutils literal">false</tt>
otherwise.</p>
</div>
<div class="section" id="sending-events-to-the-host">
-<h3><a class="toc-backref" href="#id36">Sending events to the host</a></h3>
+<h3><a class="toc-backref" href="#id38">Sending events to the host</a></h3>
<p>The plugin can notify the host of parameter changes by sending events to:
<tt class="docutils literal"><span class="pre">host->events(host,</span> plugin, events);</tt>.</p>
<p>Events sent to the host should be stamped:</p>
@@ -687,7 +768,7 @@ otherwise.</p>
</pre>
</div>
<div class="section" id="hiding-the-gui">
-<h3><a class="toc-backref" href="#id37">Hiding the GUI</a></h3>
+<h3><a class="toc-backref" href="#id39">Hiding the GUI</a></h3>
<p>The plugin should hide the GUI after a call to <tt class="docutils literal"><span class="pre">plugin->hide_gui(plugin)</span></tt>.
If the plugin window has been closed by the user, then the plugin should
send an event <tt class="docutils literal">CLAP_EVENT_GUI_CLOSED</tt> to the host.</p>
@@ -701,15 +782,15 @@ send an event <tt class="docutils literal">CLAP_EVENT_GUI_CLOSED</tt> to the hos
</div>
</div>
<div class="section" id="presets">
-<h2><a class="toc-backref" href="#id38">Presets</a></h2>
+<h2><a class="toc-backref" href="#id40">Presets</a></h2>
<div class="section" id="list-plugin-s-presets">
-<h3><a class="toc-backref" href="#id39">List plugin's presets</a></h3>
-<p>The host can browse the plugin's preset by callign <tt class="docutils literal"><span class="pre">plugin->get_presets(plugin);</span></tt>.
+<h3><a class="toc-backref" href="#id41">List plugin's presets</a></h3>
+<p>The host can browse the plugin's preset by calling <tt class="docutils literal"><span class="pre">plugin->get_presets(plugin);</span></tt>.
This function returns a newly allocated preset linked list.
It is the responsibility of the host to free the linked list.</p>
</div>
<div class="section" id="load-a-preset">
-<h3><a class="toc-backref" href="#id40">Load a preset</a></h3>
+<h3><a class="toc-backref" href="#id42">Load a preset</a></h3>
<p>To load a preset, the host should send an event <tt class="docutils literal">CLAP_EVENT_PRESET_SET</tt> to
the plugin.</p>
<p>When a preset is loaded from the plugin's GUI, the plugin must send a
@@ -717,7 +798,7 @@ the plugin.</p>
</div>
</div>
<div class="section" id="save-and-restore-plugin-s-state">
-<h2><a class="toc-backref" href="#id41">Save and restore plugin's state</a></h2>
+<h2><a class="toc-backref" href="#id43">Save and restore plugin's state</a></h2>
<p>Saving the plugin's state is done by:</p>
<pre class="code c literal-block">
<span class="kt">void</span> <span class="o">*</span><span class="n">buffer</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
@@ -730,12 +811,12 @@ the plugin.</p>
<pre class="code c literal-block">
<span class="n">plugin</span><span class="o">-></span><span class="n">restore</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</pre>
-<p>The state of the plugin should be indepentant of the machine: you can save a
+<p>The state of the plugin should be independent of the machine: you can save a
plugin state on a little endian machine and send it through the network to a
big endian machine, it should load again successfully.</p>
</div>
<div class="section" id="extension-system">
-<h2><a class="toc-backref" href="#id42">Extension system</a></h2>
+<h2><a class="toc-backref" href="#id44">Extension system</a></h2>
<p>To extend clap's functionnality, there is a pretty simple mechanism:</p>
<pre class="code c literal-block">
<span class="kt">void</span> <span class="o">*</span><span class="n">plug_ext</span> <span class="o">=</span> <span class="n">plugin</span><span class="o">-></span><span class="n">extension</span><span class="p">(</span><span class="n">plug</span><span class="p">,</span> <span class="s">"company/ext-name"</span><span class="p">);</span>
@@ -745,9 +826,9 @@ big endian machine, it should load again successfully.</p>
</div>
</div>
<div class="section" id="examples">
-<h1><a class="toc-backref" href="#id43">Examples</a></h1>
+<h1><a class="toc-backref" href="#id45">Examples</a></h1>
<div class="section" id="samples-clap-info-c">
-<h2><a class="toc-backref" href="#id44">samples/clap-info.c</a></h2>
+<h2><a class="toc-backref" href="#id46">samples/clap-info.c</a></h2>
<pre class="code c literal-block">
<span class="cp">#include <stdio.h>
#include <dlfcn.h>
@@ -847,9 +928,9 @@ big endian machine, it should load again successfully.</p>
</div>
</div>
<div class="section" id="references">
-<h1><a class="toc-backref" href="#id45">References</a></h1>
+<h1><a class="toc-backref" href="#id47">References</a></h1>
<div class="section" id="clap-c">
-<h2><a class="toc-backref" href="#id46">clap.c</a></h2>
+<h2><a class="toc-backref" href="#id48">clap.c</a></h2>
<pre class="code c literal-block">
<span class="cm">/**
* CLAP - CLever Audio Plugin (<--- needs to find a marketing ok name)
@@ -910,6 +991,15 @@ big endian machine, it should load again successfully.</p>
<span class="n">CLAP_URL_SIZE</span> <span class="o">=</span> <span class="mi">256</span><span class="p">,</span>
<span class="p">};</span>
+<span class="k">enum</span> <span class="n">clap_log_severity</span>
+<span class="p">{</span>
+ <span class="n">CLAP_LOG_DEBUG</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+ <span class="n">CLAP_LOG_INFO</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
+ <span class="n">CLAP_LOG_WARNING</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
+ <span class="n">CLAP_LOG_ERROR</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span>
+ <span class="n">CLAP_LOG_FATAL</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span>
+<span class="p">};</span>
+
<span class="c1">///////////
// PORTS //
///////////
@@ -1138,6 +1228,11 @@ big endian machine, it should load again successfully.</p>
* value must be greater or equal to the previous one. */</span>
<span class="kt">uint64_t</span> <span class="p">(</span><span class="o">*</span><span class="n">steady_time</span><span class="p">)(</span><span class="k">struct</span> <span class="n">clap_host</span> <span class="o">*</span><span class="n">host</span><span class="p">);</span>
+ <span class="cm">/* Log a message through the host. */</span>
+ <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">log</span><span class="p">)(</span><span class="k">struct</span> <span class="n">clap_host</span> <span class="o">*</span><span class="n">host</span><span class="p">,</span>
+ <span class="k">enum</span> <span class="n">clap_log_severity</span> <span class="n">severity</span><span class="p">,</span>
+ <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">msg</span><span class="p">);</span>
+
<span class="cm">/* future features */</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">extension</span><span class="p">)(</span><span class="k">struct</span> <span class="n">clap_host</span> <span class="o">*</span><span class="n">host</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">extention_id</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span>
<span class="p">};</span>
@@ -1180,7 +1275,7 @@ big endian machine, it should load again successfully.</p>
</span> <span class="kt">uint32_t</span> <span class="n">chunk_size</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">has_gui</span><span class="p">;</span>
- <span class="kt">bool</span> <span class="n">supports_tunning</span><span class="p">;</span>
+ <span class="kt">bool</span> <span class="n">supports_tuning</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">supports_microtones</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">latency</span><span class="p">;</span> <span class="c1">// latency in samples
diff --git a/spec.rst b/spec.rst
@@ -29,6 +29,22 @@ Later goals
- Provide a validation host, which should give hard time to the plugin and
ensure that basic functionnality are working
+Design choice
+-------------
+
+- The plugin and the host interface must be thread-safe.
+- Avoid pointer exchange between the host and the plugin
+ whenever it is possible. The choose way is to pass a buffer
+ as a parameter and let the host/plugin copy/read data from it.
+ Rationale: as the host and the plugin can be multi-threaded,
+ keeping pointers to the plugin or host internal memory can lead
+ to race conditions. Also it can lead to ambiguities about who's
+ responsible to free the memory. Also the host and the plugin
+ may use custom allocator.
+- Use the C language.
+- Have support for dynamic configuration, to let a modular plugin
+ add new parameters, new outputs/inputs, etc... dynamically.
+
Specification
=============
@@ -44,12 +60,12 @@ Plugins location
Common
~~~~~~
-- Directories should be scanned recursively
+- Directories should be scanned recursively.
Linux
~~~~~
-- Plugins distrubuted with packages should be installed to: ``/usr/lib/clap/``
+- Plugins distributed with packages should be installed to: ``/usr/lib/clap/``
- Plugins installed in the user's home should be installed to: ``${HOME}/.clap/``
Windows
@@ -62,10 +78,42 @@ Mac
TBD
+Multi-architecture conventions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's say that we have a plugin called ``DigitalDragon``. If we distribute
+it for multiple architecture, then the host should be able to identify which
+version is suited for the current architecture by reading its name.
+
+For example:
+
++-------------+---------------------------+
+| Archtecture | Filename |
++=============+===========================+
+| x86 | DigitalDragon.x86.so |
++-------------+---------------------------+
+| x86_64 | DigitalDragon.x86_64.so |
++-------------+---------------------------+
+| alpha | DigitalDrapon.alpha.so |
++-------------+---------------------------+
+| arm | DigitalDrapon.arm.so |
++-------------+---------------------------+
+| sparc | DigitalDrapon.sparc.so |
++-------------+---------------------------+
+| hppa | DigitalDrapon.hppa.so |
++-------------+---------------------------+
+| ppc | DigitalDrapon.ppc.so |
++-------------+---------------------------+
+| ppc64 | DigitalDrapon.ppc64.so |
++-------------+---------------------------+
+
+If the name does not contain an indicator, then the plugin should be
+built for the native/current architecture.
+
Instantiate a plugin
--------------------
-Plugin instanciation can be done in a few steps:
+Plugin instantiating can be done in a few steps:
- load the plugin library
- find the symbol ``clap_create``
@@ -124,15 +172,20 @@ Both the plugin and host have a few attribute giving general plugin description.
| | ``mailto:support@company.com`` or |
| | ``http://company.com/support``. |
+---------------------+---------------------------------------------------------------+
-| categories | An array of categories, the plugins fits into. Eg: analogue, |
-| | digital, fm, delay, reverb, compressor, ... |
+| categories | A string containing a list of categories, joined with ``;``. |
+| | For example: ``fm;analogue;delay``. |
+---------------------+---------------------------------------------------------------+
-| plugin_type | Bitfield describing what the plugin does. See |
+| type | Bitfield describing what the plugin does. See |
| | ``enum clap_plugin_type``. |
+---------------------+---------------------------------------------------------------+
+| chunk_size | The process buffer, must have a number of sample multiple of |
+| | ``chunk_size``. |
++---------------------+---------------------------------------------------------------+
+| latency | The latency introduced by the plugin. |
++---------------------+---------------------------------------------------------------+
| has_gui | True if the plugin can show a graphical user interface |
+---------------------+---------------------------------------------------------------+
-| supports_tunning | True if the plugin supports tunning |
+| supports_tuning | True if the plugin supports tuning |
+---------------------+---------------------------------------------------------------+
| supports_microtones | True if the plugin supports micro tones |
+---------------------+---------------------------------------------------------------+
@@ -141,13 +194,13 @@ Both the plugin and host have a few attribute giving general plugin description.
| plugin_data | Reserved pointer for the plugin. |
+---------------------+---------------------------------------------------------------+
-Audio channel configuration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Audio ports configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~
-A plugin may have multiple audio channels, and so multiple audio channels
+A plugin may have multiple audio ports, and so multiple audio ports
layout or configurations.
-An audio channel has a type: mono, stereo, surround and a role: main
+An audio port has a type: mono, stereo, surround and a role: main
input/output, sidechain, feedback.
Pin layout
@@ -203,22 +256,20 @@ So for the following configuration:
Available configurations
````````````````````````
-It is possible to discover a plugin's channel configurations by calling
-``plugin->get_channels_configs(plugin);``. It returns a newly allocated linked
-list of configurations. It is the responsability of the host to free the list.
+It is possible to discover a plugin's port configurations by calling
+``plugin->get_ports_configs_count(plugin);``. It returns the number of
+configurations. Then for each configuration you have to call
+``plugin->get_ports_config(plugin, config_index, &config);`` which will
+tell you the number of input and output ports. Then to get the port details,
+you have to call
+``plugin->get_port_info(plugin, config_index, port_index, &port);``.
Selecting a configuration
`````````````````````````
Selecting an audio configuration has to be done when the plugin is deactivated.
-It is done by calling ``plugin->set_channels_config(plugin, config)``.
-
-The host should make sure that the config stays allocated/available until
-an other call to ``plugin->set_channel_config()`` or
-``plugin->destroy(plugin)``.
-
-``plugin->set_channels_config(plugin, config)`` returns ``true`` if the
-confiugration is successful, ``false`` otherwise.
+It is done by calling ``plugin->set_port_config(plugin, config_index)``.
+If the call returns false, then the plugin is in failed state.
Repeatable channels
```````````````````
@@ -226,13 +277,16 @@ Repeatable channels
Repeatable channels are a special case. A channel can be identified as
repeatable if ``channel->is_repeatable == true``.
-A usefull case is for an analyzer. Imagine a spectroscope, to which you want to
+A useful case is for an analyzer. Imagine a spectroscope, to which you want to
plug any number of inputs. Each of those inputs can be named and displayed in
the spectrograph, so it is a convinient way analyze many tracks in the same
spectroscope.
-To repeat a channel, just duplicate it and insert it between the original and
-its next channel. Then call ``plugin->set_channels_config(plugin, config);``.
+For the special case of repeatable side chain input, the host
+has to tell the plugin how many times the port should be repeated.
+To do that it has to call ``plugin->set_port_repeat(plugin, port_index, count)``.
+If it returns ``false`` then the plugin is in the same state as before
+the call.
Feedback stream
```````````````
@@ -245,7 +299,7 @@ A practical usage is to put an effect in a delay feedback loop.
A feedback loop has it's both ends identified by ``clap_channel->stream_id``.
During the audio processing, ``struct clap_process`` contains a callback which
-is used to process the feeback stream:
+is used to process the feedback stream:
.. code:: c
@@ -254,21 +308,27 @@ is used to process the feeback stream:
uint32_t fb_in; // index to the stereo feedback input buffer
uint32_t fb_out; // index to the stereo feedback output buffer
uint32_t stream_id; // the feedback stream id
+ uint32_t offset;
- // one sample process loop
- for (uint32_t i = 0; i < process->nb_samples; ++i) {
- // audio processing
+ // process all the buffer
+ for (offset = 0; offset < process->nb_samples;
+ offset += process->feedback_chunk_size)
+ {
+
+ // ...
// prepare feedback output buffer
- process->output[fb_out][i] = XXX;
- process->output[fb_out + 1][i] = XXX;
+ for (uint32_t i = 0; i < process->feedback_chunk_size; ++i) {
+ process->output[fb_out][offset + i] = XXX;
+ process->output[fb_out + 1][offset + i] = XXX;
+ }
// process one sample feedback
process->feedback(process, stream_id, 1);
// audio processing of the feedback values:
- // process->input[fb_in][i]
- // process->input[fb_in + 1][i]
+ // process->input[fb_in][offset + i]
+ // process->input[fb_in + 1][offset + i]
}
}
@@ -319,7 +379,7 @@ Audio buffers
~~~~~~~~~~~~~
The audio buffers are allocated by the host. They must be aligned by the
-maximum requirement of the vector instructions currently avalaible.
+maximum requirement of the vector instructions currently available.
In-place processing is not supported.
@@ -342,12 +402,12 @@ Events
Notes
`````
-Notes are reprensented as a pair ``note, division``.
+Notes are represented as a pair ``note, division``.
Division is the number of intervals between one note and an other note with
half or the double frequency. A division by 12 must be supported.
If a plugin plugin does not support micro tones, it should ignore
-micro-tunned notes.
+micro-tuned notes.
The host should not send micro tones to the plugin if
``plugin->supports_microtones == false``.
@@ -384,7 +444,7 @@ There are a few parameter types:
| type | value attribute | description |
+=======+=================+======================================================+
| group | none | not a value, but the only parameter which can have |
-| | | childs. It should be used to organise parameters in |
+| | | child. It should be used to organize parameters in |
| | | the host GUI. |
+-------+-----------------+------------------------------------------------------+
| bool | ``value.b`` | a boolean value, can be true or false |
@@ -405,14 +465,14 @@ The plugin can inform the host, which scale to use for the parameter's UI
or ``CLAP_PARAM_LOG``. A logarithmic scale is convinient for a frequency
parameter.
-Automations
-~~~~~~~~~~~
+Automation
+~~~~~~~~~~
When a parameter is modified by the GUI, the plugin should send a
``CLAP_EVENT_SET`` event must be sent to the host, using
``host->events(host, plugin, events);`` so the host can record the automation.
-When a parameter is modified by an other parameter, for exemple imagine you
+When a parameter is modified by an other parameter, for example imagine you
have a parameter modulating "absolutely" an other one through an XY mapping.
The host should record the modulation source but not the modulation target.
To do that the plugin uses ``clap_event_param->is_recordable``.
@@ -464,7 +524,7 @@ Presets
List plugin's presets
~~~~~~~~~~~~~~~~~~~~~
-The host can browse the plugin's preset by callign ``plugin->get_presets(plugin);``.
+The host can browse the plugin's preset by calling ``plugin->get_presets(plugin);``.
This function returns a newly allocated preset linked list.
It is the responsibility of the host to free the linked list.
@@ -496,7 +556,7 @@ Restoring the plugin's state is done by:
plugin->restore(plugin, buffer, size);
-The state of the plugin should be indepentant of the machine: you can save a
+The state of the plugin should be independent of the machine: you can save a
plugin state on a little endian machine and send it through the network to a
big endian machine, it should load again successfully.