ref: dd88a3bf36323b1917aad54943766529bcfbe9d0
dir: /modules/adsr.c/
/* This code is placed in the public domain. */ #include <stdlib.h> #include <math.h> #include "soundpipe.h" enum { CLEAR, ATTACK, DECAY, SUSTAIN, RELEASE }; int sp_adsr_create(sp_adsr **p) { *p = malloc(sizeof(sp_adsr)); return SP_OK; } int sp_adsr_destroy(sp_adsr **p) { free(*p); return SP_OK; } int sp_adsr_init(sp_data *sp, sp_adsr *p) { p->atk = 0.1; p->dec = 0.1; p->sus = 0.5; p->rel = 0.3; p->timer = 0; p->a = 0; p->b = 0; p->y = 0; p->x = 0; p->prev = 0; p->atk_time = p->atk * sp->sr; p->mode = CLEAR; return SP_OK; } static SPFLOAT tau2pole(sp_data *sp, sp_adsr *p, SPFLOAT tau) { return exp(-1.0 / (tau * sp->sr)); } static SPFLOAT adsr_filter(sp_data *sp, sp_adsr *p) { p->y = p->b * p->x + p->a * p->y; return p->y; } int sp_adsr_compute(sp_data *sp, sp_adsr *p, SPFLOAT *in, SPFLOAT *out) { SPFLOAT pole; if (p->prev < *in && p->mode != DECAY) { p->mode = ATTACK; p->timer = 0; /* quick fix: uncomment if broken */ /* pole = tau2pole(sp, p, p->atk * 0.75); */ /* p->atk_time = p->atk * sp->sr * 1.5; */ pole = tau2pole(sp, p, p->atk * 0.6); p->atk_time = p->atk * sp->sr; p->a = pole; p->b = 1 - pole; } else if (p->prev > *in) { p->mode = RELEASE; pole = tau2pole(sp, p, p->rel); p->a = pole; p->b = 1 - pole; } p->x = *in; p->prev = *in; switch (p->mode) { case CLEAR: *out = 0; break; case ATTACK: p->timer++; *out = adsr_filter(sp, p); /* quick fix: uncomment if broken */ /* if(p->timer > p->atk_time) { */ if (*out > 0.99) { p->mode = DECAY; pole = tau2pole(sp, p, p->dec); p->a = pole; p->b = 1 - pole; } break; case DECAY: case RELEASE: p->x *= p->sus; *out = adsr_filter(sp, p); default: break; } return SP_OK; }