ref: 264e4718c21792ed8ee230d39aa2b9ac88d73b14
dir: /modules/tadsr.c/
/* * TADSR * * This module uses modified code from Perry Cook's ADSR STK module. * */ #include <stdlib.h> #include <math.h> #include "soundpipe.h" enum{ ATTACK, DECAY, SUSTAIN, RELEASE, CLEAR, KEY_ON, KEY_OFF }; static void make_Envelope(sp_tadsr *e) { e->target = 0.0; e->value = 0.0; e->rate = 0.001; e->state = 1; } static void make_ADSR(sp_tadsr *a) { make_Envelope(a); a->target = 0.0; a->value = 0.0; a->attackRate = 0.001; a->decayRate = 0.001; a->sustainLevel = 0.0; a->releaseRate = 0.01; a->state = CLEAR; } static void ADSR_keyOn(sp_tadsr *a) { a->target = 1.0; a->rate = a->attackRate; a->state = ATTACK; } static void ADSR_keyOff(sp_tadsr *a) { a->target = 0.0; a->rate = a->releaseRate; a->state = RELEASE; } static void ADSR_setSustainLevel(sp_data *sp, sp_tadsr *a, SPFLOAT aLevel) { a->sustainLevel = aLevel; } static void ADSR_setAttackTime(sp_data *sp, sp_tadsr *a, SPFLOAT aTime) { a->attackRate = 1.0 / (aTime * sp->sr); } static void ADSR_setDecayTime(sp_data *sp, sp_tadsr *a, SPFLOAT aTime) { a->decayRate = 1.0 / (aTime * sp->sr); } static void ADSR_setReleaseTime(sp_data *sp, sp_tadsr *a, SPFLOAT aTime) { a->releaseRate = 1.0 / (aTime * sp->sr); } static void ADSR_setAllTimes(sp_data *sp, sp_tadsr *a, SPFLOAT attTime, SPFLOAT decTime, SPFLOAT susLevel, SPFLOAT relTime) { ADSR_setAttackTime(sp, a, attTime); ADSR_setDecayTime(sp, a, decTime); ADSR_setSustainLevel(sp, a, susLevel); ADSR_setReleaseTime(sp, a, relTime); } static SPFLOAT ADSR_tick(sp_tadsr *a) { SPFLOAT out = 0; if (a->state == ATTACK) { a->value += a->rate; if (a->value >= a->target) { a->value = a->target; a->rate = a->decayRate; a->target = a->sustainLevel; a->state = DECAY; } out = a->value; } else if (a->state == DECAY) { a->value -= a->decayRate; out = a->value; if (a->value <= a->sustainLevel) { a->value = a->sustainLevel; out = a->sustainLevel; a->rate = 0.0; a->state = SUSTAIN; } } else if (a->state == RELEASE) { a->value -= a->releaseRate; if (a->value <= 0.0) { a->value = 0.0; a->state = CLEAR; } out = a->value; } else if (a->state == SUSTAIN) { out = a->sustainLevel; } return out; } int sp_tadsr_create(sp_tadsr **p) { *p = malloc(sizeof(sp_tadsr)); return SP_OK; } int sp_tadsr_destroy(sp_tadsr **p) { free(*p); return SP_OK; } int sp_tadsr_init(sp_data *sp, sp_tadsr *p) { make_ADSR(p); p->atk = 0.5; p->dec = 0.5; p->sus = 0.0; p->rel = 0.5; p->mode = KEY_OFF; return SP_OK; } int sp_tadsr_compute(sp_data *sp, sp_tadsr *p, SPFLOAT *trig, SPFLOAT *out) { if(*trig != 0) { if(*trig == 2) { ADSR_keyOff(p); p->mode = KEY_OFF; }else if(p->mode == KEY_OFF) { ADSR_setAllTimes(sp, p, p->atk, p->dec, p->sus, p->rel); ADSR_keyOn(p); p->mode = KEY_ON; } else { ADSR_keyOff(p); p->mode = KEY_OFF; } } *out = ADSR_tick(p); return SP_OK; }