clap

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

commit ce11a8537f677f58a1941d7e9240083d9b143786
parent 473967b226ac640bcc557b1e915098e48eedf904
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Fri, 16 Jan 2015 18:10:36 +0100

Bring ramp support to the demo synthesizer

Diffstat:
Mexamples/thyns/params.h | 17+++++++++++++++++
Mexamples/thyns/thyns.h | 149++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mexamples/thyns/voice.h | 8+++++++-
3 files changed, 142 insertions(+), 32 deletions(-)

diff --git a/examples/thyns/params.h b/examples/thyns/params.h @@ -12,6 +12,23 @@ struct thyns_params 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) { diff --git a/examples/thyns/thyns.h b/examples/thyns/thyns.h @@ -5,7 +5,8 @@ # include "dlist.h" # include "params.h" -# define THYNS_VOICE_COUNT 32 +# define THYNS_VOICES_COUNT 8 +# define THYNS_RAMPS_COUNT 32 struct thyns { @@ -14,12 +15,19 @@ struct thyns uint64_t steady_time; - struct thyns_voice *singing; - struct thyns_voice *idle; - struct thyns_voice *keys[0x80]; + 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_voice buffer[THYNS_VOICE_COUNT]; + 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, uint32_t sr) @@ -31,21 +39,24 @@ static inline void thyns_init(struct thyns *thyns, uint32_t sr) thyns_params_init(&thyns->params); - for (uint32_t i = 0; i < THYNS_VOICE_COUNT; ++i) { - thyns_voice_init(thyns->buffer + i, sr); - thyns_dlist_push_back(thyns->idle, thyns->buffer + i); + for (uint32_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 (uint32_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->singing) + if (!thyns->voices_singing) return 0; double out = 0; struct thyns_voice *prev = NULL; - struct thyns_voice *v = thyns->singing; + struct thyns_voice *v = thyns->voices_singing; struct thyns_voice *end = v->prev; /* compute voices */ @@ -56,10 +67,10 @@ static double thyns_step(struct thyns *thyns, if (v->amp_env.state == THYNS_ENV_IDLE) { printf("releasing %d\n", v->key); assert(v->key != 0); - thyns->keys[v->key] = NULL; - thyns_dlist_remove(thyns->singing, v); - thyns_dlist_push_back(thyns->idle, v); - v = prev ? prev->next : thyns->singing; + 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; @@ -78,24 +89,24 @@ thyns_note_on(struct thyns *thyns, printf("note_on(%d, %f)\n", key, pitch); assert(key < 0x80); - if (thyns->keys[key]) { - voice = thyns->keys[key]; + if (thyns->voices_keys[key]) { + voice = thyns->voices_keys[key]; } else { - if (thyns->idle) { - voice = thyns->idle; - thyns_dlist_remove(thyns->idle, voice); + if (thyns->voices_idle) { + voice = thyns->voices_idle; + thyns_dlist_remove(thyns->voices_idle, voice); } else { - voice = thyns->singing; - thyns_dlist_remove(thyns->singing, voice); - thyns->keys[voice->key] = NULL; + voice = thyns->voices_singing; + thyns_dlist_remove(thyns->voices_singing, voice); + thyns->voices_keys[voice->key] = NULL; } - thyns_dlist_push_back(thyns->singing, voice); - thyns->keys[key] = voice; + 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->keys[key], key, pitch); + thyns_voice_start_note(thyns->voices_keys[key], key, pitch); } static inline void @@ -104,8 +115,16 @@ thyns_note_off(struct thyns *thyns, { printf("note_off(%d)\n", key); assert(key < 0x80); - if (thyns->keys[key]) - thyns_voice_stop_note(thyns->keys[key], key); + 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 @@ -122,15 +141,83 @@ thyns_handle_event(struct thyns *thyns, break; case CLAP_EVENT_PARAM_SET: - if (ev->param.is_global) + if (ev->param.is_global) { thyns->params.values[ev->param.index] = ev->param.value; - else if (thyns->keys[ev->param.key]) { - struct thyns_voice *voice = thyns->keys[ev->param.key]; + + // 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; } @@ -161,7 +248,7 @@ thyns_process(struct thyns *thyns, struct clap_process *process) // ensure no more events are left assert(!ev); - if (thyns->singing) + if (thyns->voices_singing) return CLAP_PROCESS_CONTINUE; return CLAP_PROCESS_STOP; } diff --git a/examples/thyns/voice.h b/examples/thyns/voice.h @@ -48,7 +48,9 @@ struct thyns_voice union clap_param_value *values[THYNS_VOICE_PARAM_COUNT]; // voice parameters - struct thyns_params params; + struct thyns_params params; + struct thyns_ramps ramps; + struct thyns_ramp *ramping; // list }; static inline void @@ -127,6 +129,10 @@ thyns_voice_init(struct thyns_voice *voice, uint32_t sr) // amp thyns_env_init(&voice->amp_env, sr); + + // parameters ramps + memset(&voice->ramps, 0, sizeof (voice->ramps)); + voice->ramping = NULL; } static inline void