2 * Small modules for modular synthesizers
4 * Copyright (C) 2001-2008 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
24 #include <calf/primitives.h>
25 #include <calf/biquad.h>
26 #include <calf/inertia.h>
27 #include <calf/audio_fx.h>
28 #include <calf/plugininfo.h>
29 #include <calf/giface.h>
30 #include <calf/lv2wrap.h>
32 #include <calf/modules_small.h>
33 #include <calf/lv2helpers.h>
35 #ifdef ENABLE_EXPERIMENTAL
38 #define LV2_SMALL_WRAPPER(mod, name) static calf_plugins::lv2_small_wrapper<small_plugins::mod##_audio_module> lv2_small_##mod(name);
40 #define LV2_SMALL_WRAPPER(...)
43 #define SMALL_WRAPPERS(mod, name) LV2_SMALL_WRAPPER(mod, name)
47 using namespace calf_plugins
;
51 template<class Module
> LV2_Descriptor lv2_small_wrapper
<Module
>::descriptor
;
52 template<class Module
> uint32_t lv2_small_wrapper
<Module
>::poly_port_types
;
54 namespace small_plugins
57 class filter_base
: public null_small_audio_module
60 enum { in_signal
, in_cutoff
, in_resonance
, in_count
};
61 enum { out_signal
, out_count
};
63 float *outs
[out_count
];
64 static void port_info(plugin_info_iface
*pii
)
66 pii
->audio_port("in", "In").input();
67 pii
->control_port("cutoff", "Cutoff", 1000).input().log_range(20, 20000);
68 pii
->control_port("res", "Resonance", 0.707).input().log_range(0.707, 20);
69 pii
->audio_port("out", "Out").output();
71 dsp::biquad_d1
<float> filter
;
76 inline void process_inner(uint32_t count
) {
77 for (uint32_t i
= 0; i
< count
; i
++)
78 outs
[out_signal
][i
] = filter
.process(ins
[in_signal
][i
]);
83 class lp_filter_audio_module
: public filter_base
86 inline void process(uint32_t count
) {
87 filter
.set_lp_rbj(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), *ins
[in_resonance
], srate
);
90 static void plugin_info(plugin_info_iface
*pii
)
92 pii
->names("lowpass12", "12dB/oct RBJ Lowpass", "lv2:LowpassPlugin");
97 class hp_filter_audio_module
: public filter_base
100 inline void process(uint32_t count
) {
101 filter
.set_hp_rbj(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), *ins
[in_resonance
], srate
);
102 process_inner(count
);
104 static void plugin_info(plugin_info_iface
*pii
)
106 pii
->names("highpass12", "12dB/oct RBJ Highpass", "lv2:HighpassPlugin");
111 class bp_filter_audio_module
: public filter_base
114 inline void process(uint32_t count
) {
115 filter
.set_bp_rbj(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), *ins
[in_resonance
], srate
);
116 process_inner(count
);
118 static void plugin_info(plugin_info_iface
*pii
)
120 pii
->names("bandpass6", "6dB/oct RBJ Bandpass", "lv2:BandpassPlugin");
125 class br_filter_audio_module
: public filter_base
128 inline void process(uint32_t count
) {
129 filter
.set_br_rbj(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), *ins
[in_resonance
], srate
);
130 process_inner(count
);
132 static void plugin_info(plugin_info_iface
*pii
)
134 pii
->names("notch6", "6dB/oct RBJ Bandpass", "lv2:FilterPlugin");
139 class onepole_filter_base
: public null_small_audio_module
142 enum { in_signal
, in_cutoff
, in_count
};
143 enum { out_signal
, out_count
};
144 float *ins
[in_count
];
145 float *outs
[out_count
];
146 dsp::onepole
<float> filter
;
147 static parameter_properties param_props
[];
149 static void port_info(plugin_info_iface
*pii
)
151 pii
->audio_port("In", "in").input();
152 pii
->control_port("Cutoff", "cutoff", 1000).input().log_range(20, 20000);
153 pii
->audio_port("Out", "out").output();
155 /// do not export mode and inertia as CVs, as those are settings and not parameters
161 class onepole_lp_filter_audio_module
: public onepole_filter_base
164 void process(uint32_t count
) {
165 filter
.set_lp(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), srate
);
166 for (uint32_t i
= 0; i
< count
; i
++)
167 outs
[0][i
] = filter
.process_lp(ins
[0][i
]);
170 static void plugin_info(plugin_info_iface
*pii
)
172 pii
->names("lowpass6", "6dB/oct Lowpass Filter", "lv2:LowpassPlugin");
177 class onepole_hp_filter_audio_module
: public onepole_filter_base
180 void process(uint32_t count
) {
181 filter
.set_hp(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), srate
);
182 for (uint32_t i
= 0; i
< count
; i
++)
183 outs
[0][i
] = filter
.process_hp(ins
[0][i
]);
186 static void plugin_info(plugin_info_iface
*pii
)
188 pii
->names("highpass6", "6dB/oct Highpass Filter", "lv2:HighpassPlugin");
193 class onepole_ap_filter_audio_module
: public onepole_filter_base
196 void process(uint32_t count
) {
197 filter
.set_ap(clip
<float>(*ins
[in_cutoff
], 0.0001, 0.48 * srate
), srate
);
198 for (uint32_t i
= 0; i
< count
; i
++)
199 outs
[0][i
] = filter
.process_ap(ins
[0][i
]);
202 static void plugin_info(plugin_info_iface
*pii
)
204 pii
->names("allpass", "1-pole 1-zero Allpass Filter", "lv2:AllpassPlugin");
209 /// This works for 1 or 2 operands only...
211 class audio_operator_audio_module
: public small_audio_module_base
<Inputs
, 1>
214 static void port_info(plugin_info_iface
*pii
)
217 pii
->audio_port("in", "In", "").input();
220 pii
->audio_port("in_1", "In 1", "").input();
221 pii
->audio_port("in_2", "In 2", "").input();
223 pii
->audio_port("out", "Out", "").output();
227 class min_audio_module
: public audio_operator_audio_module
<2>
230 void process(uint32_t count
) {
231 for (uint32_t i
= 0; i
< count
; i
++)
232 outs
[0][i
] = std::min(ins
[0][i
], ins
[1][i
]);
234 static void plugin_info(plugin_info_iface
*pii
)
236 pii
->names("min", "Minimum (A)", "kf:MathOperatorPlugin", "min");
241 class max_audio_module
: public audio_operator_audio_module
<2>
244 void process(uint32_t count
) {
245 for (uint32_t i
= 0; i
< count
; i
++)
246 outs
[0][i
] = std::max(ins
[0][i
], ins
[1][i
]);
248 static void plugin_info(plugin_info_iface
*pii
)
250 pii
->names("max", "Maximum (A)", "kf:MathOperatorPlugin", "max");
255 class minus_audio_module
: public audio_operator_audio_module
<2>
258 void process(uint32_t count
) {
259 for (uint32_t i
= 0; i
< count
; i
++)
260 outs
[0][i
] = ins
[0][i
] - ins
[1][i
];
262 static void plugin_info(plugin_info_iface
*pii
)
264 pii
->names("minus", "Subtract (A)", "kf:MathOperatorPlugin", "-");
269 class mul_audio_module
: public audio_operator_audio_module
<2>
272 void process(uint32_t count
) {
273 for (uint32_t i
= 0; i
< count
; i
++)
274 outs
[0][i
] = ins
[0][i
] * ins
[1][i
];
276 static void plugin_info(plugin_info_iface
*pii
)
278 pii
->names("mul", "Multiply (A)", "kf:MathOperatorPlugin", "*");
283 class neg_audio_module
: public audio_operator_audio_module
<1>
286 void process(uint32_t count
) {
287 for (uint32_t i
= 0; i
< count
; i
++)
288 outs
[0][i
] = -ins
[0][i
];
290 static void plugin_info(plugin_info_iface
*pii
)
292 pii
->names("neg", "Negative (A)", "kf:MathOperatorPlugin", "-");
297 template<class T
, int Inputs
> struct polymorphic_process
;
299 template<class T
> struct polymorphic_process
<T
, 1>
301 static inline void run(float **ins
, float **outs
, uint32_t count
, uint32_t poly_port_types
) {
302 if (poly_port_types
< 2) // control to control or audio to control
303 *outs
[0] = T::process_single(*ins
[0]);
304 else if (poly_port_types
== 2) {
305 outs
[0][0] = T::process_single(ins
[0][0]); // same as above, but the index might not be 0 in later versions
306 for (uint32_t i
= 1; i
< count
; i
++)
307 outs
[0][i
] = outs
[0][0];
309 else { // audio to audio
310 for (uint32_t i
= 0; i
< count
; i
++)
311 outs
[0][i
] = T::process_single(ins
[0][i
]);
316 template<class T
> struct polymorphic_process
<T
, 2>
318 static inline void run(float **ins
, float **outs
, uint32_t count
, uint32_t poly_port_types
) {
319 poly_port_types
&= ~1;
320 if (poly_port_types
< 4) // any to control
321 *outs
[0] = T::process_single(*ins
[0], *ins
[1]);
322 else if (poly_port_types
== 4) { // control+control to audio
323 outs
[0][0] = T::process_single(*ins
[0], *ins
[1]); // same as above, but the index might not be 0 in later versions
324 for (uint32_t i
= 1; i
< count
; i
++)
325 outs
[0][i
] = outs
[0][0];
327 else { // {control+audio or audio+control or audio+audio} to audio
328 // use masks to force 0 for index for control ports
329 uint32_t mask1
= null_small_audio_module::port_audio_mask(0, poly_port_types
);
330 uint32_t mask2
= null_small_audio_module::port_audio_mask(1, poly_port_types
);
331 for (uint32_t i
= 0; i
< count
; i
++)
332 outs
[0][i
] = T::process_single(ins
[0][i
& mask1
], ins
[1][i
& mask2
]);
337 /// This works for 1 or 2 operands only...
339 class control_operator_audio_module
: public small_audio_module_base
<Inputs
, 1>
342 using small_audio_module_base
<Inputs
, 1>::ins
;
343 using small_audio_module_base
<Inputs
, 1>::outs
;
344 using small_audio_module_base
<Inputs
, 1>::poly_port_types
;
345 static void port_info(plugin_info_iface
*pii
, control_port_info_iface
*cports
[Inputs
+ 1], float in1
= 0, float in2
= 0)
349 cports
[idx
++] = &pii
->control_port("in", "In", in1
, "").polymorphic().poly_audio().input();
352 cports
[idx
++] = &pii
->control_port("in_1", "In 1", in1
, "").polymorphic().poly_audio().input();
353 cports
[idx
++] = &pii
->control_port("in_2", "In 2", in2
, "").polymorphic().poly_audio().input();
355 cports
[idx
++] = &pii
->control_port("out", "Out", 0, "").poly_audio().output();
358 template<class T
> inline void do_process(uint32_t count
) {
359 polymorphic_process
<T
, Inputs
>::run(ins
, outs
, count
, poly_port_types
);
363 class minus_c_audio_module
: public control_operator_audio_module
<2>
366 static inline float process_single(float x
, float y
) {
369 void process(uint32_t count
) {
370 do_process
<minus_c_audio_module
>(count
);
372 static void plugin_info(plugin_info_iface
*pii
)
374 pii
->names("minus_c", "Subtract (C)", "kf:MathOperatorPlugin", "-");
375 control_port_info_iface
*cports
[3];
376 port_info(pii
, cports
);
380 class mul_c_audio_module
: public control_operator_audio_module
<2>
383 static inline float process_single(float x
, float y
) {
386 void process(uint32_t count
) {
387 do_process
<mul_c_audio_module
>(count
);
389 static void plugin_info(plugin_info_iface
*pii
)
391 pii
->names("mul_c", "Multiply (C)", "kf:MathOperatorPlugin", "*");
392 control_port_info_iface
*cports
[3];
393 port_info(pii
, cports
);
397 class neg_c_audio_module
: public control_operator_audio_module
<1>
400 static inline float process_single(float x
) {
403 void process(uint32_t count
) {
404 do_process
<neg_c_audio_module
>(count
);
406 static void plugin_info(plugin_info_iface
*pii
)
408 pii
->names("neg_c", "Negative (C)", "kf:MathOperatorPlugin", "-");
409 control_port_info_iface
*cports
[2];
410 port_info(pii
, cports
);
414 class min_c_audio_module
: public control_operator_audio_module
<2>
417 static inline float process_single(float x
, float y
) {
418 return std::min(x
, y
);
420 void process(uint32_t count
) {
421 do_process
<min_c_audio_module
>(count
);
423 static void plugin_info(plugin_info_iface
*pii
)
425 pii
->names("min_c", "Minimum (C)", "kf:MathOperatorPlugin", "min");
426 control_port_info_iface
*cports
[3];
427 port_info(pii
, cports
);
431 class max_c_audio_module
: public control_operator_audio_module
<2>
434 static inline float process_single(float x
, float y
) {
435 return std::max(x
, y
);
437 void process(uint32_t count
) {
438 do_process
<max_c_audio_module
>(count
);
440 static void plugin_info(plugin_info_iface
*pii
)
442 pii
->names("max_c", "Maximum (C)", "kf:MathOperatorPlugin", "max");
443 control_port_info_iface
*cports
[3];
444 port_info(pii
, cports
);
448 class less_c_audio_module
: public control_operator_audio_module
<2>
451 static inline float process_single(float x
, float y
) {
454 void process(uint32_t count
) {
455 do_process
<less_c_audio_module
>(count
);
457 static void plugin_info(plugin_info_iface
*pii
)
459 pii
->names("less_c", "Less than (C)", "kf:MathOperatorPlugin", "<");
460 control_port_info_iface
*cports
[2];
461 port_info(pii
, cports
);
466 class level2edge_c_audio_module
: public control_operator_audio_module
<1>
473 void process(uint32_t count
) {
474 *outs
[0] = (*ins
[0] > 0 && !last_value
) ? 1.f
: 0.f
;
475 last_value
= *ins
[0] > 0;
477 static void plugin_info(plugin_info_iface
*pii
)
479 pii
->names("level2edge_c", "Level to edge (C)", "kf:BooleanPlugin");
480 control_port_info_iface
*cports
[2];
481 port_info(pii
, cports
);
483 cports
[1]->toggle().trigger();
487 class int_c_audio_module
: public control_operator_audio_module
<1>
490 static inline float process_single(float x
) {
493 void process(uint32_t count
) {
494 do_process
<int_c_audio_module
>(count
);
496 static void plugin_info(plugin_info_iface
*pii
)
498 pii
->names("int_c", "Integer value (C)", "kf:IntegerPlugin");
499 control_port_info_iface
*cports
[2];
500 port_info(pii
, cports
);
501 cports
[0]->integer();
502 cports
[1]->integer();
506 class bitwise_op_c_module_base
: public control_operator_audio_module
<2>
509 static void port_info(plugin_info_iface
*pii
)
511 pii
->control_port("in_1", "In 1", 0, "").polymorphic().poly_audio().integer().input();
512 pii
->control_port("in_2", "In 2", 0, "").polymorphic().poly_audio().integer().input();
513 pii
->control_port("out", "Out", 0, "").polymorphic().poly_audio().integer().output();
516 class bit_and_c_audio_module
: public bitwise_op_c_module_base
519 static inline float process_single(float x
, float y
) {
520 return ((int)x
) & ((int)y
);
522 void process(uint32_t count
) {
523 do_process
<bit_and_c_audio_module
>(count
);
525 static void plugin_info(plugin_info_iface
*pii
)
527 pii
->names("bit_and_c", "Bitwise AND (C)", "kf:IntegerPlugin");
532 class bit_or_c_audio_module
: public bitwise_op_c_module_base
535 static inline float process_single(float x
, float y
) {
536 return ((int)x
) | ((int)y
);
538 void process(uint32_t count
) {
539 do_process
<bit_or_c_audio_module
>(count
);
541 static void plugin_info(plugin_info_iface
*pii
)
543 pii
->names("bit_or_c", "Bitwise OR (C)", "kf:IntegerPlugin");
548 class bit_xor_c_audio_module
: public bitwise_op_c_module_base
551 static inline float process_single(float x
, float y
) {
552 return ((int)x
) ^ ((int)y
);
554 void process(uint32_t count
) {
555 do_process
<bit_xor_c_audio_module
>(count
);
557 static void plugin_info(plugin_info_iface
*pii
)
559 pii
->names("bit_xor_c", "Bitwise XOR (C)", "kf:IntegerPlugin");
564 class flipflop_c_audio_module
: public control_operator_audio_module
<1>
567 bool last_value
, output
;
572 void process(uint32_t count
) {
573 if (*ins
[0] > 0 && !last_value
)
575 *outs
[0] = output
? 1.f
: 0.f
;
576 last_value
= *ins
[0] > 0;
578 static void plugin_info(plugin_info_iface
*pii
)
580 pii
->names("flipflop_c", "T Flip-Flop (C)", "kf:BooleanPlugin");
581 control_port_info_iface
*cports
[2];
582 port_info(pii
, cports
);
583 cports
[0]->toggle().trigger();
588 class logical_and_c_audio_module
: public control_operator_audio_module
<2>
591 static inline float process_single(float x
, float y
) {
592 return (x
> 0 && y
> 0) ? 1.f
: 0.f
;
594 void process(uint32_t count
) {
595 do_process
<logical_and_c_audio_module
>(count
);
597 static void plugin_info(plugin_info_iface
*pii
)
599 pii
->names("logical_and_c", "Logical AND (C)", "kf:BooleanPlugin", "&&");
600 control_port_info_iface
*cports
[3];
601 port_info(pii
, cports
);
608 class logical_or_c_audio_module
: public control_operator_audio_module
<2>
611 static inline float process_single(float x
, float y
) {
612 return (x
> 0 || y
> 0) ? 1.f
: 0.f
;
614 void process(uint32_t count
) {
615 do_process
<logical_or_c_audio_module
>(count
);
617 static void plugin_info(plugin_info_iface
*pii
)
619 pii
->names("logical_or_c", "Logical OR (C)", "kf:BooleanPlugin", "||");
620 control_port_info_iface
*cports
[3];
621 port_info(pii
, cports
);
628 class logical_xor_c_audio_module
: public control_operator_audio_module
<2>
631 static inline float process_single(float x
, float y
) {
632 return ((x
> 0) != (y
> 0)) ? 1.f
: 0.f
;
634 void process(uint32_t count
) {
635 do_process
<logical_xor_c_audio_module
>(count
);
637 static void plugin_info(plugin_info_iface
*pii
)
639 pii
->names("logical_xor_c", "Logical XOR (C)", "kf:BooleanPlugin", "xor");
640 control_port_info_iface
*cports
[3];
641 port_info(pii
, cports
);
648 class logical_not_c_audio_module
: public control_operator_audio_module
<1>
651 static inline float process_single(float x
) {
652 return (x
<= 0) ? 1.f
: 0.f
;
654 void process(uint32_t count
) {
655 do_process
<logical_not_c_audio_module
>(count
);
657 static void plugin_info(plugin_info_iface
*pii
)
659 pii
->names("logical_not_c", "Logical NOT (C)", "kf:BooleanPlugin", "!");
660 control_port_info_iface
*cports
[2];
661 port_info(pii
, cports
);
667 /// converter of trigger signals from audio to control rate
668 class trigger_a2c_audio_module
: public null_small_audio_module
671 enum { in_count
= 1, out_count
= 1 };
672 float *ins
[in_count
];
673 float *outs
[out_count
];
674 void process(uint32_t count
) {
675 for (uint32_t i
= 0; i
< count
; i
++)
685 static void plugin_info(plugin_info_iface
*pii
)
687 pii
->names("trigger_a2c", "Audio-to-control OR", "kf:BooleanPlugin", "ta2c");
688 pii
->audio_port("in", "In").input();
689 pii
->control_port("out", "Out", 0.f
).output().toggle();
693 /// Monostable multivibrator like 74121 or 74123, with reset input, progress output (0 to 1), "finished" signal, configurable to allow or forbid retriggering.
694 class timer_c_audio_module
: public null_small_audio_module
697 enum { in_trigger
, in_time
, in_reset
, in_allow_retrig
, in_count
};
698 enum { out_running
, out_finished
, out_progress
, out_count
};
699 float *ins
[in_count
];
700 float *outs
[out_count
];
701 bool running
, finished
, old_trigger
;
711 static void plugin_info(plugin_info_iface
*pii
)
713 pii
->names("timer_c", "Timer (C)", "lv2:UtilityPlugin");
714 pii
->control_port("trigger", "Trigger", 0.f
).input().toggle().trigger();
715 pii
->control_port("time", "Time", 0.f
).input();
716 pii
->control_port("reset", "Reset", 0).input().toggle();
717 pii
->control_port("allow_retrig", "Allow retrig", 0).input().toggle();
718 pii
->control_port("running", "Running", 0.f
).output().toggle();
719 pii
->control_port("finished", "Finished", 0.f
).output().toggle();
720 pii
->control_port("progress", "Progress", 0.f
).output().lin_range(0, 1);
722 void process(uint32_t count
)
724 // This is a branch city, which is definitely a bad thing.
725 // Perhaps I'll add a bunch of __builtin_expect hints some day, but somebody would have to start using it first.
726 if (*ins
[in_reset
] > 0)
729 running
= finished
= false;
732 if (!old_trigger
&& *ins
[in_trigger
] > 0 && (!running
|| *ins
[in_allow_retrig
] > 0))
741 float rate
= (1.0 / std::max(0.0000001f
, *ins
[in_time
]));
742 state
+= rate
* odsr
* count
;
750 old_trigger
= *ins
[in_trigger
] > 0;
751 *outs
[out_running
] = running
? 1.f
: 0.f
;
752 *outs
[out_finished
] = finished
? 1.f
: 0.f
;
753 *outs
[out_progress
] = state
;
757 /// 4-input priority multiplexer - without inertia. Outputs the first input if gate_1 is TRUE, else second input if gate_2 is TRUE, else... else "Else" input
758 class prio_mux_c_audio_module
: public null_small_audio_module
761 enum { in_in1
, in_gate1
, in_in2
, in_gate2
, in_in3
, in_gate3
, in_in4
, in_gate4
, in_else
, in_count
};
762 enum { out_value
, out_count
};
763 float *ins
[in_count
];
764 float *outs
[out_count
];
766 static void plugin_info(plugin_info_iface
*pii
)
768 pii
->names("prio_mux_c", "Priority Multiplexer (C)", "kf:BooleanPlugin");
769 for (int i
= 1; i
<= 4; i
++)
773 string num
= numb
.str();
774 pii
->control_port("in_"+num
, "In "+num
, 0.f
).input();
775 pii
->control_port("gate_"+num
, "Gate "+num
, 0.f
).input().toggle();
777 pii
->control_port("in_else", "Else", 0.f
).input();
778 pii
->control_port("out", "Out", 0.f
).output();
780 void process(uint32_t count
)
782 for (int i
= 0; i
< 4; i
++)
784 if (*ins
[i
* 2 + in_gate1
] > 0)
786 *outs
[out_value
] = *ins
[i
* 2 + in_in1
];
790 *outs
[out_value
] = *ins
[in_else
];
794 /// 8-input priority encoder - outputs the index of the first port whose value is >0. 'Any' output is set whenever any of gates is set (which tells
795 /// apart no inputs set and 0th input set).
797 class prio_enc_c_audio_module
: public null_small_audio_module
800 enum { in_gate1
, in_count
= in_gate1
+ N
};
801 enum { out_value
, out_any
, out_count
};
802 float *ins
[in_count
];
803 float *outs
[out_count
];
805 static void plugin_info(plugin_info_iface
*pii
)
807 char buf
[32], buf2
[64];
808 sprintf(buf
, "prio_enc%d_c", N
);
809 sprintf(buf2
, "%d-input Priority Encoder (C)", N
);
810 pii
->names(buf
, buf2
, "kf:IntegerPlugin");
811 for (int i
= 0; i
< N
; i
++)
815 string num
= numb
.str();
816 pii
->control_port("gate_"+num
, "Gate "+num
, 0.f
).input().toggle();
818 pii
->control_port("out", "Out", -1).output().integer();
819 pii
->control_port("any", "Any", -1).output().toggle();
821 void process(uint32_t count
)
823 for (int i
= 0; i
< N
; i
++)
825 if (*ins
[in_gate1
+ i
] > 0)
827 *outs
[out_value
] = i
;
832 *outs
[out_value
] = 0;
837 typedef prio_enc_c_audio_module
<8> prio_enc8_c_audio_module
;
839 /// 8-input integer multiplexer, outputs the input selected by ((int)select input & 7)
841 class mux_c_audio_module
: public null_small_audio_module
844 enum { in_select
, in_in1
, in_count
= in_in1
+ N
};
845 enum { out_value
, out_count
};
846 float *ins
[in_count
];
847 float *outs
[out_count
];
849 static void plugin_info(plugin_info_iface
*pii
)
851 char buf
[32], buf2
[64];
852 sprintf(buf
, "mux%d_c", N
);
853 sprintf(buf2
, "%d-input Multiplexer (C)", N
);
854 pii
->names(buf
, buf2
, "kf:IntegerPlugin");
855 pii
->control_port("select", "Select", 0.f
).input().integer().lin_range(0, N
- 1);
856 for (int i
= 0; i
< N
; i
++)
860 string num
= numb
.str();
861 pii
->control_port("in_"+num
, "In "+num
, 0.f
).input();
863 pii
->control_port("out", "Out", -1).output();
865 void process(uint32_t count
)
867 *outs
[out_value
] = *ins
[in_in1
+ ((N
- 1) & (int)*ins
[in_select
])];
871 typedef mux_c_audio_module
<4> mux4_c_audio_module
;
872 typedef mux_c_audio_module
<8> mux8_c_audio_module
;
873 typedef mux_c_audio_module
<16> mux16_c_audio_module
;
875 /// Linear-to-exponential mapper
876 class map_lin2exp_audio_module
: public null_small_audio_module
879 enum { in_signal
, in_from_min
, in_from_max
, in_to_min
, in_to_max
, in_count
};
880 enum { out_signal
, out_count
};
881 float *ins
[in_count
];
882 float *outs
[out_count
];
884 static void plugin_info(plugin_info_iface
*pii
)
886 pii
->names("lin2exp", "Lin-Exp Mapper", "lv2:UtilityPlugin");
887 pii
->control_port("in", "In", 0.f
).input();
888 pii
->control_port("from_min", "Min (from)", 0).input();
889 pii
->control_port("from_max", "Max (from)", 1).input();
890 pii
->control_port("to_min", "Min (to)", 20).input();
891 pii
->control_port("to_max", "Max (to)", 20000).input();
892 pii
->control_port("out", "Out", 0.f
).output();
894 void process(uint32_t count
)
896 float normalized
= (*ins
[in_signal
] - *ins
[in_from_min
]) / (*ins
[in_from_max
] - *ins
[in_from_min
]);
897 *outs
[out_signal
] = *ins
[in_to_min
] * pow(*ins
[in_to_max
] / *ins
[in_to_min
], normalized
);
901 /// Schmitt trigger - http://en.wikipedia.org/wiki/Schmitt_trigger - also outputs a change signal (positive spike whenever output value is changed)
902 class schmitt_c_audio_module
: public null_small_audio_module
905 enum { in_signal
, in_low
, in_high
, in_count
};
906 enum { out_signal
, out_change
, out_count
};
907 float *ins
[in_count
];
908 float *outs
[out_count
];
915 static void plugin_info(plugin_info_iface
*pii
)
917 pii
->names("schmitt_c", "Schmitt Trigger (C)", "kf:BooleanPlugin");
918 pii
->control_port("in", "In", 0.f
).input();
919 pii
->control_port("low", "Low threshold", 0).input();
920 pii
->control_port("high", "High threshold", 0.5).input();
921 pii
->control_port("out", "Out", 0.f
).output();
922 pii
->control_port("change", "Change", 0.f
).output();
924 void process(uint32_t count
)
926 float value
= *ins
[in_signal
];
927 bool new_state
= state
;
928 if (value
<= *ins
[in_low
])
930 if (value
>= *ins
[in_high
])
932 *outs
[out_signal
] = new_state
? 1.f
: 0.f
;
933 *outs
[out_change
] = (new_state
!= state
) ? 1.f
: 0.f
;
938 /// Stateless 'between' operator (lo <= in <= hi)
939 class between_c_audio_module
: public null_small_audio_module
942 enum { in_signal
, in_low
, in_high
, in_count
};
943 enum { out_signal
, out_count
};
944 float *ins
[in_count
];
945 float *outs
[out_count
];
947 static void plugin_info(plugin_info_iface
*pii
)
949 pii
->names("between_c", "Between (C)", "kf:MathOperatorPlugin");
950 pii
->control_port("in", "In", 0.f
).input();
951 pii
->control_port("low", "Low threshold", 0).input();
952 pii
->control_port("high", "High threshold", 1).input();
953 pii
->control_port("out", "Out", 0.f
).output();
955 void process(uint32_t count
)
957 float value
= *ins
[in_signal
];
958 *outs
[out_signal
] = (value
>= *ins
[in_low
] && value
<= *ins
[in_high
]) ? 1.f
: 0.f
;
963 class clip_c_audio_module
: public null_small_audio_module
966 enum { in_signal
, in_min
, in_max
, in_count
};
967 enum { out_signal
, out_count
};
968 float *ins
[in_count
];
969 float *outs
[out_count
];
971 static void plugin_info(plugin_info_iface
*pii
)
973 pii
->names("clip_c", "Clip (C)", "kf:MathOperatorPlugin", "clip");
974 pii
->control_port("in", "In", 0.f
).input();
975 pii
->control_port("min", "Min", 0).input();
976 pii
->control_port("max", "Max", 1).input();
977 pii
->control_port("out", "Out", 0.f
).output();
979 void process(uint32_t count
)
981 float value
= *ins
[in_signal
];
982 *outs
[out_signal
] = std::min(*ins
[in_max
], std::max(value
, *ins
[in_min
]));
986 /// Two input control crossfader
987 class crossfader2_c_audio_module
: public null_small_audio_module
990 enum { in_a
, in_b
, in_ctl
, in_count
};
991 enum { out_value
, out_count
};
992 float *ins
[in_count
];
993 float *outs
[out_count
];
995 static void plugin_info(plugin_info_iface
*pii
)
997 pii
->names("crossfader2_c", "2-in crossfader (C)", "kf:MathOperatorPlugin", "xfC");
998 pii
->control_port("in_a", "In A", 0.f
).input();
999 pii
->control_port("in_b", "In B", 0).input();
1000 pii
->control_port("mix", "B in mix", 0.5).input();
1001 pii
->control_port("out", "Out", 0.f
).output();
1003 void process(uint32_t count
)
1005 *outs
[out_value
] = *ins
[in_a
] + (*ins
[in_b
] - *ins
[in_a
]) * dsp::clip(*ins
[in_ctl
], 0.f
, 1.f
);
1009 /// 2-input multiplexer (if-then-else)
1010 class ifthenelse_c_audio_module
: public null_small_audio_module
1013 enum { in_if
, in_then
, in_else
, in_count
};
1014 enum { out_value
, out_count
};
1015 float *ins
[in_count
];
1016 float *outs
[out_count
];
1018 static void plugin_info(plugin_info_iface
*pii
)
1020 pii
->names("ifthenelse_c", "If-Then-Else (C)", "kf:BooleanPlugin", "if");
1021 pii
->control_port("if", "If", 0.f
).input().toggle();
1022 pii
->control_port("then", "Then", 0).input();
1023 pii
->control_port("else", "Else", 0).input();
1024 pii
->control_port("out", "Out", 0.f
).output();
1026 void process(uint32_t count
)
1028 *outs
[out_value
] = *ins
[in_if
] > 0 ? *ins
[in_then
] : *ins
[in_else
];
1032 /// Integer counter with definable ranges
1033 class counter_c_audio_module
: public null_small_audio_module
1036 enum { in_clock
, in_min
, in_max
, in_steps
, in_reset
, in_count
};
1037 enum { out_value
, out_carry
, out_count
};
1038 float *ins
[in_count
];
1039 float *outs
[out_count
];
1049 static void plugin_info(plugin_info_iface
*pii
)
1051 pii
->names("counter_c", "Counter (C)", "kf:IntegerPlugin", "cnt");
1052 pii
->control_port("clock", "Clock", 0.f
).input().toggle().trigger();
1053 pii
->control_port("min", "Min", 0).input();
1054 pii
->control_port("max", "Max", 15).input();
1055 pii
->control_port("steps", "Steps", 16).input().integer();
1056 pii
->control_port("reset", "Reset", 0).input().toggle();
1057 pii
->control_port("out", "Out", 0.f
).output();
1058 pii
->control_port("carry", "Carry", 0.f
).output().toggle().trigger();
1060 void process(uint32_t count
)
1062 // Yes, this is slower than it should be. I will bother optimizing it when someone starts actually using it.
1063 if (*ins
[in_reset
] > 0 || *ins
[in_steps
] < 2.0)
1067 *outs
[out_value
] = *ins
[in_min
];
1068 *outs
[out_carry
] = 0.f
;
1071 *outs
[out_carry
] = 0;
1072 if (!state
&& *ins
[in_clock
] > 0)
1076 if (value
>= (int)*ins
[in_steps
])
1079 *outs
[out_carry
] = 1;
1083 state
= *ins
[in_clock
] > 0;
1084 *outs
[out_value
] = *ins
[in_min
] + (*ins
[in_max
] - *ins
[in_min
]) * value
/ (int)(*ins
[in_steps
] - 1);
1088 /// Two input audio crossfader
1089 class crossfader2_a_audio_module
: public null_small_audio_module
1092 enum { in_a
, in_b
, in_ctl
, in_count
};
1093 enum { out_value
, out_count
};
1094 float *ins
[in_count
];
1095 float *outs
[out_count
];
1097 static void plugin_info(plugin_info_iface
*pii
)
1099 pii
->names("crossfader2_a", "2-in crossfader (A)", "kf:MathOperatorPlugin", "xfA");
1100 pii
->audio_port("in_a", "In A").input();
1101 pii
->audio_port("in_b", "In B").input();
1102 pii
->audio_port("mix", "B in mix").input();
1103 pii
->audio_port("out", "Out").output();
1105 void process(uint32_t count
)
1107 for (uint32_t i
= 0; i
< count
; i
++)
1108 outs
[out_value
][i
] = ins
[in_a
][i
] + (ins
[in_b
][i
] - ins
[in_a
][i
]) * dsp::clip(ins
[in_ctl
][i
], 0.f
, 1.f
);
1112 /// Base class for LFOs with frequency and reset inputs
1113 class freq_phase_lfo_base
: public small_audio_module_base
<2, 1>
1116 enum { in_freq
, in_reset
};
1118 inline void activate()
1122 static void port_info(plugin_info_iface
*pii
)
1124 pii
->control_port("freq", "Frequency", 1).input().log_range(0.02, 100);
1125 pii
->control_port("reset", "Reset", 0).input().toggle();
1126 pii
->control_port("out", "Out", 0).output();
1128 inline void check_inputs()
1133 inline void advance(uint32_t count
)
1135 phase
+= count
* *ins
[in_freq
] * odsr
;
1137 phase
= fmod(phase
, 1.0);
1141 class square_lfo_audio_module
: public freq_phase_lfo_base
1144 void process(uint32_t count
)
1147 *outs
[0] = (phase
< 0.5) ? -1 : +1;
1150 static void plugin_info(plugin_info_iface
*pii
)
1152 pii
->names("square_lfo", "Square LFO", "lv2:OscillatorPlugin");
1157 class saw_lfo_audio_module
: public freq_phase_lfo_base
1160 void process(uint32_t count
)
1163 *outs
[0] = -1 + 2 * phase
;
1166 static void plugin_info(plugin_info_iface
*pii
)
1168 pii
->names("saw_lfo", "Saw LFO", "lv2:OscillatorPlugin");
1173 class pulse_lfo_audio_module
: public freq_phase_lfo_base
1176 inline void activate()
1180 void process(uint32_t count
)
1183 double oldphase
= phase
;
1185 *outs
[0] = (phase
< oldphase
) ? 1.f
: 0.f
;
1187 static void plugin_info(plugin_info_iface
*pii
)
1189 pii
->names("pulse_lfo", "Pulse LFO", "lv2:OscillatorPlugin");
1194 #define SMALL_OSC_TABLE_BITS 12
1196 class freq_only_osc_base_common
: public null_small_audio_module
1199 typedef waveform_family
<SMALL_OSC_TABLE_BITS
> waves_type
;
1200 enum { in_freq
, in_count
};
1201 enum { out_signal
, out_count
};
1202 enum { wave_size
= 1 << SMALL_OSC_TABLE_BITS
};
1203 float *ins
[in_count
];
1204 float *outs
[out_count
];
1206 waveform_oscillator
<SMALL_OSC_TABLE_BITS
> osc
;
1208 /// Fill the array with the original, non-bandlimited, waveform
1209 virtual void get_original_waveform(float data
[wave_size
]) = 0;
1210 /// This function needs to be virtual to ensure a separate wave family for each class (but not each instance)
1211 virtual waves_type
*get_waves() = 0;
1213 waves
= get_waves();
1215 void process(uint32_t count
)
1217 osc
.set_freq_odsr(*ins
[in_freq
], odsr
);
1218 osc
.waveform
= waves
->get_level(osc
.phasedelta
);
1221 for (uint32_t i
= 0; i
< count
; i
++)
1222 outs
[out_signal
][i
] = osc
.get();
1225 dsp::zero(outs
[out_signal
], count
);
1227 static void port_info(plugin_info_iface
*pii
)
1229 pii
->control_port("freq", "Frequency", 440).input().log_range(20, 20000);
1230 pii
->audio_port("out", "Out").output();
1232 /// Generate a wave family (bandlimit levels) from the original wave
1233 waves_type
*create_waves() {
1234 waves_type
*ptr
= new waves_type
;
1235 float source
[wave_size
];
1236 get_original_waveform(source
);
1237 bandlimiter
<SMALL_OSC_TABLE_BITS
> bl
;
1238 ptr
->make(bl
, source
);
1244 class freq_only_osc_base
: public freq_only_osc_base_common
1246 virtual waves_type
*get_waves() {
1247 static waves_type
*waves
= NULL
;
1249 waves
= create_waves();
1254 class square_osc_audio_module
: public freq_only_osc_base
<square_osc_audio_module
>
1257 virtual void get_original_waveform(float data
[wave_size
]) {
1258 for (int i
= 0; i
< wave_size
; i
++)
1259 data
[i
] = (i
< wave_size
/ 2) ? +1 : -1;
1261 static void plugin_info(plugin_info_iface
*pii
)
1263 pii
->names("squareosc", "Square Oscillator", "lv2:OscillatorPlugin");
1268 class saw_osc_audio_module
: public freq_only_osc_base
<saw_osc_audio_module
>
1271 virtual void get_original_waveform(float data
[wave_size
]) {
1272 for (int i
= 0; i
< wave_size
; i
++)
1273 data
[i
] = (i
* 2.0 / wave_size
) - 1;
1275 static void plugin_info(plugin_info_iface
*pii
)
1277 pii
->names("sawosc", "Saw Oscillator", "lv2:OscillatorPlugin");
1282 class print_c_audio_module
: public small_audio_module_base
<1, 0>
1285 static void plugin_info(plugin_info_iface
*pii
)
1287 pii
->names("print_c", "Print To Console (C)", "lv2:UtilityPlugin");
1288 pii
->control_port("in", "In", 0).input();
1290 void process(uint32_t)
1292 printf("%f\n", *ins
[0]);
1296 class print_e_audio_module
: public small_audio_module_base
<1, 0>
1299 static void plugin_info(plugin_info_iface
*pii
)
1301 pii
->names("print_e", "Print To Console (E)", "lv2:UtilityPlugin");
1302 pii
->event_port("in", "In").input();
1304 void dump(LV2_Event_Buffer
*event_data
)
1306 event_port_read_iterator
ei(event_data
);
1309 const lv2_event
&event
= *ei
++;
1310 printf("Event at %d.%d, type %d, size %d:", event
.frames
, event
.subframes
, (int)event
.type
, (int)event
.size
);
1311 uint32_t size
= std::min((uint16_t)16, event
.size
);
1313 for (uint32_t j
= 0; j
< size
; j
++)
1314 printf(" %02X", (uint32_t)event
.data
[j
]);
1315 if (event
.size
> size
)
1321 void process(uint32_t)
1323 LV2_Event_Buffer
*event_data
= (LV2_Event_Buffer
*)ins
[0];
1328 class print_em_audio_module
: public print_e_audio_module
1331 LV2_Event_Buffer
*events
;
1332 static void plugin_info(plugin_info_iface
*pii
)
1334 pii
->names("print_em", "Print To Console (EM)", "lv2:UtilityPlugin");
1335 pii
->lv2_ttl("lv2:requiredFeature <http://lv2plug.in/ns/dev/contexts> ;");
1336 pii
->lv2_ttl("lv2:requiredFeature lv2ctx:MessageContext ;");
1337 pii
->lv2_ttl("lv2ctx:requiredContext lv2ctx:MessageContext ;");
1338 pii
->event_port("in", "In").input().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;");
1340 void process(uint32_t)
1343 static uint32_t message_run(LV2_Handle instance
, const void *valid_inputs
, void *outputs_written
)
1345 print_em_audio_module
*self
= (print_em_audio_module
*)instance
;
1346 if (lv2_contexts_port_is_valid(valid_inputs
, 0))
1348 printf("message_run (events = %p, count = %d)\n", self
->events
, self
->events
->event_count
);
1349 self
->dump(self
->events
);
1353 static void message_connect_port(LV2_Handle instance
, uint32_t port
, void* data
)
1355 print_em_audio_module
*self
= (print_em_audio_module
*)instance
;
1356 printf("message_connect_port %d -> %p\n", port
, data
);
1358 self
->events
= (LV2_Event_Buffer
*)data
;
1360 static inline const void *ext_data(const char *URI
) {
1361 static LV2MessageContext ctx_ext_data
= { message_run
, message_connect_port
};
1362 printf("URI=%s\n", URI
);
1363 if (!strcmp(URI
, LV2_CONTEXT_MESSAGE
))
1365 return &ctx_ext_data
;
1371 class copy_em_audio_module
: public small_audio_module_base
<0, 0>
1374 LV2_Event_Buffer
*events_in
, *events_out
;
1375 static void plugin_info(plugin_info_iface
*pii
)
1377 pii
->names("copy_em", "Message pass-through (EM)", "lv2:UtilityPlugin");
1378 pii
->lv2_ttl("lv2:requiredFeature lv2ctx:MessageContext ;");
1379 pii
->lv2_ttl("lv2:requiredFeature <http://lv2plug.in/ns/dev/contexts> ;");
1380 pii
->lv2_ttl("lv2:requiredContext lv2ctx:MessageContext ;");
1381 pii
->event_port("in", "In").input().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;");
1382 pii
->event_port("out", "Out").output().lv2_ttl("lv2ctx:context lv2ctx:MessageContext ;");
1384 void process(uint32_t)
1387 static uint32_t message_run(LV2_Handle instance
, const void *valid_inputs
, void *outputs_written
)
1389 copy_em_audio_module
*self
= (copy_em_audio_module
*)instance
;
1390 return self
->message_run(valid_inputs
, outputs_written
);
1392 uint32_t message_run(const void *inputs_written
, void *outputs_written
)
1394 if (lv2_contexts_port_is_valid(inputs_written
, 0))
1396 event_port_read_iterator
ri(events_in
);
1397 event_port_write_iterator
wi(events_out
);
1398 if (events_in
->size
> events_out
->capacity
)
1400 printf("Buffer capacity exceeded!\n");
1405 const lv2_event
&event
= *ri
++;
1408 if (events_in
->event_count
!= 0)
1410 lv2_contexts_set_port_valid(outputs_written
, 1);
1414 lv2_contexts_unset_port_valid(outputs_written
, 1);
1417 static void message_connect_port(LV2_Handle instance
, uint32_t port
, void* data
)
1419 copy_em_audio_module
*self
= (copy_em_audio_module
*)instance
;
1420 printf("message_connect_port %d -> %p\n", port
, data
);
1421 if (port
== 0) self
->events_in
= (LV2_Event_Buffer
*)data
;
1422 if (port
== 1) self
->events_out
= (LV2_Event_Buffer
*)data
;
1424 static inline const void *ext_data(const char *URI
) {
1425 static LV2MessageContext ctx_ext_data
= { message_run
, message_connect_port
};
1426 if (!strcmp(URI
, LV2_CONTEXT_MESSAGE
))
1428 printf("URI=%s\n", URI
);
1429 return &ctx_ext_data
;
1435 template<class Range
, int Inputs
= 1>
1436 class miditypefilter_m_audio_module
: public midi_mixin
<small_audio_module_base
<Inputs
, 2> >
1439 static inline void extra_inputs(plugin_info_iface
*pii
)
1442 static inline const char *plugin_symbol() { return Range::strings()[0]; }
1443 static inline const char *plugin_name() { return Range::strings()[1]; }
1444 static inline const char *port_symbol() { return Range::strings()[2]; }
1445 static inline const char *port_name() { return Range::strings()[3]; }
1446 static void plugin_info(plugin_info_iface
*pii
)
1448 pii
->names(Range::plugin_symbol(), Range::plugin_name(), "kf:MIDIPlugin");
1449 pii
->event_port("in", "In").input();
1450 Range::extra_inputs(pii
);
1451 pii
->event_port(Range::port_symbol(), Range::port_name()).output();
1452 pii
->event_port("others", "Others").output();
1454 void process(uint32_t)
1456 event_port_read_iterator
ri((LV2_Event_Buffer
*)this->ins
[0]);
1457 event_port_write_iterator
wi((LV2_Event_Buffer
*)this->outs
[0]);
1458 event_port_write_iterator
wi2((LV2_Event_Buffer
*)this->outs
[1]);
1461 const lv2_event
&event
= *ri
++;
1462 if (event
.type
== this->midi_event_type
&& event
.size
&& Range::is_in_range(event
.data
, this->ins
))
1470 class notefilter_m_audio_module
: public miditypefilter_m_audio_module
<notefilter_m_audio_module
>
1473 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0x80 && data
[0] <= 0x9F; }
1474 static inline const char **strings() { static const char *s
[] = { "notefilter_m", "Note Filter", "note", "Note" }; return s
;}
1477 class pcfilter_m_audio_module
: public miditypefilter_m_audio_module
<pcfilter_m_audio_module
>
1480 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0xA0 && data
[0] <= 0xAF; }
1481 static inline const char **strings() { static const char *s
[] = { "pcfilter_m", "Program Change Filter", "pc", "PC" }; return s
;}
1484 class ccfilter_m_audio_module
: public miditypefilter_m_audio_module
<ccfilter_m_audio_module
>
1487 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0xB0 && data
[0] <= 0xBF; }
1488 static inline const char **strings() { static const char *s
[] = { "ccfilter_m", "Control Change Filter", "cc", "CC" }; return s
;}
1491 class pressurefilter_m_audio_module
: public miditypefilter_m_audio_module
<pressurefilter_m_audio_module
>
1494 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0xC0 && data
[0] <= 0xDF; }
1495 static inline const char **strings() { static const char *s
[] = { "pressurefilter_m", "Pressure Filter", "pressure", "Pressure" }; return s
;}
1498 class pitchbendfilter_m_audio_module
: public miditypefilter_m_audio_module
<pitchbendfilter_m_audio_module
>
1501 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0xE0 && data
[0] <= 0xEF; }
1502 static inline const char **strings() { static const char *s
[] = { "pitchbendfilter_m", "Pitch Bend Filter", "pbend", "Pitch Bend" }; return s
;}
1505 class systemfilter_m_audio_module
: public miditypefilter_m_audio_module
<systemfilter_m_audio_module
>
1508 static inline bool is_in_range(const uint8_t *data
, float **) { return data
[0] >= 0xF0; }
1509 static inline const char **strings() { static const char *s
[] = { "systemfilter_m", "System Msg Filter", "system", "System" }; return s
;}
1512 class channelfilter_m_audio_module
: public miditypefilter_m_audio_module
<channelfilter_m_audio_module
, 3>
1515 static inline void extra_inputs(plugin_info_iface
*pii
)
1517 pii
->control_port("min", "Min Channel", 1).input().integer().lin_range(1, 16);
1518 pii
->control_port("max", "Max Channel", 16).input().integer().lin_range(1, 16);
1520 static inline bool is_in_range(const uint8_t *data
, float **ins
) {
1521 int chnl
= 1 + (data
[0] & 0xF);
1522 return data
[0] < 0xF0 && chnl
>= *ins
[1] && chnl
<= *ins
[2];
1524 static inline const char **strings() { static const char *s
[] = { "channelfilter_m", "Channel Range Filter", "range", "Range" }; return s
;}
1527 class keyfilter_m_audio_module
: public miditypefilter_m_audio_module
<keyfilter_m_audio_module
, 3>
1530 static inline void extra_inputs(plugin_info_iface
*pii
)
1532 pii
->control_port("min", "Min Note", 0).input().integer().lin_range(0, 127);
1533 pii
->control_port("max", "Max Note", 127).input().integer().lin_range(0, 127);
1535 static inline bool is_in_range(const uint8_t *data
, float **ins
) {
1536 // XXXKF doesn't handle polyphonic aftertouch
1537 return (data
[0] >= 0x80 && data
[0] <= 0x9F) && data
[0] >= *ins
[1] && data
[1] <= *ins
[2];
1539 static inline const char **strings() { static const char *s
[] = { "keyfilter_m", "Key Range Filter", "range", "Range" }; return s
;}
1542 class key_less_than_m_audio_module
: public miditypefilter_m_audio_module
<key_less_than_m_audio_module
, 2>
1545 static inline void extra_inputs(plugin_info_iface
*pii
)
1547 pii
->control_port("threshold", "Threshold", 60).input().integer().lin_range(0, 128);
1549 static inline bool is_in_range(const uint8_t *data
, float **ins
) {
1550 // XXXKF doesn't handle polyphonic aftertouch
1551 return (data
[0] >= 0x80 && data
[0] <= 0x9F) && data
[1] < *ins
[1];
1553 static inline const char **strings() { static const char *s
[] = { "key_less_than_m", "Key Less-Than Filter", "less", "Less" }; return s
;}
1556 class channel_less_than_m_audio_module
: public miditypefilter_m_audio_module
<channel_less_than_m_audio_module
, 2>
1559 static inline void extra_inputs(plugin_info_iface
*pii
)
1561 pii
->control_port("threshold", "Threshold", 10).input().integer().lin_range(1, 16);
1563 static inline bool is_in_range(const uint8_t *data
, float **ins
) {
1564 // XXXKF doesn't handle polyphonic aftertouch
1565 return (data
[0] < 0xF0) && (1 + (data
[0] & 0xF)) < *ins
[1];
1567 static inline const char **strings() { static const char *s
[] = { "channel_less_than_m", "Channel Less-Than Filter", "less", "Less" }; return s
;}
1570 class transpose_m_audio_module
: public midi_mixin
<small_audio_module_base
<2, 1> >
1573 static void plugin_info(plugin_info_iface
*pii
)
1575 pii
->names("transpose_m", "Transpose", "kf:MIDIPlugin");
1576 pii
->event_port("in", "In").input();
1577 pii
->control_port("transpose", "Transpose", 12).input().integer();
1578 pii
->event_port("out", "Out").output();
1580 void process(uint32_t)
1582 event_port_read_iterator
ri((LV2_Event_Buffer
*)ins
[0]);
1583 event_port_write_iterator
wi((LV2_Event_Buffer
*)outs
[0]);
1586 const lv2_event
&event
= *ri
++;
1587 if (event
.type
== this->midi_event_type
&& event
.size
== 3 && (event
.data
[0] >= 0x80 && event
.data
[0] <= 0x9F))
1589 int new_note
= event
.data
[1] + (int)*ins
[1];
1590 // ignore out-of-range notes
1591 if (new_note
>= 0 && new_note
<= 127)
1593 // it is not possible to create copies here because they are variable length and would "nicely" overwrite the stack
1594 // so write the original event instead, and then modify the pitch
1596 wi
->data
[1] = new_note
;
1606 class setchannel_m_audio_module
: public midi_mixin
<small_audio_module_base
<2, 1> >
1609 static void plugin_info(plugin_info_iface
*pii
)
1611 pii
->names("setchannel_m", "Set Channel", "kf:MIDIPlugin");
1612 pii
->event_port("in", "In").input();
1613 pii
->control_port("channel", "Channel", 1).input().integer().lin_range(1, 16);
1614 pii
->event_port("out", "Out").output();
1616 void process(uint32_t)
1618 event_port_read_iterator
ri((LV2_Event_Buffer
*)ins
[0]);
1619 event_port_write_iterator
wi((LV2_Event_Buffer
*)outs
[0]);
1622 const lv2_event
&event
= *ri
++;
1623 if (event
.type
== this->midi_event_type
&& (event
.data
[0] >= 0x80 && event
.data
[0] <= 0xEF))
1626 // modify channel number in the first byte
1627 wi
->data
[0] = (wi
->data
[0] & 0xF0) | (((int)*ins
[1] - 1) & 0xF);
1636 class eventmerge_e_audio_module
: public event_mixin
<small_audio_module_base
<2, 1> >
1639 static void plugin_info(plugin_info_iface
*pii
)
1641 pii
->names("eventmerge_e", "Event Merge (E)", "lv2:UtilityPlugin");
1642 pii
->event_port("in_1", "In 1").input();
1643 pii
->event_port("in_2", "In 2").input();
1644 pii
->event_port("out", "Out").output();
1646 void process(uint32_t)
1648 event_port_merge_iterator
<event_port_read_iterator
, event_port_read_iterator
> ri((const LV2_Event_Buffer
*)ins
[0], (const LV2_Event_Buffer
*)ins
[1]);
1649 event_port_write_iterator
wi((LV2_Event_Buffer
*)outs
[0]);
1655 class print_a_audio_module
: public small_audio_module_base
<1, 0>
1658 static void plugin_info(plugin_info_iface
*pii
)
1660 pii
->names("print_a", "Print To Console (A)", "lv2:UtilityPlugin");
1661 pii
->audio_port("in", "In").input();
1663 void process(uint32_t)
1665 printf("%f\n", *ins
[0]);
1669 template<bool audio
>
1670 class quadpower_base
: public null_small_audio_module
1673 enum { in_value
, in_factor
, in_count
, out_count
= 4 };
1674 float *ins
[in_count
];
1675 float *outs
[out_count
];
1677 static void plugin_info(plugin_info_iface
*pii
)
1679 const char *names
[8] = {"xa", "x*a^1", "xaa", "x*a^2", "xaaa", "x*a^3", "xaaaa", "x*a^4" };
1681 pii
->names("quadpower_a", "Quad Power (A)", "kf:MathOperatorPlugin");
1683 pii
->names("quadpower_c", "Quad Power (C)", "kf:MathOperatorPlugin");
1685 pii
->audio_port("x", "x").input();
1687 pii
->control_port("x", "x", 1).input();
1688 pii
->control_port("a", "a", 1).input();
1689 for (int i
= 0; i
< 8; i
+= 2)
1691 pii
->audio_port(names
[i
], names
[i
+1]).output();
1693 pii
->control_port(names
[i
], names
[i
+1], 0).output();
1697 class quadpower_a_audio_module
: public quadpower_base
<true>
1700 void process(uint32_t count
)
1702 float a
= *ins
[in_factor
];
1703 for (uint32_t i
= 0; i
< count
; i
++)
1705 float x
= ins
[in_value
][i
];
1707 outs
[1][i
] = x
* a
* a
;
1708 outs
[2][i
] = x
* a
* a
* a
;
1709 outs
[3][i
] = x
* a
* a
* a
* a
;
1714 class quadpower_c_audio_module
: public quadpower_base
<false>
1717 void process(uint32_t)
1719 float x
= *ins
[in_value
];
1720 float a
= *ins
[in_factor
];
1722 *outs
[1] = x
* a
* a
;
1723 *outs
[2] = x
* a
* a
* a
;
1724 *outs
[3] = x
* a
* a
* a
* a
;
1728 template<class Ramp
>
1729 class inertia_c_module_base
: public small_audio_module_base
<3, 1>
1732 enum { in_value
, in_inertia
, in_immediate
};
1734 inertia
<Ramp
> state
;
1735 inertia_c_module_base()
1742 static void port_info(plugin_info_iface
*pii
)
1744 pii
->control_port("in", "In", 0).input();
1745 pii
->control_port("time", "Inertia time", 100).input();
1746 pii
->control_port("reset", "Reset", 0).input().toggle().trigger();
1747 pii
->control_port("out", "Out", 0).output();
1749 void process(uint32_t count
)
1751 float value
= *ins
[in_value
];
1752 if (reset
|| *ins
[in_immediate
] > 0)
1755 state
.set_now(value
);
1760 if (value
!= state
.get_last())
1762 state
.ramp
.set_length(dsp::clip((int)(srate
* 0.001 * *ins
[in_inertia
]), 1, 10000000));
1764 state
.set_inertia(value
);
1765 *outs
[0] = state
.get_last();
1767 state
.step_many(count
);
1772 class linear_inertia_c_audio_module
: public inertia_c_module_base
<linear_ramp
>
1775 static void plugin_info(plugin_info_iface
*pii
)
1777 pii
->names("linear_inertia_c", "Linear Inertia (C)", "lv2:FilterPlugin");
1782 class exp_inertia_c_audio_module
: public inertia_c_module_base
<exponential_ramp
>
1785 static void plugin_info(plugin_info_iface
*pii
)
1787 pii
->names("exp_inertia_c", "Exponential Inertia (C)", "lv2:FilterPlugin");
1792 class sample_hold_base
: public small_audio_module_base
<2, 1>
1795 enum { in_value
, in_gate
};
1796 static void port_info(plugin_info_iface
*pii
, const char *clock_symbol
, const char *clock_name
)
1798 pii
->control_port("in", "In", 0).input();
1799 pii
->control_port(clock_symbol
, clock_name
, 0).input().toggle().trigger();
1800 pii
->control_port("out", "Out", 0).output();
1804 class sample_hold_edge_c_audio_module
: public sample_hold_base
1814 void process(uint32_t count
)
1816 if (!prev_clock
&& *ins
[in_gate
] > 0)
1817 value
= *ins
[in_value
];
1818 prev_clock
= *ins
[in_gate
] > 0;
1821 static void plugin_info(plugin_info_iface
*pii
)
1823 pii
->names("sample_hold_edge", "Sample&Hold (Edge, C)", "lv2:UtilityPlugin");
1824 port_info(pii
, "clock", "Clock");
1828 class sample_hold_level_c_audio_module
: public sample_hold_base
1836 void process(uint32_t count
)
1838 if (*ins
[in_gate
] > 0)
1839 value
= *ins
[in_value
];
1842 static void plugin_info(plugin_info_iface
*pii
)
1844 pii
->names("sample_hold_level", "Sample&Hold (Level, C)", "lv2:UtilityPlugin");
1845 port_info(pii
, "gate", "Gate");
1849 class msgread_e_audio_module
: public message_mixin
<small_audio_module_base
<1, 1> >
1852 uint32_t set_float_msg
, float_type
;
1853 static void plugin_info(plugin_info_iface
*pii
)
1855 pii
->names("msgread_e", "Msg Read", "lv2:UtilityPlugin");
1857 pii
->event_port("in", "In").input();
1858 pii
->control_port("out", "Out", 0).output();
1860 virtual void map_uris()
1862 message_mixin
<small_audio_module_base
<1, 1> >::map_uris();
1863 set_float_msg
= map_uri("http://lv2plug.in/ns/dev/msg", "http://foltman.com/garbage/setFloat");
1864 float_type
= map_uri("http://lv2plug.in/ns/dev/types", "http://lv2plug.in/ns/dev/types#float");
1866 void process(uint32_t count
)
1868 event_port_read_iterator
ri((const LV2_Event_Buffer
*)ins
[0]);
1871 const lv2_event
*event
= &*ri
++;
1872 if (event
->type
== message_event_type
)
1878 uint32_t parg_count
;
1881 uint32_t narg_count
;
1883 const payload
*p
= (const payload
*)event
->data
;
1884 if (p
->selector
== set_float_msg
) {
1885 assert(p
->parg_count
== 1);
1886 assert(p
->data_size
== 16);
1887 assert(p
->data_type
== float_type
);
1888 *outs
[0] = p
->data_value
;
1889 assert(p
->narg_count
== 0); // this is just for testing - passing
1898 #define PER_SMALL_MODULE_ITEM(name, id) SMALL_WRAPPERS(name, id)
1899 #include <calf/modulelist.h>
1901 const LV2_Descriptor
*calf_plugins::lv2_small_descriptor(uint32_t index
)
1903 #define PER_SMALL_MODULE_ITEM(name, id) if (!(index--)) return &::lv2_small_##name.descriptor;
1904 #include <calf/modulelist.h>
1910 void calf_plugins::get_all_small_plugins(plugin_list_info_iface
*iface
)
1913 #define PER_SMALL_MODULE_ITEM(name, id) { plugin_info_iface *pii = &iface->plugin(id); small_plugins::name##_audio_module::plugin_info(pii); pii->finalize(); }
1914 #include <calf/modulelist.h>