2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef CBOX_ENVELOPE_H
20 #define CBOX_ENVELOPE_H
23 #include <config-api.h>
29 int next_if_pressed
, next_if_released
, keep_last_value
, break_on_release
, is_exp
;
32 #define MAX_ENV_STAGES 16
34 struct cbox_envelope_shape
37 struct cbox_envstage stages
[MAX_ENV_STAGES
];
42 struct cbox_envelope_shape
*shape
;
43 double stage_start_value
, cur_value
, exp_factor
, inv_time
;
44 int cur_stage
, cur_time
;
47 static inline void cbox_envelope_init_stage(struct cbox_envelope
*env
)
49 struct cbox_envstage
*es
= &env
->shape
->stages
[env
->cur_stage
];
50 env
->inv_time
= es
->time
? 1.0 / es
->time
: 1;
53 if (env
->stage_start_value
< 100.0/16384.0)
54 env
->stage_start_value
= 100.0/16384.0;
55 double ev
= es
->end_value
;
56 if (ev
< 100.0/16384.0)
58 env
->exp_factor
= log(ev
/env
->stage_start_value
);
62 static inline void cbox_envelope_go_to(struct cbox_envelope
*env
, int stage
)
64 env
->stage_start_value
= env
->cur_value
;
65 env
->cur_stage
= stage
;
67 cbox_envelope_init_stage(env
);
70 static inline void cbox_envelope_reset(struct cbox_envelope
*env
)
75 cbox_envelope_init_stage(env
);
78 static inline void cbox_envelope_update_shape(struct cbox_envelope
*env
, struct cbox_envelope_shape
*shape
)
80 struct cbox_envelope_shape
*old_shape
= env
->shape
;
82 if (env
->cur_stage
< 0)
84 struct cbox_envstage
*ns
= &env
->shape
->stages
[env
->cur_stage
];
85 struct cbox_envstage
*os
= &old_shape
->stages
[env
->cur_stage
];
87 env
->cur_time
= env
->cur_time
* ns
->time
/ os
->time
;
88 if (env
->cur_time
> ns
->time
)
89 env
->cur_time
= ns
->time
;
92 static inline float cbox_envelope_get_next(struct cbox_envelope
*env
, int released
)
94 if (env
->cur_stage
< 0)
96 return env
->cur_value
;
98 struct cbox_envstage
*es
= &env
->shape
->stages
[env
->cur_stage
];
99 double pos
= es
->time
> 0 ? env
->cur_time
* env
->inv_time
: 1;
105 // instead of exp, may use 2**x which can be factored
106 // into a shift and a table lookup
107 env
->cur_value
= env
->stage_start_value
* expf(pos
* env
->exp_factor
);
108 if (env
->cur_value
<= 100.1/16384.0)
112 env
->cur_value
= env
->stage_start_value
+ (es
->end_value
- env
->stage_start_value
) * pos
;
113 if (pos
>= 1 || (es
->break_on_release
&& released
))
115 env
->cur_stage
= released
? es
->next_if_released
: es
->next_if_pressed
;
116 if (!es
->keep_last_value
)
117 env
->stage_start_value
= es
->end_value
;
119 env
->stage_start_value
= env
->cur_value
;
121 cbox_envelope_init_stage(env
);
123 return env
->cur_value
;
134 static inline void cbox_envelope_init_adsr(struct cbox_envelope_shape
*env
, const struct cbox_adsr
*adsr
, int sr
)
136 env
->start_value
= 0;
137 env
->stages
[0].end_value
= 1;
138 env
->stages
[0].time
= adsr
->attack
* sr
;
139 env
->stages
[0].next_if_pressed
= 1;
140 env
->stages
[0].next_if_released
= 1;
141 env
->stages
[0].keep_last_value
= 1;
142 env
->stages
[0].break_on_release
= 0;
143 env
->stages
[0].is_exp
= 0;
145 env
->stages
[1].end_value
= adsr
->sustain
;
146 env
->stages
[1].time
= adsr
->decay
* sr
;
147 env
->stages
[1].next_if_pressed
= 2;
148 env
->stages
[1].next_if_released
= 2;
149 env
->stages
[1].keep_last_value
= 0;
150 env
->stages
[1].break_on_release
= 0;
151 env
->stages
[1].is_exp
= 0;
153 env
->stages
[2].end_value
= adsr
->sustain
;
154 env
->stages
[2].time
= 1 * sr
;
155 env
->stages
[2].next_if_pressed
= 2;
156 env
->stages
[2].next_if_released
= 3;
157 env
->stages
[2].keep_last_value
= 0;
158 env
->stages
[2].break_on_release
= 1;
159 env
->stages
[2].is_exp
= 0;
161 env
->stages
[3].end_value
= 0;
162 env
->stages
[3].time
= adsr
->release
* sr
;
163 env
->stages
[3].next_if_pressed
= -1;
164 env
->stages
[3].next_if_released
= -1;
165 env
->stages
[3].keep_last_value
= 0;
166 env
->stages
[3].break_on_release
= 0;
167 env
->stages
[3].is_exp
= 1;
169 env
->stages
[15].end_value
= 0;
170 env
->stages
[15].time
= 0.01 * sr
;
171 env
->stages
[15].next_if_pressed
= -1;
172 env
->stages
[15].next_if_released
= -1;
173 env
->stages
[15].keep_last_value
= 0;
174 env
->stages
[15].break_on_release
= 0;
175 env
->stages
[15].is_exp
= 0;
189 static inline void cbox_dahdsr_init(struct cbox_dahdsr
*dahdsr
, float top_value
)
193 dahdsr
->attack
= 0.f
;
196 dahdsr
->sustain
= top_value
;
197 dahdsr
->release
= 0.05f
;
200 static inline void cbox_envelope_init_dahdsr(struct cbox_envelope_shape
*env
, const struct cbox_dahdsr
*dahdsr
, int sr
, float top_value
, gboolean is_release_exp
)
202 env
->start_value
= 0;
203 env
->stages
[0].end_value
= 0;
204 env
->stages
[0].time
= dahdsr
->delay
* sr
;
205 env
->stages
[0].next_if_pressed
= 1;
206 env
->stages
[0].next_if_released
= 5;
207 env
->stages
[0].keep_last_value
= 1;
208 env
->stages
[0].break_on_release
= 0;
209 env
->stages
[0].is_exp
= 0;
211 env
->stages
[1].end_value
= top_value
;
212 env
->stages
[1].time
= dahdsr
->attack
* sr
;
213 env
->stages
[1].next_if_pressed
= 2;
214 env
->stages
[1].next_if_released
= 5;
215 env
->stages
[1].keep_last_value
= 1;
216 env
->stages
[1].break_on_release
= 1;
217 env
->stages
[1].is_exp
= 0;
219 env
->stages
[2].end_value
= top_value
;
220 env
->stages
[2].time
= dahdsr
->hold
* sr
;
221 env
->stages
[2].next_if_pressed
= 3;
222 env
->stages
[2].next_if_released
= 5;
223 env
->stages
[2].keep_last_value
= 1;
224 env
->stages
[2].break_on_release
= 1;
225 env
->stages
[2].is_exp
= 0;
227 env
->stages
[3].end_value
= dahdsr
->sustain
;
228 env
->stages
[3].time
= dahdsr
->decay
* sr
;
229 env
->stages
[3].next_if_pressed
= 4;
230 env
->stages
[3].next_if_released
= 5;
231 env
->stages
[3].keep_last_value
= 1;
232 env
->stages
[3].break_on_release
= 1;
233 env
->stages
[3].is_exp
= 0;
235 env
->stages
[4].end_value
= dahdsr
->sustain
;
236 env
->stages
[4].time
= 1 * sr
;
237 env
->stages
[4].next_if_pressed
= 4;
238 env
->stages
[4].next_if_released
= 5;
239 env
->stages
[4].keep_last_value
= 0;
240 env
->stages
[4].break_on_release
= 1;
241 env
->stages
[4].is_exp
= 0;
243 env
->stages
[5].end_value
= 0;
244 env
->stages
[5].time
= dahdsr
->release
* sr
;
245 env
->stages
[5].next_if_pressed
= -1;
246 env
->stages
[5].next_if_released
= -1;
247 env
->stages
[5].keep_last_value
= 0;
248 env
->stages
[5].break_on_release
= 0;
249 env
->stages
[5].is_exp
= is_release_exp
;
251 env
->stages
[15].end_value
= 0;
252 env
->stages
[15].time
= 0.01 * sr
;
253 env
->stages
[15].next_if_pressed
= -1;
254 env
->stages
[15].next_if_released
= -1;
255 env
->stages
[15].keep_last_value
= 0;
256 env
->stages
[15].break_on_release
= 0;
257 env
->stages
[15].is_exp
= 0;
260 static inline void cbox_envelope_modify_dahdsr(struct cbox_envelope_shape
*env
, int part
, float value
, int sr
)
269 env
->stages
[part
].time
+= value
* sr
;
270 if (env
->stages
[part
].time
< 0)
271 env
->stages
[part
].time
= 0;
274 env
->stages
[3].end_value
= value
;
275 env
->stages
[4].end_value
= value
;