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