1 #include <stdlib.h>
2 #include <math.h>
3 #include "soundpipe.h"
4
5 enum { CLEAR, ATTACK, DECAY, SUSTAIN, RELEASE };
6
sp_adsr_create(sp_adsr ** p)7 int sp_adsr_create(sp_adsr **p)
8 {
9 *p = malloc(sizeof(sp_adsr));
10 return SP_OK;
11 }
12
sp_adsr_destroy(sp_adsr ** p)13 int sp_adsr_destroy(sp_adsr **p)
14 {
15 free(*p);
16 return SP_OK;
17 }
18
sp_adsr_init(sp_data * sp,sp_adsr * p)19 int sp_adsr_init(sp_data *sp, sp_adsr *p)
20 {
21 p->atk = 0.1;
22 p->dec = 0.1;
23 p->sus = 0.5;
24 p->rel = 0.3;
25 p->timer = 0;
26 p->a = 0;
27 p->b = 0;
28 p->y = 0;
29 p->x = 0;
30 p->prev = 0;
31 p->atk_time = p->atk * sp->sr;
32 p->mode = CLEAR;
33 return SP_OK;
34 }
35
tau2pole(sp_data * sp,sp_adsr * p,SPFLOAT tau)36 static SPFLOAT tau2pole(sp_data *sp, sp_adsr *p, SPFLOAT tau)
37 {
38 return exp(-1.0 / (tau * sp->sr));
39 }
40
adsr_filter(sp_data * sp,sp_adsr * p)41 static SPFLOAT adsr_filter(sp_data *sp, sp_adsr *p)
42 {
43 p->y = p->b * p->x + p->a * p->y;
44 return p->y;
45 }
46
sp_adsr_compute(sp_data * sp,sp_adsr * p,SPFLOAT * in,SPFLOAT * out)47 int sp_adsr_compute(sp_data *sp, sp_adsr *p, SPFLOAT *in, SPFLOAT *out)
48 {
49 SPFLOAT pole;
50 if(p->prev < *in && p->mode != DECAY) {
51 p->mode = ATTACK;
52 p->timer = 0;
53 /* quick fix: uncomment if broken */
54 /* pole = tau2pole(sp, p, p->atk * 0.75); */
55 /* p->atk_time = p->atk * sp->sr * 1.5; */
56 pole = tau2pole(sp, p, p->atk * 0.6);
57 p->atk_time = p->atk * sp->sr;
58 p->a = pole;
59 p->b = 1 - pole;
60 } else if(p->prev > *in) {
61 p->mode = RELEASE;
62 pole = tau2pole(sp, p, p->rel);
63 p->a = pole;
64 p->b = 1 - pole;
65 }
66
67 p->x = *in;
68 p->prev = *in;
69
70 switch(p->mode) {
71 case CLEAR:
72 *out = 0;
73 break;
74 case ATTACK:
75 p->timer++;
76 *out = adsr_filter(sp, p);
77 /* quick fix: uncomment if broken */
78 /* if(p->timer > p->atk_time) { */
79 if(*out > 0.99) {
80 p->mode = DECAY;
81 pole = tau2pole(sp, p, p->dec);
82 p->a = pole;
83 p->b = 1 - pole;
84 }
85 break;
86 case DECAY:
87 case RELEASE:
88 p->x *= p->sus;
89 *out = adsr_filter(sp, p);
90 default:
91 break;
92 }
93
94 return SP_OK;
95 }
96