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