1 /* Mixer + Trigger LV2
2  *
3  * Copyright (C) 2013 Robin Gareus <robin@gareus.org>
4  *
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 2, or (at your option)
8  * any later version.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <string.h>
28 #include <stdbool.h>
29 #include <math.h>
30 #include <ltc.h>
31 
32 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
33 #include "mixtri.h"
34 
35 #ifndef MIN
36 #define MIN(A,B) ( (A) < (B) ? (A) : (B) )
37 #endif
38 #ifndef MAX
39 #define MAX(A,B) ( (A) > (B) ? (A) : (B) )
40 #endif
41 
42 /******************************************************************************
43  * trigger helpers
44  */
45 
46 #define FIRE_TRIGGER (1.0)
47 
edge_trigger(const int mode,const float lvl,const float v0,const float v1)48 static inline bool edge_trigger(const int mode, const float lvl, const float v0, const float v1) {
49 	if (   (mode&1) /* rising edge*/
50 			&& (v0 <= lvl) && (v1 > lvl)) return true;
51 	if (   (mode&2) /* falling edge*/
52 			&& (v0 >= lvl) && (v1 < lvl)) return true;
53 	return false;
54 }
55 
range_trigger(const float l0,const float l1,const float v0,const float v1)56 static inline int range_trigger(const float l0, const float l1, const float v0, const float v1) {
57 	assert (l0 <= l1);
58 	/* bit 1: falling edge, 2:rising edge  || bit(3) 4: outside */
59 	// prev signal was outside, new signal inside
60 	if ((v0 > l1 || v0 < l0) && v1 >= l0 && v1 <= l1) return (v0 > l1) ? 2 : 1;
61 	// prev signal inside , new signal outside range
62 	if (v0 <= l1 && v0 >= l0 && (v1 < l0 || v1 > l1)) return (v1 < l0) ? 6 : 5;
63 	return 0;
64 }
65 
66 /******************************************************************************
67  * LV2 routines
68  */
69 
70 #define FADE_LEN (64)
71 
72 typedef struct {
73 	float buffer[MAXDELAY];
74 	int c_dly;
75 	int w_ptr;
76 	int r_ptr;
77 } DelayLine;
78 
79 typedef struct {
80 	/* LV2 ports */
81 	float* a_in[4];
82 	float* a_out[4];
83 
84 	float* p_gain_in[4];
85 	float* p_mix[12];
86 	float* p_delay[7];
87 	float* p_input[4];
88 	float* p_trigger_chn;
89 	float* p_trigger_mode;
90 
91 	float* p_trigger_edge;
92 	float* p_trigger_level0;
93 	float* p_trigger_level1;
94 	float* p_trigger_time0;
95 	float* p_trigger_time1;
96 
97 	double rate;
98 
99 	/* internal state, delaylines */
100 	DelayLine dly_i[4];
101 	DelayLine dly_o[3];
102 
103 	/* internal state, filters */
104 	int   mode_input[4];
105 	float flt_z[4];
106 	float flt_y[4];
107 	float flt_alpha;
108 
109 	float gain_db[4];
110 	float gain_in[4];
111 
112 	float amp_z[4];
113 	float mix_z[12];
114 	float mix_alpha;
115 
116 	/* trigger state */
117 	LTCDecoder *decoder;
118 	uint64_t monotonic_cnt;
119 	uint64_t ts_time;
120 	float ts_prev;
121 	int ts_hysteresis;
122 
123 	/* trigger settings cache */
124 	int   tri_mode_prev;
125 	float tri_alpha;
126 	float tri_t0;
127 
128 } MixTri;
129 
130 static LV2_Handle
instantiate_mixtri(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)131 instantiate_mixtri(
132 		const LV2_Descriptor*     descriptor,
133 		double                    rate,
134 		const char*               bundle_path,
135 		const LV2_Feature* const* features)
136 {
137 	MixTri* self = (MixTri*)calloc(1, sizeof(MixTri));
138 	if(!self) {
139 		return NULL;
140 	}
141 
142 	self->rate = rate;
143 
144 	/* low/high pass filter time-constants */
145 	// 1.0 - e^(-2.0 * π * v / 48000)
146 	self->mix_alpha = 1.0f - expf(-2.0 * M_PI * 100 / rate); // LPF
147 	self->flt_alpha = 1.0 - 5.0 / rate; // HPF
148 
149 	for (uint32_t i = 0; i < 4; ++i) {
150 		self->mode_input[i] = 0;
151 		self->flt_z[i] = 0;
152 		self->flt_y[i] = 0;
153 		memset(self->dly_i[i].buffer, 0, sizeof(float) * MAXDELAY);
154 		self->gain_db[i] = 0.0;
155 		self->gain_in[i] = 1.0;
156 		self->amp_z[i] = 0;
157 	}
158 	for (uint32_t i = 0; i < 3; ++i) {
159 		memset(self->dly_o[i].buffer, 0, sizeof(float) * MAXDELAY);
160 	}
161 	for (uint32_t i = 0; i < 12; ++i) {
162 		self->mix_z[i] = 0;
163 	}
164 
165 	/* trigger settings & state*/
166 	self->decoder = ltc_decoder_create(rate / 25, 8);
167 	self->monotonic_cnt = 0;
168 	self->ts_time = 0;
169 	self->ts_prev = 0;
170 	self->ts_hysteresis = 0;
171 
172 	self->tri_t0 = -1;
173 	self->tri_alpha = 1.0f;
174 	self->tri_mode_prev = 0;
175 	return (LV2_Handle)self;
176 }
177 
178 static void
connect_port_mixtri(LV2_Handle handle,uint32_t port,void * data)179 connect_port_mixtri(
180 		LV2_Handle handle,
181 		uint32_t   port,
182 		void*      data)
183 {
184 	MixTri* self = (MixTri*)handle;
185 
186 	switch ((PortIndexMixTri)port) {
187 		case MIXTRI_TRIG_CHN:
188 			self->p_trigger_chn = (float*)data;
189 			break;
190 		case MIXTRI_TRIG_MODE:
191 			self->p_trigger_mode = (float*)data;
192 			break;
193 		case MIXTRI_TRIG_EDGE:
194 			self->p_trigger_edge = (float*)data;
195 			break;
196 		case MIXTRI_TRIG_LVL0:
197 			self->p_trigger_level0 = (float*)data;
198 			break;
199 		case MIXTRI_TRIG_LVL1:
200 			self->p_trigger_level1 = (float*)data;
201 			break;
202 		case MIXTRI_TRIG_TME0:
203 			self->p_trigger_time0 = (float*)data;
204 			break;
205 		case MIXTRI_TRIG_TME1:
206 			self->p_trigger_time1 = (float*)data;
207 			break;
208 		default:
209 			if (port >= MIXTRI_AUDIO_IN_0 && port <= MIXTRI_AUDIO_IN_3) {
210 				self->a_in[port - MIXTRI_AUDIO_IN_0] = (float*)data;
211 			}
212 			else if (port >= MIXTRI_AUDIO_OUT_0 && port <= MIXTRI_AUDIO_OUT_T) {
213 				self->a_out[port - MIXTRI_AUDIO_OUT_0] = (float*)data;
214 			}
215 			else if (port >= MIXTRI_MIX_0_0 && port <= MIXTRI_MIX_3_2) {
216 				self->p_mix[port - MIXTRI_MIX_0_0] = (float*)data;
217 			}
218 			else if (port >= MIXTRI_DLY_I_0 && port <= MIXTRI_DLY_O_2) {
219 				self->p_delay[port - MIXTRI_DLY_I_0] = (float*)data;
220 			}
221 			else if (port >= MIXTRI_GAIN_I_0 && port <= MIXTRI_GAIN_I_3) {
222 				self->p_gain_in[port - MIXTRI_GAIN_I_0] = (float*)data;
223 			}
224 			else if (port >= MIXTRI_MOD_I_0 && port <= MIXTRI_MOD_I_3) {
225 				self->p_input[port - MIXTRI_MOD_I_0] = (float*)data;
226 			}
227 			break;
228 	}
229 }
230 
231 static void
run_mixtri(LV2_Handle handle,uint32_t n_samples)232 run_mixtri(LV2_Handle handle, uint32_t n_samples)
233 {
234 	MixTri* self = (MixTri*)handle;
235 
236 	/* localize variable into scope */
237 	float const * const * a_i = (float const * const *) self->a_in;
238 	float * const * a_o = self->a_out;
239 	float mix_t[12], mix[12];
240 	uint32_t fade_i[4] = { 0, 0, 0, 0};
241 	uint32_t fade_o[3] = { 0, 0, 0};
242 	int delay_i[4], delay_o[3];
243 	float flt_z[4], flt_y[4];
244 	float amp_in_t[4], amp_in[4];
245 	int cmode_in[4];
246 	int pmode_in[4];
247 
248 	/* trigger settings*/
249 	int   tt_edgemode = *self->p_trigger_edge;
250 	float tt_level0   = *self->p_trigger_level0;
251 	float tt_level1   = *self->p_trigger_level1;
252 	uint64_t tt_tme0  = *self->p_trigger_time0;
253 	uint64_t tt_tme1  = *self->p_trigger_time1;
254 
255 	float ts_prev = self->ts_prev;
256 	uint64_t ts_time = self->ts_time;
257 	int ts_hysteresis = self->ts_hysteresis;
258 
259 	const uint64_t monotonic_cnt = self->monotonic_cnt;
260 	const uint32_t fade_len = (n_samples >= FADE_LEN) ? FADE_LEN : ceilf(n_samples / 2.f);
261 	const float flt_alpha = self->flt_alpha;
262 	const float mix_alpha = self->mix_alpha;
263 	const int trigger_mode = *self->p_trigger_mode;
264 	const int trigger_chn  = MIN(3, MAX(0, *self->p_trigger_chn));
265 	float tri_alpha = self->tri_alpha;
266 
267 	if (trigger_mode != self->tri_mode_prev)  {
268 		self->tri_mode_prev= trigger_mode;
269 		ts_time = 0;
270 		ts_hysteresis = 0;
271 		switch(trigger_mode) {
272 			case TRG_PULSETRAIN:
273 			case TRG_DROPOUT:
274 				ts_time = 1e18;
275 				break;
276 			default:
277 				ts_time = 0;
278 				break;
279 		}
280 	}
281 
282 	if ((trigger_mode == TRG_LPF || trigger_mode == TRG_RMS) && self->tri_t0 != tt_tme0) {
283 		self->tri_t0 = tt_tme0;
284 		if (tt_tme0 > self->rate) {
285 			self->tri_alpha = 1.0f;
286 		} else {
287 			if (tt_tme0 < 1) tt_tme0 = 1;
288 			self->tri_alpha = 1.0f - expf(-2.0 * M_PI * (float)tt_tme0 / self->rate);
289 		}
290 		tri_alpha = self->tri_alpha;
291 	}
292 
293 	for (uint32_t i = 0; i < 12; ++i) {
294 		mix_t[i] = *(self->p_mix[i]);
295 		mix[i] = self->mix_z[i];
296 	}
297 
298 	for (uint32_t i = 0; i < 4; ++i) {
299 		flt_z[i] = self->flt_z[i];
300 		flt_y[i] = self->flt_y[i];
301 		cmode_in[i] = *(self->p_input[i]);
302 		pmode_in[i] = self->mode_input[i];
303 		amp_in_t[i] = self->gain_in[i];
304 		amp_in[i] = self->amp_z[i];
305 
306 		delay_i[i] = *(self->p_delay[i]);
307 		if (delay_i[i] != self->dly_i[i].c_dly) {
308 			/* input delay time changed */
309 			fade_i[i] = fade_len;
310 		}
311 		if (self->gain_db[i] != *(self->p_gain_in[i])) {
312 			/* recalc gain only if changed */
313 			self->gain_db[i] = *(self->p_gain_in[i]);
314 			self->gain_in[i] = pow(10, .05 * self->gain_db[i]);
315 		}
316 	}
317 
318 	for (uint32_t i = 0; i < 3; ++i) {
319 		delay_o[i] = *(self->p_delay[i+4]);
320 		if (delay_o[i] != self->dly_o[i].c_dly) {
321 			/* output delay-time changed */
322 			fade_o[i] = fade_len;
323 		}
324 	}
325 
326 	/* process every sample */
327 	for (uint32_t n = 0; n < n_samples; ++n) {
328 		float d_i[4], d_o[4], ain[4];
329 
330 #define DELAYLINE_INC(IN, OUT, IO, CHN) \
331 		self->dly_ ## IO[CHN].r_ptr = (self->dly_ ## IO[CHN].r_ptr + 1) % MAXDELAY; \
332 		self->dly_ ## IO[CHN].w_ptr = (self->dly_ ## IO[CHN].w_ptr + 1) % MAXDELAY;
333 
334 #define DELAYLINE_STEP(IN, OUT, IO, CHN) \
335 		if (fade_ ## IO[CHN] > 0 && n < 2 * fade_ ## IO[CHN]) { \
336 			if (n < fade_ ## IO[CHN]) { \
337 				/* fade out previous signal */ \
338 				const float gain = (float)(fade_ ## IO[CHN] - n) / (float)fade_ ## IO[CHN]; \
339 				self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].w_ptr ] = IN; \
340 				OUT = self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].r_ptr ] * gain; \
341 				DELAYLINE_INC(IN, OUT, IO, CHN) \
342 			} else \
343 			if (n == fade_ ## IO[CHN]) { \
344 				/* switch read pointer */ \
345 				self->dly_ ## IO[CHN].r_ptr += self->dly_ ## IO[CHN].c_dly - delay_ ## IO[CHN]; \
346 				if (self->dly_ ## IO[CHN].r_ptr < 0) { \
347 					self->dly_ ## IO[CHN].r_ptr -= MAXDELAY * floor(self->dly_ ## IO[CHN].r_ptr / (float)MAXDELAY); \
348 				} \
349 				self->dly_ ## IO[CHN].r_ptr = self->dly_ ## IO[CHN].r_ptr % MAXDELAY; \
350 				self->dly_ ## IO[CHN].c_dly = delay_ ## IO[CHN]; \
351 				OUT = 0; \
352 			} \
353 			if (n >= fade_ ## IO[CHN]) { \
354 				/* fade in at new position */ \
355 				const float gain = (float)(n - fade_ ## IO[CHN]) / (float)fade_ ## IO[CHN]; \
356 				self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].w_ptr ] = IN; \
357 				OUT = self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].r_ptr ] * gain; \
358 				DELAYLINE_INC(IN, OUT, IO, CHN) \
359 			} \
360 		} else { \
361 			self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].w_ptr ] = IN; \
362 			OUT = self->dly_ ## IO[CHN].buffer[ self->dly_ ## IO[CHN].r_ptr ]; \
363 			DELAYLINE_INC(IN, OUT, IO, CHN) \
364 		}
365 
366 #define PREFILTER(IN, OUT, CHN) \
367 		flt_y[CHN] = flt_alpha * (flt_y[CHN] + IN[CHN] - flt_z[CHN]); \
368 		flt_z[CHN] = IN[CHN]; \
369 		switch(cmode_in[CHN]) { \
370 			case 0: OUT[CHN] = IN[CHN]; break; \
371 			case 2: OUT[CHN] = flt_y[CHN]; break; \
372 			default: OUT[CHN] = 0; break; \
373 		} \
374 		if (cmode_in[CHN] != pmode_in[CHN] && n < fade_len) { \
375 			const float gain = (float)(fade_len - n) / fade_len; \
376 			switch(pmode_in[CHN]) { \
377 				case 0: OUT[CHN] = IN[CHN] * gain; break; \
378 				case 2: OUT[CHN] = flt_y[CHN] * gain; break; \
379 				default: OUT[CHN] = 0; break; \
380 			} \
381 		} \
382 		else if (cmode_in[CHN] != pmode_in[CHN] && n < 2 * fade_len) { \
383 			const float gain = (float)(n - fade_len) / fade_len; \
384 			OUT[CHN] *= gain; \
385 		} \
386 		amp_in[CHN] += mix_alpha * (amp_in_t[CHN] - amp_in[CHN]); \
387 		OUT[CHN] *= amp_in[CHN];
388 
389 		/* input delaylines */
390 		DELAYLINE_STEP(a_i[0][n], ain[0], i, 0)
391 		DELAYLINE_STEP(a_i[1][n], ain[1], i, 1)
392 		DELAYLINE_STEP(a_i[2][n], ain[2], i, 2)
393 		DELAYLINE_STEP(a_i[3][n], ain[3], i, 3)
394 
395 		/* filter | mute */
396 		PREFILTER(ain, d_i, 0)
397 		PREFILTER(ain, d_i, 1)
398 		PREFILTER(ain, d_i, 2)
399 		PREFILTER(ain, d_i, 3)
400 
401 		bool clear = true;
402 		const float tin = d_i[trigger_chn];
403 
404 		/* process trigger */
405 		switch (trigger_mode) {
406 			case TRG_EDGE:
407 				if (edge_trigger(tt_edgemode, tt_level0, ts_prev, tin)) {
408 					a_o[3][n] = FIRE_TRIGGER;
409 					clear = false;
410 				}
411 				ts_prev = tin;
412 				break;
413 			case TRG_LTC:
414 				ltc_decoder_write_float(self->decoder, &d_i[trigger_chn], 1, n + monotonic_cnt);
415 				break;
416 			case TRG_PULSEWIDTH:
417 				/* - prev. edge-trigger is between min,max time ago
418 				 * % trigger-level, edge-mode, time min,max
419 				 */
420 				if (edge_trigger(tt_edgemode, tt_level0, ts_prev, tin)) {
421 					if (monotonic_cnt + n >= ts_time + tt_tme0 && monotonic_cnt + n <= ts_time + tt_tme1) {
422 						a_o[3][n] = FIRE_TRIGGER;
423 						clear = false;
424 					}
425 					ts_time = monotonic_cnt + n;
426 				}
427 				ts_prev = tin;
428 				break;
429 			case TRG_PULSETRAIN:
430 				/* - no trigger for a given time (max)
431 				 * - more than one trigger for given time (min)
432 				 * % trigger-level, edge-mode, time min,max
433 				 */
434 				if (edge_trigger(tt_edgemode, tt_level0, ts_prev, tin)) {
435 					if (monotonic_cnt + n < ts_time + tt_tme0) {
436 						a_o[3][n] = FIRE_TRIGGER;
437 						clear = false;
438 					}
439 					ts_time = monotonic_cnt + n;
440 				}
441 				if (monotonic_cnt + n > ts_time + tt_tme1 ) {
442 					a_o[3][n] = FIRE_TRIGGER;
443 					ts_time = 1e18; // XXX screws up above < tme0 !?
444 					clear = false;
445 				}
446 				ts_prev = tin;
447 				break;
448 			case TRG_WINDOW_ENTER:
449 				/* - fire is signal enters a given range
450 				 * % trigger-level A, trigger-level B, enter||leave
451 				 */
452 				{
453 					const int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
454 					if ((rt&4) == 0 && (rt & tt_edgemode) != 0) {
455 						a_o[3][n] = FIRE_TRIGGER;
456 						clear = false;
457 					}
458 				}
459 				ts_prev = tin;
460 				break;
461 			case TRG_WINDOW_LEAVE:
462 				/* - fire is signal leaves a certain range
463 				 * % trigger-level A, trigger-level B, enter||leave
464 				 */
465 				{
466 					const int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
467 					if ((rt&4) == 4 && (rt & tt_edgemode) != 0) {
468 						a_o[3][n] = FIRE_TRIGGER;
469 						clear = false;
470 					}
471 				}
472 				ts_prev = tin;
473 				break;
474 			case TRG_DROPOUT:
475 				/* - fire is signal leaves a given range for at least a given time
476 				 * % trigger-level A, trigger-level B, enter||leave, timeout
477 				 */
478 				{
479 					const int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
480 					if ((rt&4) == 4 && (rt & tt_edgemode) != 0) {
481 						ts_time = monotonic_cnt + n;
482 					}
483 				}
484 				if (monotonic_cnt + n > ts_time + tt_tme0) {
485 					a_o[3][n] = FIRE_TRIGGER;
486 					ts_time = 1e18;
487 					clear = false;
488 				}
489 				ts_prev = tin;
490 				break;
491 			case TRG_DROPIN:
492 				/* - fire is signal enters a given range for at least a given time
493 				 * % trigger-level A, trigger-level B, enter||leave, timeout
494 				 */
495 				{
496 					const int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
497 					if ((rt&4) == 0 && (rt & tt_edgemode) != 0) {
498 						// in range -- start counting (if not counting already)
499 						if (ts_time == 0) {
500 							ts_time = monotonic_cnt + n;
501 						}
502 					} else if (rt&4) {
503 						// out of range -- reset count
504 						ts_time = 0;
505 					}
506 				}
507 				if (ts_time > 0 && monotonic_cnt + n >= ts_time + tt_tme0) {
508 					a_o[3][n] = FIRE_TRIGGER;
509 					ts_time = 1e18;
510 					clear = false;
511 				}
512 				ts_prev = tin;
513 				break;
514 			case TRG_HYSTERESIS:
515 				/* - fire if signal cross both min,max in same direction w/o interruption
516 				 * % trigger-level A, trigger-level B, edge-mode
517 				 */
518 				// TODO: consolidate calls to edge_trigger()
519 				if (tt_edgemode & 1) { // rising edge
520 					if ((ts_hysteresis & 1) == 0) {
521 						// check first edge
522 						if (edge_trigger(1, tt_level0, ts_prev, tin)) {
523 							ts_hysteresis |= 1;
524 						}
525 					}
526 					else if ((ts_hysteresis & 1) == 1) {
527 						// check 2nd edge -- or inverse 1st edge -> reset
528 						if (edge_trigger(1, tt_level1, ts_prev, tin)) {
529 							// fire
530 							ts_hysteresis &= ~1;
531 							a_o[3][n] = FIRE_TRIGGER;
532 							clear = false;
533 						}
534 						else
535 						if (edge_trigger(2, tt_level0, ts_prev, tin)) {
536 							ts_hysteresis &= ~1;
537 						}
538 					}
539 				}
540 
541 				if (tt_edgemode & 2) { // falling edge
542 					if ((ts_hysteresis & 2) == 0) {
543 						// check first edge
544 						if (edge_trigger(2, tt_level1, ts_prev, tin)) {
545 							ts_hysteresis |= 2;
546 						}
547 					}
548 					else if ((ts_hysteresis & 2) == 2) {
549 						// check 2nd edge -- or inverse 1st edge -> reset
550 						if (edge_trigger(2, tt_level0, ts_prev, tin)) {
551 							// fire
552 							ts_hysteresis &= ~2;
553 							a_o[3][n] = FIRE_TRIGGER;
554 							clear = false;
555 						}
556 						else
557 						if (edge_trigger(1, tt_level1, ts_prev, tin)) {
558 							ts_hysteresis &= ~2;
559 						}
560 					}
561 				}
562 				ts_prev = tin;
563 				break;
564 			case TRG_RUNT:
565 				/* - fire is signal crosses 1st but not 2nd threshold
566 				 * % trigger-level A, trigger-level B, edge-direction(s)
567 				 */
568 				if (tt_edgemode & 1) { // rising edge
569 					if ((ts_hysteresis & 1) == 0) {
570 						// check first edge
571 						if (edge_trigger(1, tt_level0, ts_prev, tin)) {
572 							ts_hysteresis |= 1;
573 						}
574 					}
575 					else if ((ts_hysteresis & 1) == 1) {
576 						int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
577 						//assert (rt & 4);
578 						if (rt & 2) {
579 							ts_hysteresis &= ~1;
580 							a_o[3][n] = FIRE_TRIGGER;
581 						} else if (rt & 1) {
582 							ts_hysteresis &= ~1;
583 						}
584 					}
585 				}
586 				if (tt_edgemode & 2) { // falling edge
587 					if ((ts_hysteresis & 2) == 0) {
588 						// check first edge
589 						if (edge_trigger(2, tt_level1, ts_prev, tin)) {
590 							ts_hysteresis |= 2;
591 						}
592 					}
593 					else if ((ts_hysteresis & 2) == 2) {
594 						int rt = range_trigger(tt_level0, tt_level1, ts_prev, tin);
595 						//assert (rt & 4);
596 						if (rt & 1) {
597 							ts_hysteresis &= ~2;
598 							a_o[3][n] = FIRE_TRIGGER;
599 							clear = false;
600 						} else if (rt & 2) {
601 							ts_hysteresis &= ~2;
602 						}
603 					}
604 				}
605 				ts_prev = tin;
606 				break;
607 			case TRG_RMS:
608 				ts_prev += tri_alpha * ((tin * tin) - ts_prev);
609 				a_o[3][n] = sqrtf(ts_prev);
610 				clear = false;
611 				break;
612 			case TRG_LPF:
613 				ts_prev += tri_alpha * (tin - ts_prev);
614 				a_o[3][n] = ts_prev;
615 				clear = false;
616 				break;
617 			default:
618 				a_o[3][n] = tin;
619 				clear = false;
620 				break;
621 		}
622 		if (clear) {
623 			a_o[3][n] = 0;
624 		}
625 
626 		for (uint32_t i = 0; i < 12; ++i) {
627 			/* low-pass filter gain */
628 			mix[i] += mix_alpha * (mix_t[i] - mix[i]);
629 		}
630 
631 		/* mix matrix */
632 		d_o[0] = d_i[0] * mix[0] + d_i[1] * mix[3] + d_i[2] * mix[6] + d_i[3] * mix[ 9];
633 		d_o[1] = d_i[0] * mix[1] + d_i[1] * mix[4] + d_i[2] * mix[7] + d_i[3] * mix[10];
634 		d_o[2] = d_i[0] * mix[2] + d_i[1] * mix[5] + d_i[2] * mix[8] + d_i[3] * mix[11];
635 
636 		/* output delaylines */
637 		DELAYLINE_STEP(d_o[0], a_o[0][n], o, 0)
638 		DELAYLINE_STEP(d_o[1], a_o[1][n], o, 1)
639 		DELAYLINE_STEP(d_o[2], a_o[2][n], o, 2)
640 	}
641 
642 	/* post-process trigger */
643 	switch (trigger_mode) {
644 		case TRG_LTC:
645 			{
646 				LTCFrameExt frame;
647 				while (ltc_decoder_read(self->decoder,&frame)) {
648 					const uint64_t ltc_end = frame.off_end;
649 					if (ltc_end >= monotonic_cnt && ltc_end < monotonic_cnt + n_samples) {
650 						const int nf = frame.off_end - monotonic_cnt;
651 						a_o[3][nf] = FIRE_TRIGGER;
652 					}
653 				}
654 			}
655 			break;
656 		case TRG_LPF:
657 			if (isfinite(ts_prev)) {
658 				ts_prev += 1e-20;
659 			} else {
660 				ts_prev = 0;
661 			}
662 			break;
663 		default:
664 			break;
665 	}
666 
667 	/* copy back filter vars */
668 	for (uint32_t i = 0; i < 4; ++i) {
669 		self->flt_z[i] = flt_z[i];
670 		if (isfinite(flt_y[i])) {
671 			self->flt_y[i] = flt_y[i];
672 		} else {
673 			self->flt_y[i] = 0;
674 		}
675 
676 		if (isfinite(amp_in[i])
677 				&& fabsf(amp_in[i]) > 0.0001 /* -80dB */) {
678 			self->amp_z[i] = amp_in[i] + 1e-20;
679 		} else {
680 			self->amp_z[i] = 0;
681 		}
682 
683 		self->mode_input[i] = cmode_in[i];
684 	}
685 
686 	for (uint32_t i = 0; i < 12; ++i) {
687 		if (isfinite(mix[i])
688 				&& fabsf(mix[i]) > 0.0001 /* -80dB */) {
689 			self->mix_z[i] = mix[i] + 1e-20;
690 		} else {
691 			self->mix_z[i] = 0;
692 		}
693 	}
694 	self->monotonic_cnt += n_samples;
695 	self->ts_time = ts_time;
696 	self->ts_prev = ts_prev;
697 	self->ts_hysteresis = ts_hysteresis;
698 }
699 
700 static void
cleanup_mixtri(LV2_Handle handle)701 cleanup_mixtri(LV2_Handle handle)
702 {
703 	MixTri* self = (MixTri*)handle;
704 	ltc_decoder_free(self->decoder);
705 	free(handle);
706 }
707 
708 
709 #ifdef MIXTRILV2
710 /******************************************************************************
711  * LV2 setup
712  */
713 
714 const void*
extension_data(const char * uri)715 extension_data(const char* uri)
716 {
717 	return NULL;
718 }
719 
720 #define mkdesc_mixtri(ID, NAME) \
721 static const LV2_Descriptor descriptor ## ID = { \
722 	MIXTRI_URI NAME,     \
723 	instantiate_mixtri,  \
724 	connect_port_mixtri, \
725 	NULL,                \
726 	run_mixtri,          \
727 	NULL,                \
728 	cleanup_mixtri,      \
729 	extension_data       \
730 };
731 
732 mkdesc_mixtri(0, "lv2")
733 mkdesc_mixtri(1, "lv2_gtk")
734 
735 #undef LV2_SYMBOL_EXPORT
736 #ifdef _WIN32
737 #    define LV2_SYMBOL_EXPORT __declspec(dllexport)
738 #else
739 #    define LV2_SYMBOL_EXPORT  __attribute__ ((visibility ("default")))
740 #endif
741 LV2_SYMBOL_EXPORT
742 const LV2_Descriptor*
lv2_descriptor(uint32_t index)743 lv2_descriptor(uint32_t index)
744 {
745 	switch (index) {
746 		case  0: return &descriptor0;
747 		case  1: return &descriptor1;
748 		default: return NULL;
749 	}
750 }
751 #endif
752 
753 /* vi:set ts=2 sts=2 sw=2: */
754