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:
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