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:
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">-></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">"C"</span> <span class="p">{</span>
<span class="cp"># endif
</span>
-<span class="cp"># include <stdbool.h>
+<span class="cp"># include <stddef.h>
+# include <stdbool.h>
# include <stdint.h>
</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>