1
2 /*
3 * Diverse Bristol audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21 /*#define BRISTOL_DBG */
22 /*
23 * Need to have basic template for an operator. Will consist of
24 *
25 * envelopeinit()
26 * operate()
27 * reset()
28 * destroy()
29 *
30 * destroy() is in the library.
31 *
32 * Operate will be called when all the inputs have been loaded, and the result
33 * will be an output buffer written to the next operator.
34 *
35 *
36 * level1 rate1 level2
37 * level2 rate2 level3
38 * level3 rate3 level4 (Sustain)
39 * level4 rate4 level5
40 *
41 * Level 1 and level 5 are typically going to be zero however not for the
42 * CS-80, they will be equal to sustain via the GUI. All the rates can be
43 * applied in either direction since the envelope may retrigger.
44 *
45 * If any two adjacent levels are similar they should be dropped, alternatively
46 * the rate is actually a time for that level?
47 *
48 * Needs options for touch sensitivity, rezero, maybe others.
49 */
50
51 #include "bristol.h"
52 #include "env5stage.h"
53
54 static float samplerate = 0;
55
56 /*
57 * The name of this operator, IO count, and IO names.
58 */
59 #define OPNAME "ENV"
60 #define OPDESCRIPTION "Digital ADSR 5-stage Envelope Generator"
61 #define PCOUNT 13
62 #define IOCOUNT 1
63
64 #define ENV_OUT_IND 0
65
66 #define LEVEL_0 0
67 #define RATE_0 1
68 #define LEVEL_1 2
69 #define RATE_1 3
70 #define LEVEL_2 4
71 #define RATE_2 5
72 #define LEVEL_3 6
73 #define RATE_3 7
74 #define LEVEL_4 8
75 #define GAIN 9
76 #define VELOCITY 10
77 #define REZERO 11
78 #define RETRIGGER 12
79
80 /*
81 * Reset any local memory information.
82 */
destroy(bristolOP * operator)83 static int destroy(bristolOP *operator)
84 {
85 #ifdef BRISTOL_DBG
86 printf("reset(%x)\n", operator);
87 #endif
88
89 /*
90 * Unmalloc anything we added to this structure
91 */
92 bristolfree(operator->specs);
93
94 /*
95 * Free any local memory. We should also free ourselves, since we did the
96 * initial allocation.
97 */
98 cleanup(operator);
99 return(0);
100 }
101
102 /*
103 * Reset any local memory information.
104 */
reset(bristolOP * operator,bristolOPParams * param)105 static int reset(bristolOP *operator, bristolOPParams *param)
106 {
107 #ifdef BRISTOL_DBG
108 printf("reset(%x)\n", operator);
109 #endif
110
111 param->param[0].float_val = 0;
112 param->param[1].float_val = 0.1;
113 param->param[2].float_val = 1.0;
114 param->param[3].float_val = 0.3;
115 param->param[4].float_val = 0.1;
116 param->param[5].float_val = 0.3;
117 param->param[6].float_val = 0.5;
118 param->param[7].float_val = 0.2;
119 param->param[8].float_val = 0;
120 /* Gain */
121 param->param[9].float_val = 1.0;
122 /* Velocity and rezero flags */
123 param->param[10].int_val = 1;
124 param->param[11].int_val = 0;
125
126 return(0);
127 }
128
129 /*
130 * Alter an internal parameter of an operator.
131 */
param(bristolOP * operator,bristolOPParams * param,unsigned char index,float value)132 static int param(bristolOP *operator, bristolOPParams *param,
133 unsigned char index, float value)
134 {
135 //int ivalue = value * C_RANGE_MIN_1;
136
137 #ifdef BRISTOL_DBG
138 printf("env5param(%i, %f)\n", index, value);
139 #endif
140
141 if (index >= PCOUNT)
142 return(0);
143
144 switch (index) {
145 case 0:
146 case 2:
147 case 4:
148 case 6:
149 case 8:
150 case 9:
151 /*
152 * Levels and gain
153 */
154 param->param[index].float_val = value;
155 break;
156 case 1:
157 case 3:
158 case 5:
159 case 7:
160 /*
161 * Rates: get tweaked into a rate at operational time as
162 * per decay and release.
163 */
164 if ((param->param[index].float_val = value * value) == 0)
165 param->param[index].float_val
166 = 1.0 / (CONTROLLER_RANGE * CONTROLLER_RANGE);
167
168 /*
169 * This is now converted into a number of seconds up to 10
170 */
171 if ((param->param[index].float_val = 1.0
172 / (param->param[index].float_val * samplerate * 10)) > 0.5)
173 param->param[index].float_val = 0.5;
174 break;
175 case 10:
176 case 11:
177 case 12:
178 if (value == 0)
179 param->param[index].int_val = 0;
180 else
181 param->param[index].int_val = 1;
182 break;
183 }
184 #ifdef BRISTOL_DBG
185 printf("R: %1.2f %1.4f %1.2f, %1.2f %1.2f, %1.2f %1.2f, %1.2f %1.2f\n",
186 param->param[LEVEL_0].float_val, param->param[RATE_0].float_val,
187 param->param[LEVEL_1].float_val, param->param[RATE_1].float_val,
188 param->param[LEVEL_2].float_val, param->param[RATE_2].float_val,
189 param->param[LEVEL_3].float_val, param->param[RATE_3].float_val,
190 param->param[LEVEL_4].float_val);
191 #endif
192
193 return(0);
194 }
195
196 /*
197 * Envelope generation:
198 */
operate(register bristolOP * operator,bristolVoice * voice,bristolOPParams * param,void * lcl)199 static int operate(register bristolOP *operator, bristolVoice *voice,
200 bristolOPParams *param, void *lcl)
201 {
202 register bristolENVlocal *local = lcl;
203 register float *ob, current, cgain, gain;
204 register int count;
205 bristolENV *specs;
206
207 specs = (bristolENV *) operator->specs;
208
209 #ifdef BRISTOL_DBG
210 printf("env5stage(%x, %x, %x, %x)\n", operator, voice, param, local);
211 #endif
212
213 count = specs->spec.io[0].samplecount;
214 ob = specs->spec.io[0].buf;
215
216 if (voice->flags & BRISTOL_KEYOFF)
217 {
218 voice->flags |= BRISTOL_KEYOFFING;
219 local->state = RELEASE_STAGE;
220 }
221
222 cgain = local->cgain;
223 current = local->current;
224
225 if (param->param[VELOCITY].int_val)
226 gain = param->param[GAIN].float_val
227 * (voice->velocity + voice->press + voice->chanpressure);
228 else
229 gain = param->param[GAIN].float_val;
230
231 if (voice->flags & BRISTOL_KEYREON)
232 {
233 if (param->param[RETRIGGER].int_val)
234 {
235 if (param->param[REZERO].int_val != 0)
236 current = param->param[LEVEL_0].float_val;
237 local->state = ATTACK_STAGE;
238 }
239 } else if (voice->flags & BRISTOL_KEYON) {
240 cgain = gain;
241 current = param->param[LEVEL_0].float_val;
242 local->state = ATTACK_STAGE;
243 /*
244 printf("T: %1.2f %1.4f %1.2f, %1.2f %1.2f, %1.2f %1.2f, %1.2f %1.2f\n",
245 param->param[LEVEL_0].float_val,
246 param->param[RATE_0].float_val,
247 param->param[LEVEL_1].float_val,
248 param->param[RATE_1].float_val,
249 param->param[LEVEL_2].float_val,
250 param->param[RATE_2].float_val,
251 param->param[LEVEL_3].float_val,
252 param->param[RATE_3].float_val,
253 param->param[LEVEL_4].float_val);
254 */
255 if ((~voice->flags & BRISTOL_KEYREON) &&
256 (voice->offset > 0) && (voice->offset < count))
257 {
258 if (voice->baudio->midiflags & BRISTOL_MIDI_DEBUG1)
259 printf("envelope trigger offset %i frames\n", voice->offset);
260
261 memset(ob, 0.0f, voice->offset * sizeof(float));
262 ob += voice->offset;
263 count -= voice->offset;
264 }
265 }
266
267 while (count-- > 0)
268 {
269 switch (local->state) {
270 case STAGE_0:
271 if (current > param->param[LEVEL_1].float_val)
272 {
273 if ((*ob = (current -= param->param[RATE_0].float_val))
274 < param->param[LEVEL_1].float_val)
275 local->state++;
276 } else {
277 if ((*ob = (current += param->param[RATE_0].float_val))
278 >= param->param[LEVEL_1].float_val)
279 local->state++;
280 }
281 break;
282 case STAGE_1:
283 if (current > param->param[LEVEL_2].float_val)
284 {
285 if ((*ob = (current -= param->param[RATE_1].float_val))
286 < param->param[LEVEL_2].float_val)
287 local->state++;
288 } else {
289 if ((*ob = (current += param->param[RATE_1].float_val))
290 >= param->param[LEVEL_2].float_val)
291 local->state++;
292 }
293 break;
294 case STAGE_2:
295 if (current > param->param[LEVEL_3].float_val)
296 {
297 if ((*ob = (current -= param->param[RATE_2].float_val))
298 < param->param[LEVEL_3].float_val)
299 local->state++;
300 } else {
301 if ((*ob = (current += param->param[RATE_2].float_val))
302 >= param->param[LEVEL_3].float_val)
303 local->state++;
304 }
305 break;
306 case STAGE_3:
307 /* Sustain */
308 if (current > param->param[LEVEL_3].float_val)
309 {
310 if ((*ob = (current -= param->param[RATE_2].float_val))
311 < param->param[LEVEL_3].float_val)
312 current = param->param[LEVEL_3].float_val;
313 } else if (current < param->param[LEVEL_3].float_val) {
314 if ((*ob = (current += param->param[RATE_2].float_val))
315 >= param->param[LEVEL_3].float_val)
316 current = param->param[LEVEL_3].float_val;
317 } else
318 *ob = current;
319 break;
320 case STAGE_4:
321 if (current > param->param[LEVEL_4].float_val)
322 {
323 if ((*ob = (current -= param->param[RATE_3].float_val))
324 < param->param[LEVEL_4].float_val)
325 local->state++;
326 } else {
327 if ((*ob = (current += param->param[RATE_3].float_val))
328 >= param->param[LEVEL_4].float_val)
329 local->state++;
330 }
331 break;
332 case STAGE_5:
333 default:
334 *ob = param->param[LEVEL_4].float_val;
335 break;
336 }
337
338 /*
339 * This smooths over key reassigments, channel or poly pressure changes
340 * where the target gain can jump noticably - our operational gain will
341 * tend towards the target. It may cause a bit of breathing however that
342 * is far preferable to ticking.
343 */
344 if (cgain > gain)
345 {
346 if ((cgain -= 0.067) < gain) cgain = gain;
347 } else if (cgain < gain) {
348 if ((cgain += 0.067) > gain) cgain = gain;
349 }
350
351 *ob++ *= cgain * BRISTOL_VPO;
352 }
353
354 if (local->state == END_STAGE)
355 {
356 voice->flags |= BRISTOL_KEYDONE;
357 voice->flags &= ~BRISTOL_KEYOFFING;
358 } else
359 voice->flags &= ~(BRISTOL_KEYDONE|BRISTOL_KEYOFFING);
360
361 local->current = current;
362 local->cgain = cgain;
363
364 return(0);
365 }
366
367 /*
368 * Setup any variables in our OP structure, in our IO structures, and malloc
369 * any memory we need.
370 */
371 bristolOP *
env5stageinit(bristolOP ** operator,int index,int sr,int samplecount)372 env5stageinit(bristolOP **operator, int index, int sr, int samplecount)
373 {
374 bristolENV *specs;
375
376 #ifdef BRISTOL_DBG
377 printf("env5stageinit(%x(%x), %i, %i, %i)\n",
378 operator, *operator, index, samplerate, samplecount);
379 #endif
380
381 *operator = bristolOPinit(operator, index, samplecount);
382 samplerate = sr;
383
384 /*
385 * Then the local parameters specific to this operator. These will be
386 * the same for each operator, but must be inited in the local code.
387 */
388 (*operator)->operate = operate;
389 (*operator)->destroy = destroy;
390 (*operator)->reset = reset;
391 (*operator)->param = param;
392
393 specs = (bristolENV *) bristolmalloc0(sizeof(bristolENV));
394 (*operator)->specs = (bristolOPSpec *) specs;
395 (*operator)->size = sizeof(bristolENV);
396
397 /*
398 * These are specific to this operator, and will need to be altered for
399 * each operator.
400 */
401 specs->spec.opname = OPNAME;
402 specs->spec.description = OPDESCRIPTION;
403 specs->spec.pcount = PCOUNT;
404 specs->spec.iocount = IOCOUNT;
405 specs->spec.localsize = sizeof(bristolENVlocal);
406
407 /*
408 * Now fill in the envelope specs for this operator. These are specific to
409 * an ADSR.
410 */
411 specs->spec.param[0].pname = "level-3";
412 specs->spec.param[0].description = "level 1";
413 specs->spec.param[0].type = BRISTOL_FLOAT;
414 specs->spec.param[0].low = 0;
415 specs->spec.param[0].high = 1;
416 specs->spec.param[0].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
417
418 specs->spec.param[1].pname = "rate-1";
419 specs->spec.param[1].description = "Rate 1";
420 specs->spec.param[1].type = BRISTOL_FLOAT;
421 specs->spec.param[1].low = 0;
422 specs->spec.param[1].high = 1;
423 specs->spec.param[1].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
424
425 specs->spec.param[2].pname = "level-2";
426 specs->spec.param[2].description = "level 2";
427 specs->spec.param[2].type = BRISTOL_FLOAT;
428 specs->spec.param[2].low = 0;
429 specs->spec.param[2].high = 1;
430 specs->spec.param[2].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
431
432 specs->spec.param[3].pname = "rate-2";
433 specs->spec.param[3].description = "Rate 2";
434 specs->spec.param[3].type = BRISTOL_FLOAT;
435 specs->spec.param[3].low = 0;
436 specs->spec.param[3].high = 1;
437 specs->spec.param[3].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
438
439 specs->spec.param[4].pname = "level-3";
440 specs->spec.param[4].description = "level 3";
441 specs->spec.param[4].type = BRISTOL_FLOAT;
442 specs->spec.param[4].low = 0;
443 specs->spec.param[4].high = 1;
444 specs->spec.param[4].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
445
446 specs->spec.param[5].pname = "rate-3";
447 specs->spec.param[5].description = "Rate 3";
448 specs->spec.param[5].type = BRISTOL_FLOAT;
449 specs->spec.param[5].low = 0;
450 specs->spec.param[5].high = 1;
451 specs->spec.param[5].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
452
453 specs->spec.param[6].pname = "level-4";
454 specs->spec.param[6].description = "level 4";
455 specs->spec.param[6].type = BRISTOL_FLOAT;
456 specs->spec.param[6].low = 0;
457 specs->spec.param[6].high = 1;
458 specs->spec.param[6].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
459
460 specs->spec.param[7].pname = "rate-4";
461 specs->spec.param[7].description = "Rate 4";
462 specs->spec.param[7].type = BRISTOL_FLOAT;
463 specs->spec.param[7].low = 0;
464 specs->spec.param[7].high = 1;
465 specs->spec.param[7].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
466
467 specs->spec.param[8].pname = "level-5";
468 specs->spec.param[8].description = "level 5";
469 specs->spec.param[8].type = BRISTOL_FLOAT;
470 specs->spec.param[8].low = 0;
471 specs->spec.param[8].high = 1;
472 specs->spec.param[8].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
473
474 specs->spec.param[9].pname = "gain";
475 specs->spec.param[9].description = "Overall signal level";
476 specs->spec.param[9].type = BRISTOL_FLOAT;
477 specs->spec.param[9].low = 0;
478 specs->spec.param[9].high = 1;
479 specs->spec.param[9].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
480
481 specs->spec.param[10].pname = "velocity";
482 specs->spec.param[10].description = "velocity sensitive gain";
483 specs->spec.param[10].type = BRISTOL_INT;
484 specs->spec.param[10].low = 0;
485 specs->spec.param[10].high = 1;
486 specs->spec.param[10].flags = BRISTOL_BUTTON;
487
488 specs->spec.param[11].pname = "rezero";
489 specs->spec.param[11].description = "reset gain on retrigger";
490 specs->spec.param[11].type = BRISTOL_INT;
491 specs->spec.param[11].low = 0;
492 specs->spec.param[11].high = 1;
493 specs->spec.param[11].flags = BRISTOL_BUTTON;
494
495 specs->spec.param[12].pname = "retrigger";
496 specs->spec.param[12].description = "retrigger on reon";
497 specs->spec.param[12].type = BRISTOL_INT;
498 specs->spec.param[12].low = 0;
499 specs->spec.param[12].high = 1;
500 specs->spec.param[12].flags = BRISTOL_BUTTON;
501
502 /*
503 * Now fill in the dco IO specs.
504 */
505 specs->spec.io[0].ioname = "output";
506 specs->spec.io[0].description = "ADSR Envelope Output Signal";
507 specs->spec.io[0].samplerate = samplerate;
508 specs->spec.io[0].samplecount = samplecount;
509 specs->spec.io[0].flags = BRISTOL_DC|BRISTOL_OUTPUT;
510
511 return(*operator);
512 }
513
514