clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

commit 88511bd968a25a078d5b574c30fa3187619c591b
parent 3e6d4821578f22b12fef30d6e31d67784b1e71b7
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Thu, 23 Oct 2014 01:49:52 +0200

Small changes to the synth example

Diffstat:
Mexamples/thyns/CMakeLists.txt | 6++++++
Mexamples/thyns/plugin.c | 1+
Mexamples/thyns/thyns.h | 85+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Aexamples/thyns/voice.h | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mspec.html | 16++++++++++++----
5 files changed, 131 insertions(+), 45 deletions(-)

diff --git a/examples/thyns/CMakeLists.txt b/examples/thyns/CMakeLists.txt @@ -1,3 +1,9 @@ add_library(thyns SHARED + defs.h + env.h + filt.h + osc.h + thyns.h + plugin.c) target_link_libraries(thyns m) diff --git a/examples/thyns/plugin.c b/examples/thyns/plugin.c @@ -9,6 +9,7 @@ struct thyns_plugin struct thyns thyns; struct clap_plugin plugin; struct clap_host *host; + float pitch; }; void diff --git a/examples/thyns/thyns.h b/examples/thyns/thyns.h @@ -1,63 +1,66 @@ #ifndef THYNS_H # define THYNS_H -# include "env.h" -# include "filt.h" -# include "osc.h" +# include <clap/clap.h> + +# include "voice.h" + +# define THYNS_VOICE_COUNT 32 struct thyns { uint32_t sr; // sample rate double pi_sr; // M_PI / sample_rate - // osc part - struct thyns_osc osc1; - struct thyns_osc osc2; - double osc_mix; - - // filter - struct thyns_filt filt; - struct thyns_env filt_env; - double filt_env_depth; + struct thyns_voice *running; + struct thyns_voice *idle; - // amp - struct thyns_env amp_env; - double amp; + struct thyns_voice buffer[THYNS_VOICE_COUNT]; }; static void thyns_init(struct thyns *thyns, uint32_t sr) { - thyns->sr = sr; - thyns->pi_sr = M_PI / sr; - - // osc - thyns_osc_init(&thyns->osc1); - thyns_osc_init(&thyns->osc2); - thyns->osc_mix = 0; - - // filter - thyns_filt_init(&thyns->filt); - thyns_filt_set_cutoff(&thyns->filt, 1000, thyns->pi_sr); - thyns_env_init(&thyns->filt_env); - thyns->filt_env_depth = 0; - - // amp - thyns_env_init(&thyns->amp_env); - thyns->amp = 0.7; + thyns->sr = sr; + thyns->pi_sr = M_PI / sr; + thyns->running = NULL; + thyns->idle = thyns->buffer; + + for (uint32_t i = 0; i < THYNS_VOICE_COUNT; ++i) { + thyns_voice_init(thyns->buffer + i, sr); + thyns->buffer[i].next = thyns->buffer + i + 1; + } + thyns->buffer[THYNS_VOICE_COUNT - 1].next = NULL; } -double thyns_step(struct thyns *thyns) +double thyns_step(struct thyns *thyns, + struct clap_process *process) { - double osc1 = thyns_osc_step(&thyns->osc1); - double osc2 = thyns_osc_step(&thyns->osc2); - double oscm = osc1 * (1 - thyns->osc_mix) + osc2 * thyns->osc_mix; + double out = 0; + struct thyns_voice *prev = NULL; + struct thyns_voice *v = thyns->running; + + while (v) { + out += thyns_voice_step(v); - double fenv = thyns_env_step(&thyns->filt_env); - double cutoff = exp(log(thyns->filt.cutoff) + fenv); - thyns_filt_set_cutoff(&thyns->filt, cutoff, thyns->pi_sr); - double filtered = thyns_filt_step(&thyns->filt, oscm); + // can we release the voice? + if (v->amp_env.state == THYNS_ENV_IDLE) { + if (prev) { + prev->next = v->next; + v->next = thyns->idle; + thyns->idle = v; + v = prev->next; + } else { + v->next = thyns->idle; + thyns->idle = v; + v = thyns->running; + } + } else { + prev = v; + v = v->next; + } + } - return filtered * thyns->amp * thyns_env_step(&thyns->amp_env); + return out; } #endif /* !THYNS_H */ diff --git a/examples/thyns/voice.h b/examples/thyns/voice.h @@ -0,0 +1,68 @@ +#ifndef VOICE_H +# define VOICE_H + +# include "env.h" +# include "filt.h" +# include "osc.h" + +struct thyns_voice +{ + struct thyns_voice *next; + + uint32_t sr; // sample rate + double pi_sr; // M_PI / sample_rate + + uint32_t note; + uint32_t division; + + // osc part + struct thyns_osc osc1; + struct thyns_osc osc2; + double osc_mix; + + // filter + struct thyns_filt filt; + struct thyns_env filt_env; + double filt_env_depth; + + // amp + struct thyns_env amp_env; + double amp; +}; + +static void thyns_voice_init(struct thyns_voice *voice, uint32_t sr) +{ + voice->sr = sr; + voice->pi_sr = M_PI / sr; + + // osc + thyns_osc_init(&voice->osc1); + thyns_osc_init(&voice->osc2); + voice->osc_mix = 0; + + // filter + thyns_filt_init(&voice->filt); + thyns_filt_set_cutoff(&voice->filt, 1000, voice->pi_sr); + thyns_env_init(&voice->filt_env); + voice->filt_env_depth = 0; + + // amp + thyns_env_init(&voice->amp_env); + voice->amp = 0.7; +} + +double thyns_voice_step(struct thyns_voice *voice) +{ + double osc1 = thyns_osc_step(&voice->osc1); + double osc2 = thyns_osc_step(&voice->osc2); + double oscm = osc1 * (1 - voice->osc_mix) + osc2 * voice->osc_mix; + + double fenv = thyns_env_step(&voice->filt_env); + double cutoff = exp(log(voice->filt.cutoff) + fenv); + thyns_filt_set_cutoff(&voice->filt, cutoff, voice->pi_sr); + double filtered = thyns_filt_step(&voice->filt, oscm); + + return filtered * voice->amp * thyns_env_step(&voice->amp_env); +} + +#endif /* !VOICE_H */ diff --git a/spec.html b/spec.html @@ -1057,6 +1057,8 @@ big endian machine, it should load again successfully.</p> </span> <span class="n">plugin</span><span class="o">-&gt;</span><span class="n">destroy</span><span class="p">(</span><span class="n">plugin</span><span class="p">);</span> <span class="p">}</span> + <span class="n">dlclose</span><span class="p">(</span><span class="n">handle</span><span class="p">);</span> + <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre> @@ -1099,7 +1101,8 @@ big endian machine, it should load again successfully.</p> </span><span class="k">extern</span> <span class="s">&quot;C&quot;</span> <span class="p">{</span> <span class="cp"># endif </span> -<span class="cp"># include &lt;stdbool.h&gt; +<span class="cp"># include &lt;stddef.h&gt; +# include &lt;stdbool.h&gt; # include &lt;stdint.h&gt; </span> <span class="cp"># define CLAP_VERSION_MAKE(Major, Minor, Revision) \ @@ -1331,7 +1334,12 @@ big endian machine, it should load again successfully.</p> <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="k">union</span> <span class="p">{</span> + <span class="kt">float</span> <span class="o">**</span><span class="n">input_f</span><span class="p">;</span> + <span class="kt">double</span> <span class="o">**</span><span class="n">input_d</span><span class="p">;</span> + <span class="kt">long</span> <span class="kt">double</span> <span class="o">**</span><span class="n">input_ld</span><span class="p">;</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> @@ -1469,8 +1477,8 @@ big endian machine, it should load again successfully.</p> <span class="cm">/* The plugin has to allocate and save its state into *buffer. * The plugin is also responsible to free the buffer on the * next call to save() or when the plugin is destroyed. */</span> - <span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">save</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">void</span> <span class="o">**</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">);</span> - <span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">restore</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">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span> + <span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">save</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">void</span> <span class="o">**</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">size</span><span class="p">);</span> + <span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">restore</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">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">size</span><span class="p">);</span> <span class="cm">/* Sets the locale to use */</span> <span class="kt">bool</span> <span class="p">(</span><span class="o">*</span><span class="n">set_locale</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">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">locale</span><span class="p">);</span>