clap

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

commit bb9370f4c469dcfab169718b77811b0b65bffba3
parent 50e8c69788d8d44d20936ecd2bd90d6f64c8e9b6
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Wed, 12 Oct 2016 08:52:21 +0200

Remove example folder

Diffstat:
Dexamples/CMakeLists.txt | 2--
Dexamples/thyns/CMakeLists.txt | 9---------
Dexamples/thyns/defs.h | 15---------------
Dexamples/thyns/dlist.h | 36------------------------------------
Dexamples/thyns/env.h | 180-------------------------------------------------------------------------------
Dexamples/thyns/filt.h | 117-------------------------------------------------------------------------------
Dexamples/thyns/osc.h | 175-------------------------------------------------------------------------------
Dexamples/thyns/params.h | 43-------------------------------------------
Dexamples/thyns/plugin.c | 227-------------------------------------------------------------------------------
Dexamples/thyns/thyns.h | 256-------------------------------------------------------------------------------
Dexamples/thyns/voice.h | 257-------------------------------------------------------------------------------
11 files changed, 0 insertions(+), 1317 deletions(-)

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt @@ -1,2 +0,0 @@ -# Currently broken -# add_subdirectory(thyns) diff --git a/examples/thyns/CMakeLists.txt b/examples/thyns/CMakeLists.txt @@ -1,9 +0,0 @@ -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/defs.h b/examples/thyns/defs.h @@ -1,15 +0,0 @@ -#ifndef DEFS_H -# define DEFS_H - -# include <string.h> -# include <math.h> -# include <assert.h> - -# include <clap/clap.h> -# include <clap/ext/params.h> - -# ifndef M_PI -# define M_PI 3.14159265358979323846 -# endif - -#endif /* !DEFS_H */ diff --git a/examples/thyns/dlist.h b/examples/thyns/dlist.h @@ -1,36 +0,0 @@ -#ifndef DLIST_H -# define DLIST_H - -# define thyns_dlist_push_back(Head, Item) \ - do { \ - assert((Item)->prev == NULL); \ - assert((Item)->next == NULL); \ - if (!(Head)) { \ - (Head) = (Item); \ - (Item)->next = (Item); \ - (Item)->prev = (Item); \ - } else { \ - (Item)->next = (Head); \ - (Item)->prev = (Head)->prev; \ - (Item)->prev->next = (Item); \ - (Item)->next->prev = (Item); \ - } \ - } while (0) - -# define thyns_dlist_remove(Head, Item) \ - do { \ - assert((Head)); \ - assert((Item)->prev); \ - assert((Item)->next); \ - if ((Item)->next == (Item)) \ - (Head) = NULL; \ - else { \ - (Head) = (Item)->next; \ - (Item)->next->prev = (Item)->prev; \ - (Item)->prev->next = (Item)->next; \ - } \ - (Item)->next = NULL; \ - (Item)->prev = NULL; \ - } while (0) - -#endif /* !DLIST_H */ diff --git a/examples/thyns/env.h b/examples/thyns/env.h @@ -1,180 +0,0 @@ -#ifndef ENV_H -# define ENV_H - -# include "defs.h" - -enum thyns_env_state -{ - THYNS_ENV_ATTACK = 0, - THYNS_ENV_DECAY = 1, - THYNS_ENV_SUSTAIN = 2, - THYNS_ENV_RELEASE = 3, - THYNS_ENV_IDLE = 4, -}; - -enum thyns_env_param_index -{ - THYNS_ENV_PARAM_ATTACK = 0, - THYNS_ENV_PARAM_DECAY, - THYNS_ENV_PARAM_SUSTAIN, - THYNS_ENV_PARAM_RELEASE, - THYNS_ENV_PARAM_COUNT -}; - -struct thyns_env -{ - // state - enum thyns_env_state state; - double msr; // 1000 / sr - double v; - - union clap_param_value *values[THYNS_ENV_PARAM_COUNT]; -}; - -static inline void -thyns_env_param_info(uint32_t index, - union clap_param_value value, - const char *prefix, - struct clap_param *param) -{ -#define P(Dst, Args...) snprintf(Dst, sizeof (Dst), Args); - - switch (index) { - case THYNS_ENV_PARAM_ATTACK: - P(param->id, "%s%s", prefix, "attack"); - P(param->name, "%s", "attack"); - P(param->desc, "%s", "Envelope's attack in ms"); - P(param->display, "%f ms", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 10000; - param->scale = CLAP_PARAM_SCALE_LOG; - break; - - case THYNS_ENV_PARAM_DECAY: - P(param->id, "%s%s", prefix, "decay"); - P(param->name, "%s", "decay"); - P(param->desc, "%s", "Envelope's decay in ms"); - P(param->display, "%f ms", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 10000; - param->scale = CLAP_PARAM_SCALE_LOG; - break; - - case THYNS_ENV_PARAM_SUSTAIN: - P(param->id, "%s%s", prefix, "sustain"); - P(param->name, "%s", "sustain"); - P(param->desc, "%s", "Envelope's sustain"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 1; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_ENV_PARAM_RELEASE: - P(param->id, "%s%s", prefix, "release"); - P(param->name, "%s", "release"); - P(param->desc, "%s", "Envelope's release in ms"); - P(param->display, "%f ms", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 10000; - param->scale = CLAP_PARAM_SCALE_LOG; - break; - } -#undef P -} - -static inline void -thyns_env_params_init(union clap_param_value *values) -{ - values[THYNS_ENV_PARAM_ATTACK].f = 100; - values[THYNS_ENV_PARAM_DECAY].f = 200; - values[THYNS_ENV_PARAM_SUSTAIN].f = 0.7; - values[THYNS_ENV_PARAM_RELEASE].f = 200; -} - -static inline void -thyns_env_init(struct thyns_env * restrict env, double sr) -{ - env->state = THYNS_ENV_IDLE; - env->msr = 1000.0 / sr; - env->v = 0; -} - -static inline void -thyns_env_restart(struct thyns_env * restrict env) -{ - env->state = THYNS_ENV_ATTACK; -} - -static inline void -thyns_env_release(struct thyns_env * restrict env) -{ - env->state = THYNS_ENV_RELEASE; -} - -static inline double -thyns_env_step(struct thyns_env * restrict env) -{ - switch (env->state) { - case THYNS_ENV_ATTACK: - env->v += env->values[THYNS_ENV_PARAM_ATTACK]->f * env->msr; - if (env->v >= 1) { - env->v = 1; - env->state = THYNS_ENV_DECAY; - } - break; - - case THYNS_ENV_DECAY: { - float s = env->values[THYNS_ENV_PARAM_SUSTAIN]->f; - env->v -= env->values[THYNS_ENV_PARAM_DECAY]->f * env->msr; - if (env->v <= s) { - env->v = s; - env->state = THYNS_ENV_SUSTAIN; - } - break; - } - - case THYNS_ENV_SUSTAIN: - env->v = env->values[THYNS_ENV_PARAM_SUSTAIN]->f; - break; - - case THYNS_ENV_RELEASE: - env->v -= env->values[THYNS_ENV_PARAM_RELEASE]->f * env->msr; - if (env->v <= 0) { - env->v = 0; - env->state = THYNS_ENV_IDLE; - } - break; - - case THYNS_ENV_IDLE: - break; - - default: - assert(false); - break; - } - - return env->v; -} - -#endif /* !ENV_H */ diff --git a/examples/thyns/filt.h b/examples/thyns/filt.h @@ -1,117 +0,0 @@ -/** - * Basic filter adapted from Urs Heckman's code: - * http://www.kvraudio.com/forum/viewtopic.php?f=33&t=412944#p5766724 - */ - -#ifndef FILT_H -# define FILT_H - -# include "defs.h" - -enum thyns_filt_param_index -{ - THYNS_FILT_PARAM_CUTOFF = 0, - THYNS_FILT_PARAM_RESONANCE, - THYNS_FILT_PARAM_COUNT -}; - -struct thyns_filt -{ - uint32_t sr; // sample rate - double pi_sr; // M_PI / sample_rate - - double g; - double g_div; - - double iceq1; // states in form - double iceq2; // of current - double iceq3; // equivalents - double iceq4; // of capacitors - - double y4; // delayed feedback - - /* parameters */ - union clap_param_value *values[THYNS_FILT_PARAM_COUNT]; -}; - -static inline void -thyns_filt_param_info(uint32_t index, - union clap_param_value value, - const char *prefix, - struct clap_param *param) -{ -#define P(Dst, Args...) snprintf(Dst, sizeof (Dst), Args); - - switch (index) { - case THYNS_FILT_PARAM_CUTOFF: - P(param->id, "%s%s", prefix, "cutoff"); - P(param->name, "%s", "cutoff"); - P(param->desc, "%s", "Filter's cutoff"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 28000; - param->scale = CLAP_PARAM_SCALE_LOG; - break; - - case THYNS_FILT_PARAM_RESONANCE: - P(param->id, "%s%s", prefix, "resonance"); - P(param->name, "%s", "resonance"); - P(param->desc, "%s", "Filter's resonance"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 2; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - } -#undef P -} - -static inline void -thyns_filt_params_init(union clap_param_value *values) -{ - values[THYNS_FILT_PARAM_CUTOFF].f = 4000; - values[THYNS_FILT_PARAM_RESONANCE].f = 1.5; -} - -static inline void -thyns_filt_init(struct thyns_filt *filt, uint32_t sr) -{ - memset(filt, 0, sizeof (*filt)); - filt->sr = sr; - filt->pi_sr = M_PI / sr; -} - -static inline double -thyns_filt_step(struct thyns_filt *filt, - double in, - double cutoff, - double resonance) -{ - filt->g = tan(filt->pi_sr * cutoff); - filt->g_div = 1.0 / (1.0 + filt->g); - - double x0 = in - resonance * filt->y4; - double y1 = (filt->g * tanh(x0) + filt->iceq1) * filt->g_div; - double y2 = (filt->g * tanh(y1) + filt->iceq2) * filt->g_div; - double y3 = (filt->g * tanh(y2) + filt->iceq3) * filt->g_div; - filt->y4 = (filt->g * tanh(y3) + filt->iceq4) * filt->g_div; - - filt->iceq1 = 2 * y1 - filt->iceq1; - filt->iceq2 = 2 * y2 - filt->iceq2; - filt->iceq3 = 2 * y3 - filt->iceq3; - filt->iceq4 = 2 * filt->y4 - filt->iceq4; - - return filt->y4; -} - -#endif /* !FILT_H */ diff --git a/examples/thyns/osc.h b/examples/thyns/osc.h @@ -1,175 +0,0 @@ -#ifndef OSC_H -# define OSC_H - -# include "defs.h" - -enum thyns_osc_waveform -{ - THYNS_OSC_NONE = 0, - THYNS_OSC_SQUARE = 1, - THYNS_OSC_SAW = 2, - THYNS_OSC_TRI = 3, - THYNS_OSC_SINE = 4, -}; - -static const char * const thyns_osc_waveform_name[] = { - "none", - "square", - "saw", - "tri", - "sine", -}; - -enum thyns_osc_param_index -{ - THYNS_OSC_PARAM_WAVEFORM = 0, - THYNS_OSC_PARAM_PHASE, - THYNS_OSC_PARAM_PWM, - THYNS_OSC_PARAM_TUNE, - THYNS_OSC_PARAM_COUNT -}; - -struct thyns_osc -{ - /* processing constants */ - uint32_t sr; // sample rate - double pi_sr; // M_PI / sample_rate - - /* oscillator state */ - double freq; - double angle_ramp; - double angle; - - /* parameters */ - union clap_param_value *values[THYNS_OSC_PARAM_COUNT]; -}; - -static inline void -thyns_osc_param_info(uint32_t index, - union clap_param_value value, - const char *prefix, - struct clap_param *param) -{ -#define P(Dst, Args...) snprintf(Dst, sizeof (Dst), Args); - - switch (index) { - case THYNS_OSC_PARAM_WAVEFORM: - P(param->id, "%s%s", prefix, "waveform"); - P(param->name, "%s", "waveform"); - P(param->desc, "%s", "Oscillator's waveform"); - P(param->display, "%s", thyns_osc_waveform_name[value.i]); - param->type = CLAP_PARAM_ENUM; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.i = 0; - param->max.i = THYNS_OSC_SINE; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_OSC_PARAM_PHASE: - P(param->id, "%s%s", prefix, "phase"); - P(param->name, "%s", "phase"); - P(param->desc, "%s", "Oscillator's phase"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = true; - param->value = value; - param->min.f = 0; - param->max.f = 2 * M_PI; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_OSC_PARAM_PWM: - P(param->id, "%s%s", prefix, "pwm"); - P(param->name, "%s", "pwm"); - P(param->desc, "%s", "Oscillator's pulse width modulation"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 1; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_OSC_PARAM_TUNE: - P(param->id, "%s%s", prefix, "tune"); - P(param->name, "%s", "tune"); - P(param->desc, "%s", "Oscillator's tunning in semitones"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = -48; - param->max.f = +48; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - } - -#undef P -} - -static inline void -thyns_osc_params_init(union clap_param_value *values) -{ - values[THYNS_OSC_PARAM_WAVEFORM].i = THYNS_OSC_SQUARE; - values[THYNS_OSC_PARAM_PWM].f = 0.5; - values[THYNS_OSC_PARAM_PHASE].f = 0; - values[THYNS_OSC_PARAM_TUNE].f = 0; -} - -static inline void -thyns_osc_init(struct thyns_osc *osc, uint32_t sr) -{ - osc->sr = sr; - osc->pi_sr = M_PI / ((float)sr); - osc->freq = 0; - osc->angle = 0; -} - -static inline void -thyns_osc_set_freq(struct thyns_osc *osc, double freq) -{ - osc->freq = freq; - osc->angle_ramp = 2 * osc->pi_sr * freq * pow(2, osc->values[THYNS_OSC_PARAM_TUNE]->f / 12.f); -} - -static inline double -thyns_osc_step(struct thyns_osc *osc) -{ - osc->angle = fmod(osc->angle + osc->angle_ramp, 2 * M_PI); - double angle = fmod(osc->angle + osc->values[THYNS_OSC_PARAM_PHASE]->f, 2 * M_PI); - - switch (osc->values[THYNS_OSC_PARAM_WAVEFORM]->i) { - case THYNS_OSC_NONE: - return 0; - - case THYNS_OSC_SQUARE: - return angle < M_PI; - - case THYNS_OSC_SAW: - return (2 * M_PI - angle) / (M_PI) - 1; - - case THYNS_OSC_TRI: - if (angle < M_PI) - return angle * 2.0 / M_PI - 1; - return (2 * M_PI - angle) * 2.0 / M_PI - 1; - - case THYNS_OSC_SINE: - return sin(angle); - - default: - assert(false); - return 0; - } -} - -#endif /* !OSC_H */ diff --git a/examples/thyns/params.h b/examples/thyns/params.h @@ -1,43 +0,0 @@ -#ifndef PARAMS_H -# define PARAMS_H - -struct thyns_params -{ - union clap_param_value values[0]; - union clap_param_value osc1[THYNS_OSC_PARAM_COUNT]; - union clap_param_value osc2[THYNS_OSC_PARAM_COUNT]; - union clap_param_value filt[THYNS_FILT_PARAM_COUNT]; - union clap_param_value amp_env[THYNS_ENV_PARAM_COUNT]; - union clap_param_value filt_env[THYNS_ENV_PARAM_COUNT]; - union clap_param_value voice[THYNS_VOICE_PARAM_COUNT]; -}; - -# define THYNS_PARAMS_VALUES_COUNT \ - (sizeof (struct thyns_params) / sizeof (union clap_param_value)) - -struct thyns_ramp -{ - struct thyns_ramp *prev; - struct thyns_ramp *next; - - float increment; - union clap_param_value *target; -}; - -struct thyns_ramps -{ - struct thyns_ramp *ramps[THYNS_PARAMS_VALUES_COUNT]; -}; - -static void -thyns_params_init(struct thyns_params *params) -{ - thyns_osc_params_init(params->osc1); - thyns_osc_params_init(params->osc2); - thyns_filt_params_init(params->filt); - thyns_env_params_init(params->amp_env); - thyns_env_params_init(params->filt_env); - thyns_voice_params_init(params->voice); -} - -#endif /* !PARAMS_H */ diff --git a/examples/thyns/plugin.c b/examples/thyns/plugin.c @@ -1,227 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <clap/clap.h> -#include <clap/ext/params.h> -#include <clap/ext/state.h> - -#include "thyns.h" - -struct thyns_plugin -{ - struct thyns thyns; - struct clap_plugin plugin; - struct clap_host *host; - struct clap_plugin_params params; - struct clap_plugin_state state; - - // buffer to save the synthesizer state - uint8_t state_buffer[2048]; -}; - -void -thyns_plugin_destroy(struct clap_plugin *plugin) -{ - if (!plugin) - return; - - struct thyns_plugin *p = plugin->plugin_data; - free(p); -} - -int32_t -thyns_plugin_get_attribute(struct clap_plugin *plugin, - const char *attr, - char *buffer, - int32_t size) -{ -#define attr(Attr, Value) \ - do { \ - if (!strcmp(CLAP_ATTR_##Attr, attr)) { \ - snprintf(buffer, size, "%s", Value); \ - return sizeof (Value) - 1; \ - } \ - } while (0) - - attr(ID, "clap/thyns"); - attr(NAME, "Thyns"); - attr(DESCRIPTION, "Clap demo synth"); - attr(VERSION, "0.0.1"); - attr(MANUFACTURER, "Clap"); - attr(URL, "https://github.com/abique/clap"); - attr(SUPPORT, "https://github.com/abique/clap"); - attr(LICENSE, "MIT"); - attr(CATEGORIES, ""); - attr(TYPE, "instrument"); - attr(CHUNK_SIZE, "1"); - attr(SUPPORTS_TUNING, "1"); - attr(LATENCY, "0"); - - return 0; - -#undef attr -} - -enum clap_process_status -thyns_plugin_process(struct clap_plugin *plugin, - struct clap_process *process) -{ - return thyns_process(plugin->plugin_data, process); -} - -void * -thyns_plugin_extension(struct clap_plugin *plugin, const char *extension) -{ - struct thyns_plugin *p = plugin->plugin_data; - - if (!strcmp(extension, CLAP_EXT_PARAMS)) - return &p->params; - if (!strcmp(extension, CLAP_EXT_STATE)) - return &p->state; - return NULL; -} - -bool -thyns_plugin_activate(struct clap_plugin *plugin) -{ - return true; -} - -void -thyns_plugin_deactivate(struct clap_plugin *plugin) -{ -} - -int32_t -thyns_params_count(struct clap_plugin *plugin) -{ - return sizeof (struct thyns_params) / sizeof (union clap_param_value); -} - -bool -thyns_params_get(struct clap_plugin *plugin, - int32_t index, - struct clap_param *param) -{ - if (index >= thyns_params_count(plugin)) - return false; - - struct thyns_plugin *p = plugin->plugin_data; - int32_t i = 0; - - param->index = index; - - if (index < i + THYNS_OSC_PARAM_COUNT) { - thyns_osc_param_info(index - i, p->thyns.params.osc1[index - i], - "osc1:", param); - return true; - } - i += THYNS_OSC_PARAM_COUNT; - - if (index < i + THYNS_OSC_PARAM_COUNT) { - thyns_osc_param_info(index - i, p->thyns.params.osc2[index - i], - "osc2:", param); - return true; - } - i += THYNS_OSC_PARAM_COUNT; - - if (index < i + THYNS_FILT_PARAM_COUNT) { - thyns_filt_param_info(index - i, p->thyns.params.filt[index - i], - "filt:", param); - return true; - } - i += THYNS_FILT_PARAM_COUNT; - - if (index < i + THYNS_ENV_PARAM_COUNT) { - thyns_env_param_info(index - i, p->thyns.params.amp_env[index - i], - "amp-env:", param); - return true; - } - i += THYNS_ENV_PARAM_COUNT; - - if (index < i + THYNS_ENV_PARAM_COUNT) { - thyns_env_param_info(index - i, p->thyns.params.filt_env[index - i], - "filt-env:", param); - return true; - } - i += THYNS_ENV_PARAM_COUNT; - - if (index < i + THYNS_VOICE_PARAM_COUNT) { - thyns_voice_param_info(index - i, p->thyns.params.voice[index - i], - "", param); - return true; - } - i += THYNS_ENV_PARAM_COUNT; - - return false; -} - -bool -thyns_state_save(struct clap_plugin *plugin, void **buffer, int32_t *size) -{ - struct thyns_plugin *p = plugin->plugin_data; - - *buffer = p->state_buffer; - *size = sizeof (p->state_buffer); - return clap_plugin_params_save(plugin, *buffer, size); -} - -bool -thyns_state_restore(struct clap_plugin *plugin, - const void *buffer, - int32_t size) -{ - struct thyns_plugin *p = plugin->plugin_data; - - clap_plugin_params_restore(plugin, buffer, size, *p->host->steady_time); - return true; -} - -struct thyns_plugin * -thyns_plugin_create(struct clap_host *host, - int32_t sample_rate) -{ - struct thyns_plugin *p = calloc(sizeof (*p), 1); - if (!p) - return NULL; - - // initialize the dsp - thyns_init(&p->thyns, sample_rate); - - // save host pointer - p->host = host; - - // initialize plugin - p->plugin.clap_version = CLAP_VERSION; - p->plugin.destroy = thyns_plugin_destroy; - p->plugin.plugin_data = p; - p->plugin.get_attribute = thyns_plugin_get_attribute; - p->plugin.process = thyns_plugin_process; - p->plugin.extension = thyns_plugin_extension; - p->plugin.activate = thyns_plugin_activate; - p->plugin.deactivate = thyns_plugin_deactivate; - p->params.count = thyns_params_count; - p->params.get_param = thyns_params_get; - p->state.save = thyns_state_save; - p->state.restore = thyns_state_restore; - - return p; -} - -struct clap_plugin * -clap_create(int32_t plugin_index, - struct clap_host *host, - int32_t sample_rate, - int32_t *plugins_count) -{ - if (plugins_count) - *plugins_count = 1; - - switch (plugin_index) { - case 0: { - struct thyns_plugin *p = thyns_plugin_create(host, sample_rate); - return p ? &p->plugin : NULL; - } - - default: return NULL; - } -} diff --git a/examples/thyns/thyns.h b/examples/thyns/thyns.h @@ -1,256 +0,0 @@ -#ifndef THYNS_H -# define THYNS_H - -# include "voice.h" -# include "dlist.h" -# include "params.h" - -# define THYNS_VOICES_COUNT 8 -# define THYNS_RAMPS_COUNT 32 - -struct thyns -{ - int32_t sr; // sample rate - double pi_sr; // M_PI / sample_rate - - int64_t steady_time; - - struct thyns_voice *voices_singing; // list - struct thyns_voice *voices_idle; // list - struct thyns_voice *voices_keys[0x80]; - - struct thyns_ramp *ramping; // list - struct thyns_ramp *ramps_idle; // list - - struct thyns_params params; - struct thyns_ramps ramps; - - /* allocators buffer */ - struct thyns_voice voices_buffer[THYNS_VOICES_COUNT]; - struct thyns_ramp ramps_buffer[THYNS_RAMPS_COUNT]; -}; - -static inline void thyns_init(struct thyns *thyns, int32_t sr) -{ - memset(thyns, 0, sizeof (*thyns)); - - thyns->sr = sr; - thyns->pi_sr = M_PI / sr; - - thyns_params_init(&thyns->params); - - for (int32_t i = 0; i < THYNS_VOICES_COUNT; ++i) { - thyns_voice_init(thyns->voices_buffer + i, sr); - thyns_dlist_push_back(thyns->voices_idle, thyns->voices_buffer + i); - } - - for (int32_t i = 0; i < THYNS_RAMPS_COUNT; ++i) - thyns_dlist_push_back(thyns->ramps_idle, thyns->ramps_buffer + i); -} - -static double thyns_step(struct thyns *thyns, - struct clap_process *process) -{ - if (!thyns->voices_singing) - return 0; - - double out = 0; - struct thyns_voice *prev = NULL; - struct thyns_voice *v = thyns->voices_singing; - struct thyns_voice *end = v->prev; - - /* compute voices */ - do { - out += thyns_voice_step(v); - - // can we release the voice? - if (v->amp_env.state == THYNS_ENV_IDLE) { - printf("releasing %d\n", v->key); - assert(v->key != 0); - thyns->voices_keys[v->key] = NULL; - thyns_dlist_remove(thyns->voices_singing, v); - thyns_dlist_push_back(thyns->voices_idle, v); - v = prev ? prev->next : thyns->voices_singing; - } else { - prev = v; - v = v->next; - } - } while (v && prev != end && v != prev); - - return out; -} - -static inline void -thyns_note_on(struct thyns *thyns, - uint8_t key, - float pitch) -{ - struct thyns_voice *voice = NULL; - - printf("note_on(%d, %f)\n", key, pitch); - assert(key < 0x80); - if (thyns->voices_keys[key]) { - voice = thyns->voices_keys[key]; - } else { - if (thyns->voices_idle) { - voice = thyns->voices_idle; - thyns_dlist_remove(thyns->voices_idle, voice); - } else { - voice = thyns->voices_singing; - thyns_dlist_remove(thyns->voices_singing, voice); - thyns->voices_keys[voice->key] = NULL; - } - thyns_dlist_push_back(thyns->voices_singing, voice); - thyns->voices_keys[key] = voice; - voice->key = key; - } - - thyns_voice_values_init(voice, &thyns->params); - thyns_voice_start_note(thyns->voices_keys[key], key, pitch); -} - -static inline void -thyns_note_off(struct thyns *thyns, - uint8_t key) -{ - printf("note_off(%d)\n", key); - assert(key < 0x80); - struct thyns_voice *voice = thyns->voices_keys[key]; - if (voice) { - thyns_voice_stop_note(voice, key); - - // stop ramps - for (struct thyns_ramp *ramp = voice->ramping; ramp; ramp = voice->ramping) { - thyns_dlist_remove(voice->ramping, ramp); - thyns_dlist_push_back(thyns->ramps_idle, ramp); - } - } -} - -static inline void -thyns_handle_event(struct thyns *thyns, - struct clap_event *ev) -{ - switch (ev->type) { - case CLAP_EVENT_NOTE_ON: - thyns_note_on(thyns, ev->note.key, ev->note.pitch); - break; - - case CLAP_EVENT_NOTE_OFF: - thyns_note_off(thyns, ev->note.key); - break; - - case CLAP_EVENT_PARAM_SET: - if (ev->param.is_global) { - thyns->params.values[ev->param.index] = ev->param.value; - - // stop ramps - if (thyns->ramps.ramps[ev->param.index]) { - thyns_dlist_remove(thyns->ramping, thyns->ramps.ramps[ev->param.index]); - thyns->ramps.ramps[ev->param.index] = NULL; - } - } else if (thyns->voices_keys[ev->param.key]) { - struct thyns_voice *voice = thyns->voices_keys[ev->param.key]; - voice->params.values[ev->param.index] = ev->param.value; - thyns_voice_use_value(voice, &voice->params, ev->param.index); - - // stop ramps - if (voice->ramps.ramps[ev->param.index]) { - thyns_dlist_remove(voice->ramping, voice->ramps.ramps[ev->param.index]); - voice->ramps.ramps[ev->param.index] = NULL; - } - } - break; - - case CLAP_EVENT_PARAM_RAMP: { - struct thyns_ramps *ramps = NULL; - struct thyns_params *params = NULL; - struct thyns_voice *voice = NULL; - - if (ev->param.is_global) { - // check if the parameter is ramping - if (thyns->ramps.ramps[ev->param.index]) { - // just update the increment - thyns->ramps.ramps[ev->param.index]->increment = ev->param.increment; - break; - } - - // do we have idle ramps? - if (!thyns->ramps_idle) - break; - - ramps = &thyns->ramps; - params = &thyns->params; - } else { - voice = thyns->voices_keys[ev->param.key]; - - // check if the voice is singing - if (!voice) - break; - - // check if the parameter is ramping - if (voice->ramps.ramps[ev->param.index]) { - // just update the increment - voice->ramps.ramps[ev->param.index]->increment = ev->param.increment; - break; - } - - // do we have idle ramps? - if (!thyns->ramps_idle) - break; - - ramps = &voice->ramps; - params = &voice->params; - } - - struct thyns_ramp *ramp = thyns->ramps_idle; - thyns_dlist_remove(thyns->ramps_idle, ramp); - ramp->increment = ev->param.increment; - ramp->target = params->values + ev->param.index; - ramps->ramps[ev->param.index] = ramp; - - // add the ramp to the ramping list - if (ev->param.is_global) { - thyns_dlist_push_back(thyns->ramping, ramp); - } else { - thyns_dlist_push_back(voice->ramping, ramp); - } - break; - } - - default: - break; - } -} - -static inline enum clap_process_status -thyns_process(struct thyns *thyns, struct clap_process *process) -{ - struct clap_event *ev = process->events; - - thyns->steady_time = process->steady_time; - for (int32_t i = 0; i < process->samples_count; ++i, ++thyns->steady_time) { - - // handle events - for (; ev; ev = ev->next) { - assert(ev->steady_time >= thyns->steady_time); - if (ev->steady_time > thyns->steady_time) - break; - - thyns_handle_event(thyns, ev); - } - - // process - process->outputs[0][i] = thyns_step(thyns, process); - process->outputs[1][i] = process->outputs[0][i]; - } - - // ensure no more events are left - assert(!ev); - - if (thyns->voices_singing) - return CLAP_PROCESS_CONTINUE; - return CLAP_PROCESS_STOP; -} - -#endif /* !THYNS_H */ diff --git a/examples/thyns/voice.h b/examples/thyns/voice.h @@ -1,257 +0,0 @@ -#ifndef VOICE_H -# define VOICE_H - -# include "env.h" -# include "filt.h" -# include "osc.h" - -enum thyns_voice_param_index -{ - THYNS_VOICE_PARAM_OSC_MIX = 0, - THYNS_VOICE_PARAM_FILT_ENV_DEPTH, - THYNS_VOICE_PARAM_AMP, - THYNS_VOICE_PARAM_COUNT, -}; - -static inline void -thyns_voice_params_init(union clap_param_value *values) -{ - values[THYNS_VOICE_PARAM_OSC_MIX].f = 0.5; - values[THYNS_VOICE_PARAM_FILT_ENV_DEPTH].f = 0.2; - values[THYNS_VOICE_PARAM_AMP].f = 0.2; -} - -# include "params.h" - -struct thyns_voice -{ - struct thyns_voice *prev; - struct thyns_voice *next; - - uint32_t sr; // sample rate - double pi_sr; // M_PI / sample_rate - - uint8_t key; - float freq; - - // osc part - struct thyns_osc osc1; - struct thyns_osc osc2; - - // filter - struct thyns_filt filt; - struct thyns_env filt_env; - - // amp - struct thyns_env amp_env; - - union clap_param_value *values[THYNS_VOICE_PARAM_COUNT]; - - // voice parameters - struct thyns_params params; - struct thyns_ramps ramps; - struct thyns_ramp *ramping; // list -}; - -static inline void -thyns_voice_param_info(uint32_t index, - union clap_param_value value, - const char *prefix, - struct clap_param *param) -{ -#define P(Dst, Args...) snprintf(Dst, sizeof (Dst), Args); - - switch (index) { - case THYNS_VOICE_PARAM_OSC_MIX: - P(param->id, "%s%s", prefix, "osc-mix"); - P(param->name, "%s", "osc mix"); - P(param->desc, "%s", "Oscillators mixer"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = 0; - param->max.f = 1; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_VOICE_PARAM_FILT_ENV_DEPTH: - P(param->id, "%s%s", prefix, "filt-env-depth"); - P(param->name, "%s", "filter env depth"); - P(param->desc, "%s", "Filter's envelop"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = -4; - param->max.f = 4; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - - case THYNS_VOICE_PARAM_AMP: - P(param->id, "%s%s", prefix, "amp"); - P(param->name, "%s", "output volume"); - P(param->desc, "%s", "Output volume"); - P(param->display, "%f", value.f); - param->type = CLAP_PARAM_FLOAT; - param->is_per_note = true; - param->is_used = true; - param->is_periodic = false; - param->value = value; - param->min.f = -1; - param->max.f = 1; - param->scale = CLAP_PARAM_SCALE_LINEAR; - break; - } -#undef P -} - -static inline void -thyns_voice_init(struct thyns_voice *voice, uint32_t sr) -{ - voice->prev = NULL; - voice->next = NULL; - - voice->sr = sr; - voice->pi_sr = M_PI / sr; - - // osc - thyns_osc_init(&voice->osc1, sr); - thyns_osc_init(&voice->osc2, sr); - - // filter - thyns_filt_init(&voice->filt, sr); - thyns_env_init(&voice->filt_env, sr); - - // amp - thyns_env_init(&voice->amp_env, sr); - - // parameters ramps - memset(&voice->ramps, 0, sizeof (voice->ramps)); - voice->ramping = NULL; -} - -static inline void -thyns_voice_values_init(struct thyns_voice *voice, - struct thyns_params *params) -{ - uint32_t off = 0; - - // osc1 - for (int i = 0; i < THYNS_OSC_PARAM_COUNT; ++i) - voice->osc1.values[i] = params->values + off + i; - off += THYNS_OSC_PARAM_COUNT; - - // osc2 - for (int i = 0; i < THYNS_OSC_PARAM_COUNT; ++i) - voice->osc2.values[i] = params->values + off + i; - off += THYNS_OSC_PARAM_COUNT; - - // filt - for (int i = 0; i < THYNS_FILT_PARAM_COUNT; ++i) - voice->filt.values[i] = params->values + off + i; - off += THYNS_FILT_PARAM_COUNT; - - // amp_env - for (int i = 0; i < THYNS_ENV_PARAM_COUNT; ++i) - voice->amp_env.values[i] = params->values + off + i; - off += THYNS_ENV_PARAM_COUNT; - - // filt_env - for (int i = 0; i < THYNS_ENV_PARAM_COUNT; ++i) - voice->filt_env.values[i] = params->values + off + i; - off += THYNS_ENV_PARAM_COUNT; - - // voice - for (int i = 0; i < THYNS_VOICE_PARAM_COUNT; ++i) - voice->values[i] = params->values + off + i; - off += THYNS_VOICE_PARAM_COUNT; -} - -static inline void -thyns_voice_use_value(struct thyns_voice *voice, - struct thyns_params *params, - uint32_t index) -{ - uint32_t i = 0; - - if (index < i + THYNS_OSC_PARAM_COUNT) { - voice->osc1.values[index - i] = params->values + index; - return; - } - i += THYNS_OSC_PARAM_COUNT; - - if (index < i + THYNS_OSC_PARAM_COUNT) { - voice->osc2.values[index - i] = params->values + index; - return; - } - i += THYNS_OSC_PARAM_COUNT; - - if (index < i + THYNS_FILT_PARAM_COUNT) { - voice->filt.values[index - i] = params->values + index; - return; - } - i += THYNS_FILT_PARAM_COUNT; - - if (index < i + THYNS_ENV_PARAM_COUNT) { - voice->amp_env.values[index - i] = params->values + index; - return; - } - i += THYNS_ENV_PARAM_COUNT; - - if (index < i + THYNS_ENV_PARAM_COUNT) { - voice->filt_env.values[index - i] = params->values + index; - return; - } - i += THYNS_ENV_PARAM_COUNT; - - if (index < i + THYNS_VOICE_PARAM_COUNT) { - voice->values[index - i] = params->values + index; - return; - } - i += THYNS_ENV_PARAM_COUNT; -} - -static inline void -thyns_voice_start_note(struct thyns_voice *voice, - uint32_t key, - float freq) -{ - thyns_osc_set_freq(&voice->osc1, freq); - thyns_osc_set_freq(&voice->osc2, freq); - - thyns_env_restart(&voice->filt_env); - thyns_env_restart(&voice->amp_env); -} - -static inline void -thyns_voice_stop_note(struct thyns_voice *voice, - uint32_t key) -{ - thyns_env_release(&voice->filt_env); - thyns_env_release(&voice->amp_env); -} - -static inline double -thyns_voice_step(struct thyns_voice *voice) -{ - double osc1 = thyns_osc_step(&voice->osc1); - double osc2 = thyns_osc_step(&voice->osc2); - double oscm = voice->values[THYNS_VOICE_PARAM_OSC_MIX]->f; - double osc = osc1 * (1 - oscm) + osc2 * oscm; - double fenv = thyns_env_step(&voice->filt_env) * - voice->values[THYNS_VOICE_PARAM_FILT_ENV_DEPTH]->f; - double cutoff = exp(log(voice->filt.values[THYNS_FILT_PARAM_CUTOFF]->f) + fenv); - double filtered = thyns_filt_step(&voice->filt, osc, cutoff, - voice->filt.values[THYNS_FILT_PARAM_RESONANCE]->f); - double amp = voice->values[THYNS_VOICE_PARAM_AMP]->f - * thyns_env_step(&voice->amp_env); - - return filtered * amp; -} - -#endif /* !VOICE_H */