We're including config.h everywhere, so we should pass compatible compiler options.
[calfbox.git] / envelope.h
blob3b36d65e2bc7dd4924e098556450d731424d7e8b
1 /*
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
22 #include <glib.h>
23 #include <config-api.h>
25 struct cbox_envstage
27 double end_value;
28 int time;
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
36 double start_value;
37 struct cbox_envstage stages[MAX_ENV_STAGES];
40 struct cbox_envelope
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;
51 if (es->is_exp)
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)
57 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;
66 env->cur_time = 0;
67 cbox_envelope_init_stage(env);
70 static inline void cbox_envelope_reset(struct cbox_envelope *env)
72 env->cur_value = 0;
73 env->cur_stage = 0;
74 env->cur_time = 0;
75 cbox_envelope_init_stage(env);
78 static inline float cbox_envelope_get_next(struct cbox_envelope *env, int released)
80 if (env->cur_stage < 0)
82 return env->cur_value;
84 struct cbox_envstage *es = &env->shape->stages[env->cur_stage];
85 double pos = es->time > 0 ? env->cur_time * env->inv_time : 1;
86 env->cur_time++;
87 if (pos > 1)
88 pos = 1;
89 if (es->is_exp)
91 // instead of exp, may use 2**x which can be factored
92 // into a shift and a table lookup
93 env->cur_value = env->stage_start_value * expf(pos * env->exp_factor);
94 if (env->cur_value <= 100.1/16384.0)
95 env->cur_value = 0;
97 else
98 env->cur_value = env->stage_start_value + (es->end_value - env->stage_start_value) * pos;
99 if (pos >= 1 || (es->break_on_release && released))
101 env->cur_stage = released ? es->next_if_released : es->next_if_pressed;
102 if (!es->keep_last_value)
103 env->stage_start_value = es->end_value;
104 else
105 env->stage_start_value = env->cur_value;
106 env->cur_time = 0;
107 cbox_envelope_init_stage(env);
109 return env->cur_value;
112 struct cbox_adsr
114 float attack;
115 float decay;
116 float sustain;
117 float release;
120 static inline void cbox_envelope_init_adsr(struct cbox_envelope_shape *env, const struct cbox_adsr *adsr, int sr)
122 env->start_value = 0;
123 env->stages[0].end_value = 1;
124 env->stages[0].time = adsr->attack * sr;
125 env->stages[0].next_if_pressed = 1;
126 env->stages[0].next_if_released = 1;
127 env->stages[0].keep_last_value = 1;
128 env->stages[0].break_on_release = 0;
129 env->stages[0].is_exp = 0;
131 env->stages[1].end_value = adsr->sustain;
132 env->stages[1].time = adsr->decay * sr;
133 env->stages[1].next_if_pressed = 2;
134 env->stages[1].next_if_released = 2;
135 env->stages[1].keep_last_value = 0;
136 env->stages[1].break_on_release = 0;
137 env->stages[1].is_exp = 0;
139 env->stages[2].end_value = adsr->sustain;
140 env->stages[2].time = 1 * sr;
141 env->stages[2].next_if_pressed = 2;
142 env->stages[2].next_if_released = 3;
143 env->stages[2].keep_last_value = 0;
144 env->stages[2].break_on_release = 1;
145 env->stages[2].is_exp = 0;
147 env->stages[3].end_value = 0;
148 env->stages[3].time = adsr->release * sr;
149 env->stages[3].next_if_pressed = -1;
150 env->stages[3].next_if_released = -1;
151 env->stages[3].keep_last_value = 0;
152 env->stages[3].break_on_release = 0;
153 env->stages[3].is_exp = 1;
155 env->stages[15].end_value = 0;
156 env->stages[15].time = 0.01 * sr;
157 env->stages[15].next_if_pressed = -1;
158 env->stages[15].next_if_released = -1;
159 env->stages[15].keep_last_value = 0;
160 env->stages[15].break_on_release = 0;
161 env->stages[15].is_exp = 0;
164 struct cbox_dahdsr
166 float start;
167 float delay;
168 float attack;
169 float hold;
170 float decay;
171 float sustain;
172 float release;
175 static inline void cbox_dahdsr_init(struct cbox_dahdsr *dahdsr, float top_value)
177 dahdsr->start = 0.f;
178 dahdsr->delay = 0.f;
179 dahdsr->attack = 0.f;
180 dahdsr->hold = 0.f;
181 dahdsr->decay = 0.f;
182 dahdsr->sustain = top_value;
183 dahdsr->release = 0.05f;
186 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)
188 env->start_value = 0;
189 env->stages[0].end_value = 0;
190 env->stages[0].time = dahdsr->delay * sr;
191 env->stages[0].next_if_pressed = 1;
192 env->stages[0].next_if_released = 5;
193 env->stages[0].keep_last_value = 1;
194 env->stages[0].break_on_release = 0;
195 env->stages[0].is_exp = 0;
197 env->stages[1].end_value = top_value;
198 env->stages[1].time = dahdsr->attack * sr;
199 env->stages[1].next_if_pressed = 2;
200 env->stages[1].next_if_released = 5;
201 env->stages[1].keep_last_value = 1;
202 env->stages[1].break_on_release = 1;
203 env->stages[1].is_exp = 0;
205 env->stages[2].end_value = top_value;
206 env->stages[2].time = dahdsr->hold * sr;
207 env->stages[2].next_if_pressed = 3;
208 env->stages[2].next_if_released = 5;
209 env->stages[2].keep_last_value = 1;
210 env->stages[2].break_on_release = 1;
211 env->stages[2].is_exp = 0;
213 env->stages[3].end_value = dahdsr->sustain;
214 env->stages[3].time = dahdsr->decay * sr;
215 env->stages[3].next_if_pressed = 4;
216 env->stages[3].next_if_released = 5;
217 env->stages[3].keep_last_value = 1;
218 env->stages[3].break_on_release = 1;
219 env->stages[3].is_exp = 0;
221 env->stages[4].end_value = dahdsr->sustain;
222 env->stages[4].time = 1 * sr;
223 env->stages[4].next_if_pressed = 4;
224 env->stages[4].next_if_released = 5;
225 env->stages[4].keep_last_value = 0;
226 env->stages[4].break_on_release = 1;
227 env->stages[4].is_exp = 0;
229 env->stages[5].end_value = 0;
230 env->stages[5].time = dahdsr->release * sr;
231 env->stages[5].next_if_pressed = -1;
232 env->stages[5].next_if_released = -1;
233 env->stages[5].keep_last_value = 0;
234 env->stages[5].break_on_release = 0;
235 env->stages[5].is_exp = is_release_exp;
237 env->stages[15].end_value = 0;
238 env->stages[15].time = 0.01 * sr;
239 env->stages[15].next_if_pressed = -1;
240 env->stages[15].next_if_released = -1;
241 env->stages[15].keep_last_value = 0;
242 env->stages[15].break_on_release = 0;
243 env->stages[15].is_exp = 0;
246 static inline void cbox_envelope_modify_dahdsr(struct cbox_envelope_shape *env, int part, float value, int sr)
248 switch(part)
250 case 0: // delay
251 case 1: // attack
252 case 2: // hold
253 case 3: // decay
254 case 5: // release
255 env->stages[part].time += value * sr;
256 if (env->stages[part].time < 0)
257 env->stages[part].time = 0;
258 break;
259 case 4: // sustain
260 env->stages[3].end_value = value;
261 env->stages[4].end_value = value;
262 break;
266 #endif