clap

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

commit 84b25440a67de620be2d45a5b4a034d1e2f46442
parent 090c1d04e0040e4c3463d65019df66c244e952cc
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Wed,  7 Jan 2015 00:54:43 +0100

thyns: add env parameters

Diffstat:
Mexamples/thyns/env.h | 129++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mexamples/thyns/params.h | 4++++
Mexamples/thyns/voice.h | 24++++++++++++++++++++++--
3 files changed, 137 insertions(+), 20 deletions(-)

diff --git a/examples/thyns/env.h b/examples/thyns/env.h @@ -12,61 +12,154 @@ enum thyns_env_state 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 ar; // attack ramp - double dr; // decay ramp - double s; // sustain level - double rr; // release ramp + double msr; // 1000 / sr double v; + + union clap_param_value *values[THYNS_ENV_PARAM_COUNT]; }; -static inline void thyns_env_init(struct thyns_env * restrict env) +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_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_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_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_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; - env->ar = 0.0001; - env->dr = 0.0001; - env->s = 0.7; - env->rr = 0.00001; } -static inline void thyns_env_restart(struct thyns_env * restrict env) +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) +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) +static inline double +thyns_env_step(struct thyns_env * restrict env) { switch (env->state) { case THYNS_ENV_ATTACK: - env->v += env->ar; + 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: - env->v -= env->dr; - if (env->v <= env->s) { - env->v = env->s; + 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->rr; + env->v -= env->values[THYNS_ENV_PARAM_RELEASE]->f * env->msr; if (env->v <= 0) { env->v = 0; env->state = THYNS_ENV_IDLE; diff --git a/examples/thyns/params.h b/examples/thyns/params.h @@ -7,6 +7,8 @@ struct thyns_params 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]; }; static void @@ -15,6 +17,8 @@ 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); } #endif /* !PARAMS_H */ diff --git a/examples/thyns/voice.h b/examples/thyns/voice.h @@ -53,11 +53,11 @@ thyns_voice_init(struct thyns_voice *voice, uint32_t sr) thyns_filt_init(&voice->filt, sr); voice->filt.cutoff = 4000; voice->filt.resonance = 1.5; - thyns_env_init(&voice->filt_env); + thyns_env_init(&voice->filt_env, sr); voice->filt_env_depth = 0.2; // amp - thyns_env_init(&voice->amp_env); + thyns_env_init(&voice->amp_env, sr); voice->amp = 0.2; } @@ -81,6 +81,16 @@ thyns_voice_params_init(struct thyns_voice *voice, 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; } static inline void @@ -104,6 +114,16 @@ thyns_voice_use_param(struct thyns_voice *voice, voice->filt.values[index - i] = params->values + index; } i += THYNS_FILT_PARAM_COUNT; + + if (index < i + THYNS_ENV_PARAM_COUNT) { + voice->amp_env.values[index - i] = params->values + index; + } + i += THYNS_ENV_PARAM_COUNT; + + if (index < i + THYNS_ENV_PARAM_COUNT) { + voice->filt_env.values[index - i] = params->values + index; + } + i += THYNS_ENV_PARAM_COUNT; } static inline void