commit b63b1146467c47d0680971bfff5721ab454418b6
parent 3cb666700fa6f40adb3b87a644888af72f8844dc
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Mon, 6 Oct 2014 11:30:29 +0200
update the spec
Diffstat:
M | include/clap/clap.h | | | 22 | ++++++++++++---------- |
M | spec.html | | | 176 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
M | spec.rst | | | 135 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
3 files changed, 218 insertions(+), 115 deletions(-)
diff --git a/include/clap/clap.h b/include/clap/clap.h
@@ -59,10 +59,6 @@ enum clap_channel_role
struct clap_channel
{
- /* linked list */
- struct clap_channel *next;
-
- /* channel info */
enum clap_channel_type type;
enum clap_channel_role role;
char *name;
@@ -72,10 +68,9 @@ struct clap_channel
struct clap_channels_config
{
- /* linked list */
- struct clap_channel_configs *next;
+ uint32_t input_count;
+ uint32_t output_count;
- /* config */
struct clap_channel *inputs;
struct clap_channel *output;
};
@@ -203,14 +198,16 @@ struct clap_event
struct clap_process
{
+ /* host custom ptr */
+ void *host_data;
+
/* audio buffers */
float **input;
float **output;
uint32_t nb_samples;
/* feedback loops */
- void (*feedback)(void *feedback_ctx, uint32_t stream_id, uint32_t nb_samples);
- void *feedback_ctx;
+ void (*feedback)(struct clap_process *process, uint32_t stream_id, uint32_t nb_samples);
/* process info */
bool is_offline;
@@ -279,8 +276,13 @@ struct clap_plugin
const char **caterogries; // fm, analogue, delay, reverb, ...
uint32_t plugin_type;
+ bool has_gui;
+ bool supports_tunning;
+ bool supports_microtones;
+
/* audio channels */
- struct clap_channels_config *(*get_channels_configs)(struct clap_plugin *plugin);
+ uint32_t channels_configs_count;
+ struct clap_channels_config *channels_configs;
bool (*set_channels_config)(struct clap_plugin *plugin,
struct clap_channels_config *config);
diff --git a/spec.html b/spec.html
@@ -132,42 +132,43 @@ tt.docutils {
<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>
</ul>
</li>
</ul>
</li>
-<li><a class="reference internal" href="#threading" id="id21">Threading</a></li>
-<li><a class="reference internal" href="#activation" id="id22">Activation</a></li>
-<li><a class="reference internal" href="#processing" id="id23">Processing</a><ul>
-<li><a class="reference internal" href="#audio-buffers" id="id24">Audio buffers</a></li>
-<li><a class="reference internal" href="#events" id="id25">Events</a><ul>
-<li><a class="reference internal" href="#notes" id="id26">Notes</a></li>
-<li><a class="reference internal" href="#parameters" id="id27">Parameters</a></li>
-<li><a class="reference internal" href="#pitch" id="id28">Pitch</a></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>
</ul>
</li>
</ul>
</li>
-<li><a class="reference internal" href="#id1" id="id29">Parameters</a></li>
-<li><a class="reference internal" href="#graphical-user-interface" id="id30">Graphical User Interface</a><ul>
-<li><a class="reference internal" href="#showing-the-gui" id="id31">Showing the GUI</a></li>
-<li><a class="reference internal" href="#sending-events-to-the-host" id="id32">Sending events to the host</a></li>
-<li><a class="reference internal" href="#hiding-the-gui" id="id33">Hiding the GUI</a></li>
+<li><a class="reference internal" href="#id1" id="id30">Parameters</a></li>
+<li><a class="reference internal" href="#graphical-user-interface" id="id31">Graphical User Interface</a><ul>
+<li><a class="reference internal" href="#showing-the-gui" id="id32">Showing the GUI</a></li>
+<li><a class="reference internal" href="#sending-events-to-the-host" id="id33">Sending events to the host</a></li>
+<li><a class="reference internal" href="#hiding-the-gui" id="id34">Hiding the GUI</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#presets" id="id34">Presets</a><ul>
-<li><a class="reference internal" href="#list-plugin-s-presets" id="id35">List plugin's presets</a></li>
-<li><a class="reference internal" href="#load-a-preset" id="id36">Load a preset</a></li>
+<li><a class="reference internal" href="#presets" id="id35">Presets</a><ul>
+<li><a class="reference internal" href="#list-plugin-s-presets" id="id36">List plugin's presets</a></li>
+<li><a class="reference internal" href="#load-a-preset" id="id37">Load a preset</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#save-and-restore-plugin-s-state" id="id37">Save and restore plugin's state</a></li>
-<li><a class="reference internal" href="#extension-system" id="id38">Extension system</a></li>
+<li><a class="reference internal" href="#save-and-restore-plugin-s-state" id="id38">Save and restore plugin's state</a></li>
+<li><a class="reference internal" href="#extension-system" id="id39">Extension system</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#examples" id="id39">Examples</a></li>
-<li><a class="reference internal" href="#references" id="id40">References</a><ul>
-<li><a class="reference internal" href="#clap-c" id="id41">clap.c</a></li>
-<li><a class="reference internal" href="#samples-clap-info-c" id="id42">samples/clap-info.c</a></li>
+<li><a class="reference internal" href="#examples" id="id40">Examples</a></li>
+<li><a class="reference internal" href="#references" id="id41">References</a><ul>
+<li><a class="reference internal" href="#clap-c" id="id42">clap.c</a></li>
+<li><a class="reference internal" href="#samples-clap-info-c" id="id43">samples/clap-info.c</a></li>
</ul>
</li>
</ul>
@@ -244,7 +245,7 @@ and must be valid.</p>
</div>
<div class="section" id="shell-plugins">
<h3><a class="toc-backref" href="#id13">Shell plugins</a></h3>
-<p>A single dynamic library can contains multiple plugins.
+<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
@@ -259,8 +260,8 @@ the index until you reach <tt class="docutils literal">plugin_count</tt>.
<p>Both the plugin and host have a few attribute giving general plugin description.</p>
<table border="1" class="docutils">
<colgroup>
-<col width="18%" />
-<col width="82%" />
+<col width="25%" />
+<col width="75%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Attribute</th>
@@ -306,8 +307,17 @@ should be the same on 32bits or 64bits or whatever.</td>
digital, fm, delay, reverb, compressor, ...</td>
</tr>
<tr><td>plugin_type</td>
-<td>Bitfield describing what the plugin does. See enum
-clap_plugin_type.</td>
+<td>Bitfield describing what the plugin does. See
+<tt class="docutils literal">enum clap_plugin_type</tt>.</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>
+<tr><td>supports_microtones</td>
+<td>True if the plugin supports micro tones</td>
</tr>
<tr><td>host_data</td>
<td>Reserved pointer for the host.</td>
@@ -445,7 +455,7 @@ right feedback</td>
</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 by calling
+<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>
</div>
@@ -453,8 +463,9 @@ list of configurations. It is the responsability of the host to free the list.</
<h4><a class="toc-backref" href="#id19">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 duplicate the config before passing it to the plugin, and the
-plugin is responsible to free the given config.</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>
</div>
@@ -469,14 +480,47 @@ 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>
</div>
+<div class="section" id="feedback-stream">
+<h4><a class="toc-backref" href="#id21">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>
+<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="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 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="p">}</span>
+<span class="p">}</span>
+</pre>
+</div>
</div>
</div>
<div class="section" id="threading">
-<h2><a class="toc-backref" href="#id21">Threading</a></h2>
+<h2><a class="toc-backref" href="#id22">Threading</a></h2>
<p>The plugin must be thread safe.</p>
</div>
<div class="section" id="activation">
-<h2><a class="toc-backref" href="#id22">Activation</a></h2>
+<h2><a class="toc-backref" href="#id23">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,
@@ -495,7 +539,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="#id23">Processing</a></h2>
+<h2><a class="toc-backref" href="#id24">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">
@@ -506,7 +550,7 @@ 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="#id24">Audio buffers</a></h3>
+<h3><a class="toc-backref" href="#id25">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>
<p>In-place processing is not supported.</p>
@@ -514,7 +558,7 @@ maximum requirement of the vector instructions currently avalaible.</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="#id25">Events</a></h3>
+<h3><a class="toc-backref" href="#id26">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
@@ -526,13 +570,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="#id26">Notes</a></h4>
+<h4><a class="toc-backref" href="#id27">Notes</a></h4>
<p>Notes are reprensented 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.</p>
+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>
+<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="#id27">Parameters</a></h4>
+<h4><a class="toc-backref" href="#id28">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
@@ -540,30 +588,30 @@ 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="#id28">Pitch</a></h4>
+<h4><a class="toc-backref" href="#id29">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="#id29">Parameters</a></h2>
+<h2><a class="toc-backref" href="#id30">Parameters</a></h2>
</div>
<div class="section" id="graphical-user-interface">
-<h2><a class="toc-backref" href="#id30">Graphical User Interface</a></h2>
+<h2><a class="toc-backref" href="#id31">Graphical User Interface</a></h2>
<div class="section" id="showing-the-gui">
-<h3><a class="toc-backref" href="#id31">Showing the GUI</a></h3>
+<h3><a class="toc-backref" href="#id32">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="#id32">Sending events to the host</a></h3>
+<h3><a class="toc-backref" href="#id33">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>
</div>
<div class="section" id="hiding-the-gui">
-<h3><a class="toc-backref" href="#id33">Hiding the GUI</a></h3>
+<h3><a class="toc-backref" href="#id34">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>
@@ -576,21 +624,21 @@ 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="#id34">Presets</a></h2>
+<h2><a class="toc-backref" href="#id35">Presets</a></h2>
<div class="section" id="list-plugin-s-presets">
-<h3><a class="toc-backref" href="#id35">List plugin's presets</a></h3>
+<h3><a class="toc-backref" href="#id36">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>.
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="#id36">Load a preset</a></h3>
+<h3><a class="toc-backref" href="#id37">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>
</div>
</div>
<div class="section" id="save-and-restore-plugin-s-state">
-<h2><a class="toc-backref" href="#id37">Save and restore plugin's state</a></h2>
+<h2><a class="toc-backref" href="#id38">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>
@@ -608,7 +656,7 @@ 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="#id38">Extension system</a></h2>
+<h2><a class="toc-backref" href="#id39">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>
@@ -618,12 +666,12 @@ big endian machine, it should load again successfully.</p>
</div>
</div>
<div class="section" id="examples">
-<h1><a class="toc-backref" href="#id39">Examples</a></h1>
+<h1><a class="toc-backref" href="#id40">Examples</a></h1>
</div>
<div class="section" id="references">
-<h1><a class="toc-backref" href="#id40">References</a></h1>
+<h1><a class="toc-backref" href="#id41">References</a></h1>
<div class="section" id="clap-c">
-<h2><a class="toc-backref" href="#id41">clap.c</a></h2>
+<h2><a class="toc-backref" href="#id42">clap.c</a></h2>
<pre class="code c literal-block">
<span class="cm">/**
* CLAP - CLever Audio Plugin (<--- needs to find a marketing ok name)
@@ -686,10 +734,6 @@ big endian machine, it should load again successfully.</p>
<span class="k">struct</span> <span class="n">clap_channel</span>
<span class="p">{</span>
- <span class="cm">/* linked list */</span>
- <span class="k">struct</span> <span class="n">clap_channel</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span>
-
- <span class="cm">/* channel info */</span>
<span class="k">enum</span> <span class="n">clap_channel_type</span> <span class="n">type</span><span class="p">;</span>
<span class="k">enum</span> <span class="n">clap_channel_role</span> <span class="n">role</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span>
@@ -699,10 +743,9 @@ big endian machine, it should load again successfully.</p>
<span class="k">struct</span> <span class="n">clap_channels_config</span>
<span class="p">{</span>
- <span class="cm">/* linked list */</span>
- <span class="k">struct</span> <span class="n">clap_channel_configs</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span>
+ <span class="kt">uint32_t</span> <span class="n">input_count</span><span class="p">;</span>
+ <span class="kt">uint32_t</span> <span class="n">output_count</span><span class="p">;</span>
- <span class="cm">/* config */</span>
<span class="k">struct</span> <span class="n">clap_channel</span> <span class="o">*</span><span class="n">inputs</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">clap_channel</span> <span class="o">*</span><span class="n">output</span><span class="p">;</span>
<span class="p">};</span>
@@ -830,14 +873,16 @@ big endian machine, it should load again successfully.</p>
</span>
<span class="k">struct</span> <span class="n">clap_process</span>
<span class="p">{</span>
+ <span class="cm">/* host custom ptr */</span>
+ <span class="kt">void</span> <span class="o">*</span><span class="n">host_data</span><span class="p">;</span>
+
<span class="cm">/* audio buffers */</span>
<span class="kt">float</span> <span class="o">**</span><span class="n">input</span><span class="p">;</span>
<span class="kt">float</span> <span class="o">**</span><span class="n">output</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">nb_samples</span><span class="p">;</span>
<span class="cm">/* feedback loops */</span>
- <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">feedback</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">feedback_ctx</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">nb_samples</span><span class="p">);</span>
- <span class="kt">void</span> <span class="o">*</span><span class="n">feedback_ctx</span><span class="p">;</span>
+ <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">feedback</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="kt">uint32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">nb_samples</span><span class="p">);</span>
<span class="cm">/* process info */</span>
<span class="kt">bool</span> <span class="n">is_offline</span><span class="p">;</span>
@@ -906,8 +951,13 @@ big endian machine, it should load again successfully.</p>
</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">caterogries</span><span class="p">;</span> <span class="c1">// fm, analogue, delay, reverb, ...
</span> <span class="kt">uint32_t</span> <span class="n">plugin_type</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_microtones</span><span class="p">;</span>
+
<span class="cm">/* audio channels */</span>
- <span class="k">struct</span> <span class="n">clap_channels_config</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">get_channels_configs</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="kt">uint32_t</span> <span class="n">channels_configs_count</span><span class="p">;</span>
+ <span class="k">struct</span> <span class="n">clap_channels_config</span> <span class="o">*</span><span class="n">channels_configs</span><span class="p">;</span>
<span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">set_channels_config</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_channels_config</span> <span class="o">*</span><span class="n">config</span><span class="p">);</span>
@@ -957,7 +1007,7 @@ big endian machine, it should load again successfully.</p>
</pre>
</div>
<div class="section" id="samples-clap-info-c">
-<h2><a class="toc-backref" href="#id42">samples/clap-info.c</a></h2>
+<h2><a class="toc-backref" href="#id43">samples/clap-info.c</a></h2>
<pre class="code c literal-block">
<span class="cp">#include <stdio.h>
#include <dlfcn.h>
diff --git a/spec.rst b/spec.rst
@@ -81,7 +81,7 @@ Precautions
Shell plugins
~~~~~~~~~~~~~
-A single dynamic library can contains multiple plugins.
+A single dynamic library can contains multiple clap plugins.
To list them, you have to call ``clap_create`` with an index of 0 and increment
the index until you reach ``plugin_count``.
``clap_create`` returns ``NULL`` if the plugin creation failed or if
@@ -97,43 +97,49 @@ Description
Both the plugin and host have a few attribute giving general plugin description.
-+--------------+---------------------------------------------------------------+
-| Attribute | Description |
-+==============+===============================================================+
-| clap_version | Described the plugin format version implemented. Should be |
-| | initialized with CLAP_PLUGIN_VERSION, |
-| | or CLAP_VERSION_MAKE(1, 0, 0) if you want to only support |
-| | version 1.0.0 |
-+--------------+---------------------------------------------------------------+
-| id | Unique identifier of the plugin. It should never change. It |
-| | should be the same on 32bits or 64bits or whatever. |
-+--------------+---------------------------------------------------------------+
-| name | The name of the product. |
-+--------------+---------------------------------------------------------------+
-| description | A brief description of the product. |
-+--------------+---------------------------------------------------------------+
-| manufacturer | Which company made the plugin. |
-+--------------+---------------------------------------------------------------+
-| version | A string describing the product version. |
-+--------------+---------------------------------------------------------------+
-| url | An URL to the product homepage. |
-+--------------+---------------------------------------------------------------+
-| license | The plugin license type, Custom, GPLv3, MIT, ... |
-+--------------+---------------------------------------------------------------+
-| support | A link to the support, it can be |
-| | ``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, ... |
-+--------------+---------------------------------------------------------------+
-| plugin_type | Bitfield describing what the plugin does. See enum |
-| | clap_plugin_type. |
-+--------------+---------------------------------------------------------------+
-| host_data | Reserved pointer for the host. |
-+--------------+---------------------------------------------------------------+
-| plugin_data | Reserved pointer for the plugin. |
-+--------------+---------------------------------------------------------------+
++---------------------+---------------------------------------------------------------+
+| Attribute | Description |
++=====================+===============================================================+
+| clap_version | Described the plugin format version implemented. Should be |
+| | initialized with CLAP_PLUGIN_VERSION, |
+| | or CLAP_VERSION_MAKE(1, 0, 0) if you want to only support |
+| | version 1.0.0 |
++---------------------+---------------------------------------------------------------+
+| id | Unique identifier of the plugin. It should never change. It |
+| | should be the same on 32bits or 64bits or whatever. |
++---------------------+---------------------------------------------------------------+
+| name | The name of the product. |
++---------------------+---------------------------------------------------------------+
+| description | A brief description of the product. |
++---------------------+---------------------------------------------------------------+
+| manufacturer | Which company made the plugin. |
++---------------------+---------------------------------------------------------------+
+| version | A string describing the product version. |
++---------------------+---------------------------------------------------------------+
+| url | An URL to the product homepage. |
++---------------------+---------------------------------------------------------------+
+| license | The plugin license type, Custom, GPLv3, MIT, ... |
++---------------------+---------------------------------------------------------------+
+| support | A link to the support, it can be |
+| | ``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, ... |
++---------------------+---------------------------------------------------------------+
+| plugin_type | Bitfield describing what the plugin does. See |
+| | ``enum clap_plugin_type``. |
++---------------------+---------------------------------------------------------------+
+| has_gui | True if the plugin can show a graphical user interface |
++---------------------+---------------------------------------------------------------+
+| supports_tunning | True if the plugin supports tunning |
++---------------------+---------------------------------------------------------------+
+| supports_microtones | True if the plugin supports micro tones |
++---------------------+---------------------------------------------------------------+
+| host_data | Reserved pointer for the host. |
++---------------------+---------------------------------------------------------------+
+| plugin_data | Reserved pointer for the plugin. |
++---------------------+---------------------------------------------------------------+
Audio channel configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -197,7 +203,7 @@ So for the following configuration:
Available configurations
````````````````````````
-It is possible to discover a plugin's by calling
+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.
@@ -207,8 +213,9 @@ 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 duplicate the config before passing it to the plugin, and the
-plugin is responsible to free the given 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.
@@ -227,6 +234,44 @@ 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);``.
+Feedback stream
+```````````````
+
+Feedback stream are used to plug external audio processing into one
+of the plugin feedback loop.
+
+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:
+
+.. code:: c
+
+ void my_plugin_process(struct clap_plugin *plugin, struct clap_process *process)
+ {
+ 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
+
+ // one sample process loop
+ for (uint32_t i = 0; i < process->nb_samples; ++i) {
+ // audio processing
+
+ // prepare feedback output buffer
+ process->output[fb_out][i] = XXX;
+ process->output[fb_out + 1][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]
+ }
+ }
+
Threading
---------
@@ -299,7 +344,13 @@ Notes
Notes are reprensented as a pair ``note, division``.
Division is the number of intervals between one note and an other note with
-half or the double frequency.
+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.
+
+The host should not send micro tones to the plugin if
+``plugin->supports_microtones == false``.
Parameters
``````````