Vocoder: toggle switch for detection LEDs
[calf.git] / src / modules_comp.cpp
blob9df64f47e43bc55ec159329dba1ffaba47ab8044
1 /* Calf DSP plugin pack
2 * Compression related plugins
4 * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
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
21 #include <limits.h>
22 #include <memory.h>
23 #include <calf/audio_fx.h>
24 #include <calf/giface.h>
25 #include <calf/modules_comp.h>
27 using namespace dsp;
28 using namespace calf_plugins;
30 #define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
33 /**********************************************************************
34 * GAIN REDUCTION by Thor Harald Johanssen
35 **********************************************************************/
37 gain_reduction_audio_module::gain_reduction_audio_module()
39 is_active = false;
40 srate = 0;
41 old_threshold = 0.f;
42 old_ratio = 0.f;
43 old_knee = 0.f;
44 old_makeup = 0.f;
45 old_detection = 0.f;
46 old_bypass = 0.f;
47 old_mute = 0.f;
48 linSlope = 0.f;
49 attack = -1;
50 release = -1;
51 detection = -1;
52 stereo_link = -1;
53 threshold = -1;
54 ratio = -1;
55 knee = -1;
56 makeup = -1;
57 bypass = -1;
58 mute = -1;
59 redraw_graph = true;
62 void gain_reduction_audio_module::activate()
64 is_active = true;
65 float l, r;
66 l = r = 0.f;
67 float byp = bypass;
68 bypass = 0.0;
69 process(l, r, 0, 0);
70 bypass = byp;
73 void gain_reduction_audio_module::deactivate()
75 is_active = false;
78 void gain_reduction_audio_module::update_curve()
80 float linThreshold = threshold;
81 float linKneeSqrt = sqrt(knee);
82 linKneeStart = linThreshold / linKneeSqrt;
83 adjKneeStart = linKneeStart*linKneeStart;
84 float linKneeStop = linThreshold * linKneeSqrt;
85 thres = log(linThreshold);
86 kneeStart = log(linKneeStart);
87 kneeStop = log(linKneeStop);
88 compressedKneeStop = (kneeStop - thres) / ratio + thres;
91 void gain_reduction_audio_module::process(float &left, float &right, const float *det_left, const float *det_right)
93 if(!det_left) {
94 det_left = &left;
96 if(!det_right) {
97 det_right = &right;
99 if(bypass < 0.5f) {
100 // this routine is mainly copied from thor's compressor module
101 // greatest sounding compressor I've heard!
102 bool rms = (detection == 0);
103 bool average = (stereo_link == 0);
104 float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
105 float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
107 float absample = average ? (fabs(*det_left) + fabs(*det_right)) * 0.5f : std::max(fabs(*det_left), fabs(*det_right));
108 if(rms) absample *= absample;
110 dsp::sanitize(linSlope);
112 linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
113 float gain = 1.f;
114 if(linSlope > 0.f) {
115 gain = output_gain(linSlope, rms);
118 left *= gain * makeup;
119 right *= gain * makeup;
120 meter_out = std::max(fabs(left), fabs(right));;
121 meter_comp = gain;
122 detected = rms ? sqrt(linSlope) : linSlope;
126 float gain_reduction_audio_module::output_level(float slope) const {
127 return slope * output_gain(slope, false) * makeup;
130 float gain_reduction_audio_module::output_gain(float linSlope, bool rms) const {
131 //this calculation is also thor's work
132 if(linSlope > (rms ? adjKneeStart : linKneeStart)) {
133 float slope = log(linSlope);
134 if(rms) slope *= 0.5f;
136 float gain = 0.f;
137 float delta = 0.f;
138 if(IS_FAKE_INFINITY(ratio)) {
139 gain = thres;
140 delta = 0.f;
141 } else {
142 gain = (slope - thres) / ratio + thres;
143 delta = 1.f / ratio;
146 if(knee > 1.f && slope < kneeStop) {
147 gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta);
150 return exp(gain - slope);
153 return 1.f;
156 void gain_reduction_audio_module::set_sample_rate(uint32_t sr)
158 srate = sr;
160 void gain_reduction_audio_module::set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu)
162 // set all params
163 attack = att;
164 release = rel;
165 threshold = thr;
166 ratio = rat;
167 knee = kn;
168 makeup = mak;
169 detection = det;
170 stereo_link = stl;
171 bypass = byp;
172 mute = mu;
173 if(mute > 0.f) {
174 meter_out = 0.f;
175 meter_comp = 1.f;
178 if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f) {
179 old_threshold = threshold;
180 old_ratio = ratio;
181 old_knee = knee;
182 old_makeup = makeup;
183 old_detection = detection;
184 old_bypass = bypass;
185 old_mute = mute;
186 redraw_graph = true;
189 float gain_reduction_audio_module::get_output_level() {
190 // returns output level (max(left, right))
191 return meter_out;
193 float gain_reduction_audio_module::get_comp_level() {
194 // returns amount of compression
195 return meter_comp;
198 bool gain_reduction_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context, int *mode) const
200 redraw_graph = false;
201 if (!is_active or subindex > 1)
202 return false;
204 for (int i = 0; i < points; i++)
206 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
207 if (subindex == 0) {
208 if (i == 0 or i >= points - 1)
209 data[i] = dB_grid(input);
210 else
211 data[i] = INFINITY;
212 } else {
213 float output = output_level(input);
214 data[i] = dB_grid(output);
217 if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
218 context->set_source_rgba(0.15, 0.2, 0.0, 0.3);
219 else {
220 context->set_source_rgba(0.15, 0.2, 0.0, 0.8);
222 if (!subindex)
223 context->set_line_width(1.);
224 return true;
227 bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) const
229 if (!is_active or bypass > 0.5f or mute > 0.f or subindex)
230 return false;
232 bool rms = (detection == 0);
233 float det = rms ? sqrt(detected) : detected;
234 x = 0.5 + 0.5 * dB_grid(det);
235 y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
236 return true;
239 bool gain_reduction_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
241 if (!is_active)
242 return false;
243 bool tmp;
244 vertical = (subindex & 1) != 0;
245 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
246 if (result && vertical) {
247 if ((subindex & 4) && !legend.empty()) {
248 legend = "";
250 else {
251 size_t pos = legend.find(" dB");
252 if (pos != std::string::npos)
253 legend.erase(pos);
255 pos = 0.5 + 0.5 * pos;
257 return result;
260 bool gain_reduction_audio_module::get_layers(int index, int generation, unsigned int &layers) const
262 layers = LG_REALTIME_DOT | (generation ? 0 : LG_CACHE_GRID) | ((redraw_graph || !generation) ? LG_CACHE_GRAPH : 0);
263 return true;
266 /**********************************************************************
267 * GAIN REDUCTION 2 by Damien Zammit
268 **********************************************************************/
270 gain_reduction2_audio_module::gain_reduction2_audio_module()
272 is_active = false;
273 srate = 0;
274 old_threshold = 0.f;
275 old_ratio = 0.f;
276 old_knee = 0.f;
277 old_makeup = 0.f;
278 old_detection = 0.f;
279 old_bypass = 0.f;
280 old_mute = 0.f;
281 linSlope = 0.f;
282 attack = -1;
283 release = -1;
284 detection = -1;
285 stereo_link = -1;
286 threshold = -1;
287 ratio = -1;
288 knee = -1;
289 makeup = -1;
290 bypass = -1;
291 mute = -1;
292 old_y1 = 0.f;
293 old_yl = 0.f;
294 old_detected = 0.f;
295 redraw_graph = true;
298 void gain_reduction2_audio_module::activate()
300 is_active = true;
301 float l, r;
302 l = r = 0.f;
303 float byp = bypass;
304 bypass = 0.0;
305 process(l);
306 bypass = byp;
309 void gain_reduction2_audio_module::deactivate()
311 is_active = false;
314 void gain_reduction2_audio_module::update_curve()
319 void gain_reduction2_audio_module::process(float &left)
321 if(bypass < 0.5f) {
322 float width=(knee-0.99f)*8.f;
323 float cdb=0.f;
324 float attack_coeff = exp(-1000.f/(attack * srate));
325 float release_coeff = exp(-1000.f/(release * srate));
326 float thresdb=20.f*log10(threshold);
328 float gain = 1.f;
329 float xg, xl, yg, yl, y1;
330 yg=0.f;
331 xg = (left==0.f) ? -160.f : 20.f*log10(fabs(left));
333 if (2.f*(xg-thresdb)<-width) {
334 yg = xg;
336 if (2.f*fabs(xg-thresdb)<=width) {
337 yg = xg + (1.f/ratio-1.f)*(xg-thresdb+width/2.f)*(xg-thresdb+width/2.f)/(2.f*width);
339 if (2.f*(xg-thresdb)>width) {
340 yg = thresdb + (xg-thresdb)/ratio;
343 xl = xg - yg;
345 y1 = std::max(xl, release_coeff*old_y1+(1.f-release_coeff)*xl);
346 yl = attack_coeff*old_yl+(1.f-attack_coeff)*y1;
348 cdb = -yl;
349 gain = exp(cdb/20.f*log(10.f));
351 left *= gain * makeup;
352 meter_out = (fabs(left));
353 meter_comp = gain;
354 detected = (exp(yg/20.f*log(10.f))+old_detected)/2.f;
355 old_detected = detected;
357 old_yl = yl;
358 old_y1 = y1;
362 float gain_reduction2_audio_module::output_level(float inputt) const {
363 return (output_gain(inputt) * makeup);
366 float gain_reduction2_audio_module::output_gain(float inputt) const {
367 float width=(knee-0.99f)*8.f;
368 float thresdb=20.f*log10(threshold);
370 float xg, yg;
371 yg=0.f;
372 xg = (inputt==0.f) ? -160.f : 20.f*log10(fabs(inputt));
374 if (2.f*(xg-thresdb)<-width) {
375 yg = xg;
377 if (2.f*fabs(xg-thresdb)<=width) {
378 yg = xg + (1.f/ratio-1.f)*(xg-thresdb+width/2.f)*(xg-thresdb+width/2.f)/(2.f*width);
380 if (2.f*(xg-thresdb)>width) {
381 yg = thresdb + (xg-thresdb)/ratio;
384 return(exp(yg/20.f*log(10.f)));
387 void gain_reduction2_audio_module::set_sample_rate(uint32_t sr)
389 srate = sr;
391 void gain_reduction2_audio_module::set_params(float att, float rel, float thr, float rat, float kn, float mak, float byp, float mu)
393 // set all params
394 attack = att;
395 release = rel;
396 threshold = thr;
397 ratio = rat;
398 knee = kn;
399 makeup = mak;
400 bypass = byp;
401 mute = mu;
402 if(mute > 0.f) {
403 meter_out = 0.f;
404 meter_comp = 1.f;
406 if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f) {
407 old_threshold = threshold;
408 old_ratio = ratio;
409 old_knee = knee;
410 old_makeup = makeup;
411 old_detection = detection;
412 old_bypass = bypass;
413 old_mute = mute;
414 redraw_graph = true;
417 float gain_reduction2_audio_module::get_output_level() {
418 // returns output level (max(left, right))
419 return meter_out;
421 float gain_reduction2_audio_module::get_comp_level() {
422 // returns amount of compression
423 return meter_comp;
426 bool gain_reduction2_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context, int *mode) const
428 redraw_graph = false;
429 if (!is_active or subindex > 1)
430 return false;
432 for (int i = 0; i < points; i++)
434 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
435 if (subindex == 0) {
436 if (i == 0 or i >= points - 1)
437 data[i] = dB_grid(input);
438 else
439 data[i] = INFINITY;
440 } else {
441 float output = output_level(input);
442 data[i] = dB_grid(output);
445 if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
446 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
447 else {
448 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
450 if (!subindex)
451 context->set_line_width(1.);
452 return true;
455 bool gain_reduction2_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) const
457 if (!is_active or bypass > 0.5f or mute > 0.f or subindex)
458 return false;
460 bool rms = (detection == 0);
461 float det = rms ? sqrt(detected) : detected;
462 x = 0.5 + 0.5 * dB_grid(det);
463 y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
464 return true;
467 bool gain_reduction2_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
469 bool tmp;
470 vertical = (subindex & 1) != 0;
471 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
472 if (result && vertical) {
473 if ((subindex & 4) && !legend.empty()) {
474 legend = "";
476 else {
477 size_t pos = legend.find(" dB");
478 if (pos != std::string::npos)
479 legend.erase(pos);
481 pos = 0.5 + 0.5 * pos;
483 return result;
486 bool gain_reduction2_audio_module::get_layers(int index, int generation, unsigned int &layers) const
488 layers = LG_REALTIME_DOT | (generation ? 0 : LG_CACHE_GRID) | ((redraw_graph || !generation) ? LG_CACHE_GRAPH : 0);
489 return true;
493 /**********************************************************************
494 * EXPANDER by Damien Zammit
495 **********************************************************************/
497 expander_audio_module::expander_audio_module()
499 is_active = false;
500 srate = 0;
501 range = -1;
502 threshold = -1;
503 ratio = -1;
504 knee = -1;
505 makeup = -1;
506 detection = -1;
507 bypass = -1;
508 mute = -1;
509 stereo_link = -1;
510 old_range = 0.f;
511 old_threshold = 0.f;
512 old_ratio = 0.f;
513 old_knee = 0.f;
514 old_makeup = 0.f;
515 old_detection = 0.f;
516 old_bypass = 0.f;
517 old_mute = 0.f;
518 old_trigger = 0.f;
519 old_stereo_link = 0.f;
520 linSlope = 0.f;
521 linKneeStop = 0.f;
522 redraw_graph = true;
525 void expander_audio_module::activate()
527 is_active = true;
528 update_curve();
529 float l, r;
530 l = r = 0.f;
531 float byp = bypass;
532 bypass = 0.0;
533 process(l, r);
534 bypass = byp;
537 void expander_audio_module::deactivate()
539 is_active = false;
542 void expander_audio_module::update_curve()
544 bool rms = (detection == 0);
545 float linThreshold = threshold;
546 if (rms)
547 linThreshold = linThreshold * linThreshold;
548 attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
549 release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
550 float linKneeSqrt = sqrt(knee);
551 linKneeStart = linThreshold / linKneeSqrt;
552 adjKneeStart = linKneeStart*linKneeStart;
553 linKneeStop = linThreshold * linKneeSqrt;
554 thres = log(linThreshold);
555 kneeStart = log(linKneeStart);
556 kneeStop = log(linKneeStop);
557 compressedKneeStop = (kneeStop - thres) / ratio + thres;
560 void expander_audio_module::process(float &left, float &right, const float *det_left, const float *det_right)
562 if(!det_left) {
563 det_left = &left;
565 if(!det_right) {
566 det_right = &right;
568 if(bypass < 0.5f) {
569 // this routine is mainly copied from Damien's expander module based on Thor's compressor
570 bool rms = (detection == 0);
571 bool average = (stereo_link == 0);
572 float absample = average ? (fabs(*det_left) + fabs(*det_right)) * 0.5f : std::max(fabs(*det_left), fabs(*det_right));
573 if(rms) absample *= absample;
575 dsp::sanitize(linSlope);
577 linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
578 float gain = 1.f;
579 if(linSlope > 0.f) {
580 gain = output_gain(linSlope, rms);
582 left *= gain * makeup;
583 right *= gain * makeup;
584 meter_out = std::max(fabs(left), fabs(right));
585 meter_gate = gain;
586 detected = linSlope;
590 float expander_audio_module::output_level(float slope) const {
591 bool rms = (detection == 0);
592 return slope * output_gain(rms ? slope*slope : slope, rms) * makeup;
595 float expander_audio_module::output_gain(float linSlope, bool rms) const {
596 //this calculation is also Damiens's work based on Thor's compressor
597 if(linSlope < linKneeStop) {
598 float slope = log(linSlope);
599 //float tratio = rms ? sqrt(ratio) : ratio;
600 float tratio = ratio;
601 float gain = 0.f;
602 float delta = 0.f;
603 if(IS_FAKE_INFINITY(ratio))
604 tratio = 1000.f;
605 gain = (slope-thres) * tratio + thres;
606 delta = tratio;
608 if(knee > 1.f && slope > kneeStart ) {
609 gain = dsp::hermite_interpolation(slope, kneeStart, kneeStop, ((kneeStart - thres) * tratio + thres), kneeStop, delta,1.f);
611 return std::max(range, expf(gain-slope));
613 return 1.f;
616 void expander_audio_module::set_sample_rate(uint32_t sr)
618 srate = sr;
621 void expander_audio_module::set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu, float ran)
623 // set all params
624 attack = att;
625 release = rel;
626 threshold = thr;
627 ratio = rat;
628 knee = kn;
629 makeup = mak;
630 detection = det;
631 stereo_link = stl;
632 bypass = byp;
633 mute = mu;
634 range = ran;
635 if(mute > 0.f) {
636 meter_out = 0.f;
637 meter_gate = 1.f;
639 if (fabs(range - old_range) + fabs(threshold - old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f) {
640 old_range = range;
641 old_threshold = threshold;
642 old_ratio = ratio;
643 old_knee = knee;
644 old_makeup = makeup;
645 old_detection = detection;
646 old_bypass = bypass;
647 old_mute = mute;
648 redraw_graph = true;
652 float expander_audio_module::get_output_level() {
653 // returns output level (max(left, right))
654 return meter_out;
656 float expander_audio_module::get_expander_level() {
657 // returns amount of gating
658 return meter_gate;
661 bool expander_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context, int *mode) const
663 redraw_graph = false;
664 if (!is_active or subindex > 1)
665 return false;
667 for (int i = 0; i < points; i++) {
668 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
669 if (subindex == 0) {
670 if (i == 0 or i >= points - 1)
671 data[i] = dB_grid(input);
672 else
673 data[i] = INFINITY;
674 } else {
675 float output = output_level(input);
676 data[i] = dB_grid(output);
679 if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
680 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
681 else {
682 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
684 if (!subindex)
685 context->set_line_width(1.);
686 return true;
689 bool expander_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context) const
691 if (!is_active or bypass > 0.5f or mute > 0.f or subindex)
692 return false;
694 bool rms = (detection == 0);
695 float det = rms ? sqrt(detected) : detected;
696 x = 0.5 + 0.5 * dB_grid(det);
697 y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
698 return true;
701 bool expander_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
703 bool tmp;
704 vertical = (subindex & 1) != 0;
705 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
706 if (result && vertical) {
707 if ((subindex & 4) && !legend.empty()) {
708 legend = "";
710 else {
711 size_t pos = legend.find(" dB");
712 if (pos != std::string::npos)
713 legend.erase(pos);
715 pos = 0.5 + 0.5 * pos;
717 return result;
720 bool expander_audio_module::get_layers(int index, int generation, unsigned int &layers) const
722 layers = LG_REALTIME_DOT | (generation ? 0 : LG_CACHE_GRID) | ((redraw_graph || !generation) ? LG_CACHE_GRAPH : 0);
723 return true;
727 /**********************************************************************
728 * COMPRESSOR by Thor Harald Johanssen
729 **********************************************************************/
731 compressor_audio_module::compressor_audio_module()
733 is_active = false;
734 srate = 0;
737 void compressor_audio_module::activate()
739 is_active = true;
740 // set all filters and strips
741 compressor.activate();
742 params_changed();
744 void compressor_audio_module::deactivate()
746 is_active = false;
747 compressor.deactivate();
750 void compressor_audio_module::params_changed()
752 compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f);
755 void compressor_audio_module::set_sample_rate(uint32_t sr)
757 srate = sr;
758 compressor.set_sample_rate(srate);
759 int meter[] = {param_meter_in, param_meter_out, -param_compression};
760 int clip[] = {param_clip_in, param_clip_out, -1};
761 meters.init(params, meter, clip, 3, srate);
764 uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
766 bool bypass = *params[param_bypass] > 0.5f;
767 numsamples += offset;
768 if(bypass) {
769 // everything bypassed
770 while(offset < numsamples) {
771 outs[0][offset] = ins[0][offset];
772 outs[1][offset] = ins[1][offset];
773 float values[] = {0, 0, 1};
774 meters.process(values);
775 ++offset;
777 // displays, too
778 } else {
779 // process
781 compressor.update_curve();
783 while(offset < numsamples) {
784 // cycle through samples
785 float outL = 0.f;
786 float outR = 0.f;
787 float inL = ins[0][offset];
788 float inR = ins[1][offset];
789 float Lin = ins[0][offset];
790 float Rin = ins[1][offset];
792 // in level
793 inR *= *params[param_level_in];
794 inL *= *params[param_level_in];
796 float leftAC = inL;
797 float rightAC = inR;
799 compressor.process(leftAC, rightAC);
801 outL = leftAC;
802 outR = rightAC;
804 // mix
805 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
806 outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
808 // send to output
809 outs[0][offset] = outL;
810 outs[1][offset] = outR;
812 float values[] = {std::max(inL, inR), std::max(outL, outR), compressor.get_comp_level()};
813 meters.process(values);
815 // next sample
816 ++offset;
817 } // cycle trough samples
819 meters.fall(numsamples);
820 return outputs_mask;
822 bool compressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
824 return compressor.get_graph(subindex, data, points, context, mode);
827 bool compressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
829 return compressor.get_dot(subindex, x, y, size, context);
832 bool compressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
834 return compressor.get_gridline(subindex, pos, vertical, legend, context);
837 bool compressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
839 return compressor.get_layers(index, generation, layers);
842 /**********************************************************************
843 * SIDECHAIN COMPRESSOR by Markus Schmidt
844 **********************************************************************/
846 sidechaincompressor_audio_module::sidechaincompressor_audio_module()
848 is_active = false;
849 srate = 0;
850 f1_freq_old1 = 0.f;
851 f2_freq_old1 = 0.f;
852 f1_level_old1 = 0.f;
853 f2_level_old1 = 0.f;
854 f1_freq_old = 0.f;
855 f2_freq_old = 0.f;
856 f1_level_old = 0.f;
857 f2_level_old = 0.f;
858 sc_mode_old1 = WIDEBAND;
859 redraw_graph = true;
862 void sidechaincompressor_audio_module::activate()
864 is_active = true;
865 // set all filters and strips
866 compressor.activate();
867 params_changed();
869 void sidechaincompressor_audio_module::deactivate()
871 is_active = false;
872 compressor.deactivate();
875 sidechaincompressor_audio_module::cfloat sidechaincompressor_audio_module::h_z(const cfloat &z) const
877 switch ((CalfScModes)sc_mode) {
878 default:
879 case WIDEBAND:
880 return false;
881 break;
882 case DEESSER_WIDE:
883 case DERUMBLER_WIDE:
884 case WEIGHTED_1:
885 case WEIGHTED_2:
886 case WEIGHTED_3:
887 case BANDPASS_2:
888 return f1L.h_z(z) * f2L.h_z(z);
889 break;
890 case DEESSER_SPLIT:
891 return f2L.h_z(z);
892 break;
893 case DERUMBLER_SPLIT:
894 case BANDPASS_1:
895 return f1L.h_z(z);
896 break;
900 float sidechaincompressor_audio_module::freq_gain(int index, double freq) const
902 typedef std::complex<double> cfloat;
903 freq *= 2.0 * M_PI / srate;
904 cfloat z = 1.0 / exp(cfloat(0.0, freq));
906 return std::abs(h_z(z));
909 void sidechaincompressor_audio_module::params_changed()
911 // set the params of all filters
912 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
913 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
914 or *params[param_sc_mode] != sc_mode) {
915 float q = 0.707;
916 switch ((CalfScModes)*params[param_sc_mode]) {
917 default:
918 case WIDEBAND:
919 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
920 f1R.copy_coeffs(f1L);
921 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
922 f2R.copy_coeffs(f2L);
923 f1_active = 0.f;
924 f2_active = 0.f;
925 break;
926 case DEESSER_WIDE:
927 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
928 f1R.copy_coeffs(f1L);
929 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
930 f2R.copy_coeffs(f2L);
931 f1_active = 0.5f;
932 f2_active = 1.f;
933 break;
934 case DEESSER_SPLIT:
935 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
936 f1R.copy_coeffs(f1L);
937 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
938 f2R.copy_coeffs(f2L);
939 f1_active = 0.f;
940 f2_active = 1.f;
941 break;
942 case DERUMBLER_WIDE:
943 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
944 f1R.copy_coeffs(f1L);
945 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
946 f2R.copy_coeffs(f2L);
947 f1_active = 1.f;
948 f2_active = 0.5f;
949 break;
950 case DERUMBLER_SPLIT:
951 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
952 f1R.copy_coeffs(f1L);
953 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
954 f2R.copy_coeffs(f2L);
955 f1_active = 1.f;
956 f2_active = 0.f;
957 break;
958 case WEIGHTED_1:
959 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
960 f1R.copy_coeffs(f1L);
961 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
962 f2R.copy_coeffs(f2L);
963 f1_active = 0.5f;
964 f2_active = 0.5f;
965 break;
966 case WEIGHTED_2:
967 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
968 f1R.copy_coeffs(f1L);
969 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
970 f2R.copy_coeffs(f2L);
971 f1_active = 0.5f;
972 f2_active = 0.5f;
973 break;
974 case WEIGHTED_3:
975 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
976 f1R.copy_coeffs(f1L);
977 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
978 f2R.copy_coeffs(f2L);
979 f1_active = 0.5f;
980 f2_active = 0.5f;
981 break;
982 case BANDPASS_1:
983 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
984 f1R.copy_coeffs(f1L);
985 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
986 f2R.copy_coeffs(f2L);
987 f1_active = 1.f;
988 f2_active = 0.f;
989 break;
990 case BANDPASS_2:
991 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
992 f1R.copy_coeffs(f1L);
993 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
994 f2R.copy_coeffs(f2L);
995 f1_active = 1.f;
996 f2_active = 1.f;
997 break;
999 f1_freq_old = *params[param_f1_freq];
1000 f1_level_old = *params[param_f1_level];
1001 f2_freq_old = *params[param_f2_freq];
1002 f2_level_old = *params[param_f2_level];
1003 sc_mode = (CalfScModes)*params[param_sc_mode];
1005 // light LED's
1006 if(params[param_f1_active] != NULL) {
1007 *params[param_f1_active] = f1_active;
1009 if(params[param_f2_active] != NULL) {
1010 *params[param_f2_active] = f2_active;
1012 // and set the compressor module
1013 compressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f);
1015 if (*params[param_f1_freq] != f1_freq_old1
1016 or *params[param_f2_freq] != f2_freq_old1
1017 or *params[param_f1_level] != f1_level_old1
1018 or *params[param_f2_level] != f2_level_old1
1019 or *params[param_sc_mode] != sc_mode_old1)
1021 f1_freq_old1 = *params[param_f1_freq];
1022 f2_freq_old1 = *params[param_f2_freq];
1023 f1_level_old1 = *params[param_f1_level];
1024 f2_level_old1 = *params[param_f2_level];
1025 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
1026 redraw_graph = true;
1030 void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr)
1032 srate = sr;
1033 compressor.set_sample_rate(srate);
1034 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1035 int clip[] = {param_clip_in, param_clip_out, -1};
1036 meters.init(params, meter, clip, 3, srate);
1039 uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1041 bool bypass = *params[param_bypass] > 0.5f;
1042 numsamples += offset;
1043 if(bypass) {
1044 // everything bypassed
1045 while(offset < numsamples) {
1046 outs[0][offset] = ins[0][offset];
1047 outs[1][offset] = ins[1][offset];
1048 float values[] = {0, 0, 1};
1049 meters.process(values);
1050 ++offset;
1052 } else {
1053 // process
1055 compressor.update_curve();
1057 while(offset < numsamples) {
1058 // cycle through samples
1059 float outL = 0.f;
1060 float outR = 0.f;
1061 float inL = ins[0][offset];
1062 float inR = ins[1][offset];
1063 float Lin = ins[0][offset];
1064 float Rin = ins[1][offset];
1066 float in2L = ins[2] ? ins[2][offset] : 0;
1067 float in2R = ins[3] ? ins[3][offset] : 0;
1069 // in level
1070 inR *= *params[param_level_in];
1071 inL *= *params[param_level_in];
1073 float leftAC = inL;
1074 float rightAC = inR;
1075 float leftSC = inL;
1076 float rightSC = inR;
1077 float leftMC = inL;
1078 float rightMC = inR;
1080 if (*params[param_sc_route] > 0.5) {
1081 leftAC = inL;
1082 rightAC = inR;
1083 leftSC = in2L * *params[param_sc_level];
1084 rightSC = in2R * *params[param_sc_level];
1085 leftMC = inL;
1086 rightMC = inR;
1089 switch ((CalfScModes)*params[param_sc_mode]) {
1090 default:
1091 case WIDEBAND:
1092 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1093 leftMC = leftSC;
1094 rightMC = rightSC;
1095 break;
1096 case DEESSER_WIDE:
1097 case DERUMBLER_WIDE:
1098 case WEIGHTED_1:
1099 case WEIGHTED_2:
1100 case WEIGHTED_3:
1101 case BANDPASS_2:
1102 leftSC = f2L.process(f1L.process(leftSC));
1103 rightSC = f2R.process(f1R.process(rightSC));
1104 leftMC = leftSC;
1105 rightMC = rightSC;
1106 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1107 break;
1108 case DEESSER_SPLIT:
1109 leftSC = f2L.process(leftSC);
1110 rightSC = f2R.process(rightSC);
1111 leftMC = leftSC;
1112 rightMC = rightSC;
1113 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1114 leftAC = f1L.process(leftAC);
1115 rightAC = f1R.process(rightAC);
1116 leftAC += leftSC;
1117 rightAC += rightSC;
1118 break;
1119 case DERUMBLER_SPLIT:
1120 leftSC = f1L.process(leftSC);
1121 rightSC = f1R.process(rightSC);
1122 leftMC = leftSC;
1123 rightMC = rightSC;
1124 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1125 leftAC = f2L.process(leftAC);
1126 rightAC = f2R.process(rightAC);
1127 leftAC += leftSC;
1128 rightAC += rightSC;
1129 break;
1130 case BANDPASS_1:
1131 leftSC = f1L.process(leftSC);
1132 rightSC = f1R.process(rightSC);
1133 leftMC = leftSC;
1134 rightMC = rightSC;
1135 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1136 break;
1139 if(*params[param_sc_listen] > 0.f) {
1140 outL = leftMC;
1141 outR = rightMC;
1142 } else {
1143 outL = leftAC;
1144 outR = rightAC;
1145 // mix
1146 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1147 outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1150 // send to output
1151 outs[0][offset] = outL;
1152 outs[1][offset] = outR;
1154 float values[] = {std::max(inL, inR), std::max(outL, outR), compressor.get_comp_level()};
1155 meters.process(values);
1157 // next sample
1158 ++offset;
1159 } // cycle trough samples
1160 f1L.sanitize();
1161 f1R.sanitize();
1162 f2L.sanitize();
1163 f2R.sanitize();
1165 meters.fall(numsamples);
1166 return outputs_mask;
1168 bool sidechaincompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1170 if (!is_active or phase)
1171 return false;
1172 if (index == param_sc_listen && !subindex) {
1173 return ::get_graph(*this, subindex, data, points);
1174 } else if(index == param_bypass) {
1175 return compressor.get_graph(subindex, data, points, context, mode);
1177 return false;
1180 bool sidechaincompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1182 if (!is_active or !phase)
1183 return false;
1184 if (index == param_bypass) {
1185 return compressor.get_dot(subindex, x, y, size, context);
1187 return false;
1190 bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1192 if (!is_active or phase)
1193 return false;
1194 if (index == param_bypass) {
1195 return compressor.get_gridline(subindex, pos, vertical, legend, context);
1196 } else {
1197 return get_freq_gridline(subindex, pos, vertical, legend, context);
1199 return false;
1202 bool sidechaincompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1204 if(index == param_bypass)
1205 return compressor.get_layers(index, generation, layers);
1206 bool redraw = redraw_graph || !generation;
1207 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
1208 redraw_graph = false;
1209 return redraw;
1212 /**********************************************************************
1213 * MULTIBAND COMPRESSOR by Markus Schmidt
1214 **********************************************************************/
1216 multibandcompressor_audio_module::multibandcompressor_audio_module()
1218 is_active = false;
1219 srate = 0;
1220 mode = 0;
1221 redraw = 0;
1222 page = 0;
1223 bypass = 0;
1224 crossover.init(2, 4, 44100);
1227 void multibandcompressor_audio_module::activate()
1229 is_active = true;
1230 // set all filters and strips
1231 params_changed();
1232 // activate all strips
1233 for (int j = 0; j < strips; j ++) {
1234 strip[j].activate();
1235 strip[j].id = j;
1239 void multibandcompressor_audio_module::deactivate()
1241 is_active = false;
1242 // deactivate all strips
1243 for (int j = 0; j < strips; j ++) {
1244 strip[j].deactivate();
1248 void multibandcompressor_audio_module::params_changed()
1250 // determine mute/solo states
1251 solo[0] = *params[param_solo0] > 0.f ? true : false;
1252 solo[1] = *params[param_solo1] > 0.f ? true : false;
1253 solo[2] = *params[param_solo2] > 0.f ? true : false;
1254 solo[3] = *params[param_solo3] > 0.f ? true : false;
1255 no_solo = (*params[param_solo0] > 0.f ||
1256 *params[param_solo1] > 0.f ||
1257 *params[param_solo2] > 0.f ||
1258 *params[param_solo3] > 0.f) ? false : true;
1261 int m = *params[param_mode];
1262 if (m != mode) {
1263 mode = *params[param_mode];
1266 int p = (int)*params[param_notebook];
1267 if (p != page) {
1268 page = p;
1269 redraw = strips * 2 + strips;
1272 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
1273 if (b != bypass) {
1274 redraw = strips * 2 + strips;
1275 bypass = b;
1278 crossover.set_mode(mode + 1);
1279 crossover.set_filter(0, *params[param_freq0]);
1280 crossover.set_filter(1, *params[param_freq1]);
1281 crossover.set_filter(2, *params[param_freq2]);
1283 // set the params of all strips
1284 strip[0].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], !(solo[0] || no_solo));
1285 strip[1].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], !(solo[1] || no_solo));
1286 strip[2].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], !(solo[2] || no_solo));
1287 strip[3].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], !(solo[3] || no_solo));
1290 void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
1292 srate = sr;
1293 // set srate of all strips
1294 for (int j = 0; j < strips; j ++) {
1295 strip[j].set_sample_rate(srate);
1297 // set srate of crossover
1298 crossover.set_sample_rate(srate);
1299 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
1300 param_output0, -param_compression0,
1301 param_output1, -param_compression1,
1302 param_output2, -param_compression2,
1303 param_output3, -param_compression3 };
1304 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
1305 meters.init(params, meter, clip, 12, srate);
1308 uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1310 bool bypass = *params[param_bypass] > 0.5f;
1311 numsamples += offset;
1313 for (int i = 0; i < strips; i++)
1314 strip[i].update_curve();
1315 if(bypass) {
1316 // everything bypassed
1317 while(offset < numsamples) {
1318 outs[0][offset] = ins[0][offset];
1319 outs[1][offset] = ins[1][offset];
1320 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
1321 meters.process(values);
1322 ++offset;
1324 } else {
1325 // process all strips
1326 while(offset < numsamples) {
1327 // cycle through samples
1328 float inL = ins[0][offset];
1329 float inR = ins[1][offset];
1330 // in level
1331 inR *= *params[param_level_in];
1332 inL *= *params[param_level_in];
1333 // process crossover
1334 xin[0] = inL;
1335 xin[1] = inR;
1336 crossover.process(xin);
1337 // out vars
1338 float outL = 0.f;
1339 float outR = 0.f;
1340 for (int i = 0; i < strips; i ++) {
1341 // cycle trough strips
1342 if (solo[i] || no_solo) {
1343 // strip unmuted
1344 float left = crossover.get_value(0, i);
1345 float right = crossover.get_value(1, i);
1346 // process gain reduction
1347 strip[i].process(left, right);
1348 // sum up output
1349 outL += left;
1350 outR += right;
1352 } // process single strip
1354 // out level
1355 outL *= *params[param_level_out];
1356 outR *= *params[param_level_out];
1358 // send to output
1359 outs[0][offset] = outL;
1360 outs[1][offset] = outR;
1362 float values[] = {inL, inR, outL, outR,
1363 *params[param_bypass0] > 0.5f ? 0 : strip[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : strip[0].get_comp_level(),
1364 *params[param_bypass1] > 0.5f ? 0 : strip[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : strip[1].get_comp_level(),
1365 *params[param_bypass2] > 0.5f ? 0 : strip[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : strip[2].get_comp_level(),
1366 *params[param_bypass3] > 0.5f ? 0 : strip[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : strip[3].get_comp_level() };
1367 meters.process(values);
1369 // next sample
1370 ++offset;
1371 } // cycle trough samples
1372 } // process all strips (no bypass)
1373 meters.fall(numsamples);
1374 return outputs_mask;
1377 const gain_reduction_audio_module *multibandcompressor_audio_module::get_strip_by_param_index(int index) const
1379 // let's handle by the corresponding strip
1380 switch (index) {
1381 case param_solo0:
1382 return &strip[0];
1383 case param_solo1:
1384 return &strip[1];
1385 case param_solo2:
1386 return &strip[2];
1387 case param_solo3:
1388 return &strip[3];
1390 return NULL;
1393 bool multibandcompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1395 bool r;
1397 if (redraw)
1398 redraw = std::max(0, redraw - 1);
1400 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1401 if (m) {
1402 r = m->get_graph(subindex, data, points, context, mode);
1403 } else {
1404 r = crossover.get_graph(subindex, phase, data, points, context, mode);
1406 if ((index == param_solo0 + 11 * page and subindex == 1)
1407 or (index == param_bypass and subindex == page)) {
1408 *mode = 1;
1410 if ((subindex == 1 and index != param_bypass)
1411 or (index == param_bypass)) {
1412 if (r
1413 and ((index != param_bypass and *params[index - 1])
1414 or (index == param_bypass and *params[param_bypass0 + 11 * subindex])))
1415 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
1416 else
1417 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
1419 return r;
1422 bool multibandcompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1424 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1425 if (m)
1426 return m->get_dot(subindex, x, y, size, context);
1427 return false;
1430 bool multibandcompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1432 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1433 if (m)
1434 return m->get_gridline(subindex, pos, vertical, legend, context);
1435 if (phase) return false;
1436 return get_freq_gridline(subindex, pos, vertical, legend, context);
1439 bool multibandcompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1441 bool r;
1442 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1443 if (m) {
1444 r = m->get_layers(index, generation, layers);
1445 } else {
1446 r = crossover.get_layers(index, generation, layers);
1448 if (redraw) {
1449 layers |= LG_CACHE_GRAPH;
1450 r = true;
1452 return r;
1456 /**********************************************************************
1457 * MONO COMPRESSOR by Damien Zammit
1458 **********************************************************************/
1460 monocompressor_audio_module::monocompressor_audio_module()
1462 is_active = false;
1463 srate = 0;
1466 void monocompressor_audio_module::activate()
1468 is_active = true;
1469 // set all filters and strips
1470 monocompressor.activate();
1471 params_changed();
1473 void monocompressor_audio_module::deactivate()
1475 is_active = false;
1476 monocompressor.deactivate();
1479 void monocompressor_audio_module::params_changed()
1481 monocompressor.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_bypass], 0.f);
1484 void monocompressor_audio_module::set_sample_rate(uint32_t sr)
1486 srate = sr;
1487 monocompressor.set_sample_rate(srate);
1488 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1489 int clip[] = {param_clip_in, param_clip_out, -1};
1490 meters.init(params, meter, clip, 3, srate);
1493 uint32_t monocompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1495 bool bypass = *params[param_bypass] > 0.5f;
1496 numsamples += offset;
1497 if(bypass) {
1498 // everything bypassed
1499 while(offset < numsamples) {
1500 outs[0][offset] = ins[0][offset];
1501 float values[] = {0, 0, 1};
1502 meters.process(values);
1503 ++offset;
1505 } else {
1506 // process
1508 monocompressor.update_curve();
1510 while(offset < numsamples) {
1511 // cycle through samples
1512 float outL = 0.f;
1513 //float outR = 0.f;
1514 float inL = ins[0][offset];
1515 //float inR = ins[1][offset];
1516 float Lin = ins[0][offset];
1517 //float Rin = ins[1][offset];
1519 // in level
1520 //inR *= *params[param_level_in];
1521 inL *= *params[param_level_in];
1523 float leftAC = inL;
1524 //float rightAC = inR;
1526 monocompressor.process(leftAC);
1528 outL = leftAC;
1529 //outR = rightAC;
1531 // mix
1532 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1533 //outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1535 // send to output
1536 outs[0][offset] = outL;
1537 //outs[1][offset] = 0.f;
1539 float values[] = {inL, outL, monocompressor.get_comp_level()};
1540 meters.process(values);
1542 // next sample
1543 ++offset;
1544 } // cycle trough samples
1546 meters.fall(numsamples);
1547 return outputs_mask;
1549 bool monocompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1551 return monocompressor.get_graph(subindex, data, points, context, mode);
1554 bool monocompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1556 return monocompressor.get_dot(subindex, x, y, size, context);
1559 bool monocompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1561 return monocompressor.get_gridline(subindex, pos, vertical, legend, context);
1564 bool monocompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1566 return monocompressor.get_layers(index, generation, layers);
1569 /**********************************************************************
1570 * DEESSER by Markus Schmidt
1571 **********************************************************************/
1573 deesser_audio_module::deesser_audio_module()
1575 is_active = false;
1576 srate = 0;
1577 f1_freq_old1 = 0.f;
1578 f2_freq_old1 = 0.f;
1579 f1_level_old1 = 0.f;
1580 f2_level_old1 = 0.f;
1581 f2_q_old1 = 0.f;
1582 f1_freq_old = 0.f;
1583 f2_freq_old = 0.f;
1584 f1_level_old = 0.f;
1585 f2_level_old = 0.f;
1586 f2_q_old = 0.f;
1587 detected_led = 0;
1588 redraw_graph = true;
1591 void deesser_audio_module::activate()
1593 is_active = true;
1594 // set all filters and strips
1595 compressor.activate();
1596 params_changed();
1597 detected = 0.f;
1598 detected_led = 0.f;
1600 void deesser_audio_module::deactivate()
1602 is_active = false;
1603 compressor.deactivate();
1606 void deesser_audio_module::params_changed()
1608 // set the params of all filters
1609 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1610 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1611 or *params[param_f2_q] != f2_q_old) {
1612 float q = 0.707;
1614 hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
1615 hpR.copy_coeffs(hpL);
1616 lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
1617 lpR.copy_coeffs(lpL);
1618 pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
1619 pR.copy_coeffs(pL);
1620 f1_freq_old = *params[param_f1_freq];
1621 f1_level_old = *params[param_f1_level];
1622 f2_freq_old = *params[param_f2_freq];
1623 f2_level_old = *params[param_f2_level];
1624 f2_q_old = *params[param_f2_q];
1626 // and set the compressor module
1627 compressor.set_params((float)*params[param_laxity], (float)*params[param_laxity] * 1.33, *params[param_threshold], *params[param_ratio], 2.8, *params[param_makeup], *params[param_detection], 0.f, *params[param_bypass], 0.f);
1628 if (*params[param_f1_freq] != f1_freq_old1
1629 or *params[param_f2_freq] != f2_freq_old1
1630 or *params[param_f1_level] != f1_level_old1
1631 or *params[param_f2_level] != f2_level_old1
1632 or *params[param_f2_q] !=f2_q_old1)
1634 f1_freq_old1 = *params[param_f1_freq];
1635 f2_freq_old1 = *params[param_f2_freq];
1636 f1_level_old1 = *params[param_f1_level];
1637 f2_level_old1 = *params[param_f2_level];
1638 f2_q_old1 = *params[param_f2_q];
1639 redraw_graph = true;
1643 void deesser_audio_module::set_sample_rate(uint32_t sr)
1645 srate = sr;
1646 compressor.set_sample_rate(srate);
1647 int meter[] = {param_detected, -param_compression};
1648 int clip[] = {param_clip_out, -1};
1649 meters.init(params, meter, clip, 2, srate);
1652 uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1654 bool bypass = *params[param_bypass] > 0.5f;
1655 numsamples += offset;
1656 if(bypass) {
1657 // everything bypassed81e8da266
1658 while(offset < numsamples) {
1659 outs[0][offset] = ins[0][offset];
1660 outs[1][offset] = ins[1][offset];
1661 float values[] = {0, 1};
1662 meters.process(values);
1663 ++offset;
1665 } else {
1666 // process
1668 detected_led -= std::min(detected_led, numsamples);
1669 compressor.update_curve();
1671 while(offset < numsamples) {
1672 // cycle through samples
1673 float outL = 0.f;
1674 float outR = 0.f;
1675 float inL = ins[0][offset];
1676 float inR = ins[1][offset];
1679 float leftAC = inL;
1680 float rightAC = inR;
1681 float leftSC = inL;
1682 float rightSC = inR;
1683 float leftRC = inL;
1684 float rightRC = inR;
1685 float leftMC = inL;
1686 float rightMC = inR;
1688 leftSC = pL.process(hpL.process(leftSC));
1689 rightSC = pR.process(hpR.process(rightSC));
1690 leftMC = leftSC;
1691 rightMC = rightSC;
1693 switch ((int)*params[param_mode]) {
1694 default:
1695 case WIDE:
1696 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1697 break;
1698 case SPLIT:
1699 hpL.sanitize();
1700 hpR.sanitize();
1701 leftRC = hpL.process(leftRC);
1702 rightRC = hpR.process(rightRC);
1703 compressor.process(leftRC, rightRC, &leftSC, &rightSC);
1704 leftAC = lpL.process(leftAC);
1705 rightAC = lpR.process(rightAC);
1706 leftAC += leftRC;
1707 rightAC += rightRC;
1708 break;
1711 if(*params[param_sc_listen] > 0.f) {
1712 outL = leftMC;
1713 outR = rightMC;
1714 } else {
1715 outL = leftAC;
1716 outR = rightAC;
1719 // send to output
1720 outs[0][offset] = outL;
1721 outs[1][offset] = outR;
1723 if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) {
1724 detected_led = srate >> 3;
1726 detected = std::max(fabs(leftMC), fabs(rightMC));
1728 float values[] = {detected, compressor.get_comp_level()};
1729 meters.process(values);
1731 // next sample
1732 ++offset;
1733 } // cycle trough samples
1734 hpL.sanitize();
1735 hpR.sanitize();
1736 lpL.sanitize();
1737 lpR.sanitize();
1738 pL.sanitize();
1739 pR.sanitize();
1741 // draw meters
1742 if(params[param_detected_led] != NULL) {
1743 *params[param_detected_led] = detected_led;
1745 meters.fall(numsamples);
1746 return outputs_mask;
1750 /**********************************************************************
1751 * GATE AUDIO MODULE Damien Zammit
1752 **********************************************************************/
1754 gate_audio_module::gate_audio_module()
1756 is_active = false;
1757 srate = 0;
1760 void gate_audio_module::activate()
1762 is_active = true;
1763 // set all filters and strips
1764 gate.activate();
1765 params_changed();
1767 void gate_audio_module::deactivate()
1769 is_active = false;
1770 gate.deactivate();
1773 void gate_audio_module::params_changed()
1775 gate.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f, *params[param_range]);
1778 void gate_audio_module::set_sample_rate(uint32_t sr)
1780 srate = sr;
1781 gate.set_sample_rate(srate);
1782 int meter[] = {param_meter_in, param_meter_out, -param_gating};
1783 int clip[] = {param_clip_in, param_clip_out, -1};
1784 meters.init(params, meter, clip, 3, srate);
1787 uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1789 bool bypass = *params[param_bypass] > 0.5f;
1790 numsamples += offset;
1791 if(bypass) {
1792 // everything bypassed
1793 while(offset < numsamples) {
1794 outs[0][offset] = ins[0][offset];
1795 outs[1][offset] = ins[1][offset];
1796 float values[] = {0, 0, 1};
1797 meters.process(values);
1798 ++offset;
1800 } else {
1801 // process
1802 gate.update_curve();
1804 while(offset < numsamples) {
1805 // cycle through samples
1806 float outL = 0.f;
1807 float outR = 0.f;
1808 float inL = ins[0][offset];
1809 float inR = ins[1][offset];
1810 // in level
1811 inR *= *params[param_level_in];
1812 inL *= *params[param_level_in];
1814 float leftAC = inL;
1815 float rightAC = inR;
1817 gate.process(leftAC, rightAC);
1819 outL = leftAC;
1820 outR = rightAC;
1822 // send to output
1823 outs[0][offset] = outL;
1824 outs[1][offset] = outR;
1826 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
1827 meters.process(values);
1829 // next sample
1830 ++offset;
1831 } // cycle trough samples
1833 meters.fall(numsamples);
1834 return outputs_mask;
1836 bool gate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1838 return gate.get_graph(subindex, data, points, context, mode);
1841 bool gate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1843 return gate.get_dot(subindex, x, y, size, context);
1846 bool gate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1848 return gate.get_gridline(subindex, pos, vertical, legend, context);
1851 bool gate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1853 return gate.get_layers(index, generation, layers);
1856 /**********************************************************************
1857 * SIDECHAIN GATE by Markus Schmidt
1858 **********************************************************************/
1860 sidechaingate_audio_module::sidechaingate_audio_module()
1862 is_active = false;
1863 srate = 0;
1864 redraw_graph = true;
1865 f1_freq_old = f2_freq_old = f1_level_old = f2_level_old = 0;
1866 f1_freq_old1 = f2_freq_old1 = f1_level_old1 = f2_level_old1 = 0;
1867 sc_mode_old = sc_mode_old1 = WIDEBAND; // doesn't matter as long as it's sane
1870 void sidechaingate_audio_module::activate()
1872 is_active = true;
1873 // set all filters and strips
1874 gate.activate();
1875 params_changed();
1877 void sidechaingate_audio_module::deactivate()
1879 is_active = false;
1880 gate.deactivate();
1883 sidechaingate_audio_module::cfloat sidechaingate_audio_module::h_z(const cfloat &z) const
1885 switch ((CalfScModes)sc_mode) {
1886 default:
1887 case WIDEBAND:
1888 return false;
1889 break;
1890 case HIGHGATE_WIDE:
1891 case LOWGATE_WIDE:
1892 case WEIGHTED_1:
1893 case WEIGHTED_2:
1894 case WEIGHTED_3:
1895 case BANDPASS_2:
1896 return f1L.h_z(z) * f2L.h_z(z);
1897 break;
1898 case HIGHGATE_SPLIT:
1899 return f2L.h_z(z);
1900 break;
1901 case LOWGATE_SPLIT:
1902 case BANDPASS_1:
1903 return f1L.h_z(z);
1904 break;
1908 float sidechaingate_audio_module::freq_gain(int index, double freq) const
1910 typedef std::complex<double> cfloat;
1911 freq *= 2.0 * M_PI / srate;
1912 cfloat z = 1.0 / exp(cfloat(0.0, freq));
1914 return std::abs(h_z(z));
1917 void sidechaingate_audio_module::params_changed()
1919 // set the params of all filters
1920 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1921 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1922 or *params[param_sc_mode] != sc_mode) {
1923 float q = 0.707;
1924 switch ((CalfScModes)*params[param_sc_mode]) {
1925 default:
1926 case WIDEBAND:
1927 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1928 f1R.copy_coeffs(f1L);
1929 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1930 f2R.copy_coeffs(f2L);
1931 f1_active = 0.f;
1932 f2_active = 0.f;
1933 break;
1934 case HIGHGATE_WIDE:
1935 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1936 f1R.copy_coeffs(f1L);
1937 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1938 f2R.copy_coeffs(f2L);
1939 f1_active = 0.5f;
1940 f2_active = 1.f;
1941 break;
1942 case HIGHGATE_SPLIT:
1943 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
1944 f1R.copy_coeffs(f1L);
1945 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
1946 f2R.copy_coeffs(f2L);
1947 f1_active = 0.f;
1948 f2_active = 1.f;
1949 break;
1950 case LOWGATE_WIDE:
1951 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1952 f1R.copy_coeffs(f1L);
1953 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1954 f2R.copy_coeffs(f2L);
1955 f1_active = 1.f;
1956 f2_active = 0.5f;
1957 break;
1958 case LOWGATE_SPLIT:
1959 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
1960 f1R.copy_coeffs(f1L);
1961 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
1962 f2R.copy_coeffs(f2L);
1963 f1_active = 1.f;
1964 f2_active = 0.f;
1965 break;
1966 case WEIGHTED_1:
1967 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1968 f1R.copy_coeffs(f1L);
1969 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1970 f2R.copy_coeffs(f2L);
1971 f1_active = 0.5f;
1972 f2_active = 0.5f;
1973 break;
1974 case WEIGHTED_2:
1975 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1976 f1R.copy_coeffs(f1L);
1977 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1978 f2R.copy_coeffs(f2L);
1979 f1_active = 0.5f;
1980 f2_active = 0.5f;
1981 break;
1982 case WEIGHTED_3:
1983 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1984 f1R.copy_coeffs(f1L);
1985 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1986 f2R.copy_coeffs(f2L);
1987 f1_active = 0.5f;
1988 f2_active = 0.5f;
1989 break;
1990 case BANDPASS_1:
1991 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1992 f1R.copy_coeffs(f1L);
1993 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1994 f2R.copy_coeffs(f2L);
1995 f1_active = 1.f;
1996 f2_active = 0.f;
1997 break;
1998 case BANDPASS_2:
1999 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
2000 f1R.copy_coeffs(f1L);
2001 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
2002 f2R.copy_coeffs(f2L);
2003 f1_active = 1.f;
2004 f2_active = 1.f;
2005 break;
2007 f1_freq_old = *params[param_f1_freq];
2008 f1_level_old = *params[param_f1_level];
2009 f2_freq_old = *params[param_f2_freq];
2010 f2_level_old = *params[param_f2_level];
2011 sc_mode = (CalfScModes)*params[param_sc_mode];
2013 // light LED's
2014 if(params[param_f1_active] != NULL) {
2015 *params[param_f1_active] = f1_active;
2017 if(params[param_f2_active] != NULL) {
2018 *params[param_f2_active] = f2_active;
2020 // and set the expander module
2021 gate.set_params(*params[param_attack], *params[param_release], *params[param_threshold], *params[param_ratio], *params[param_knee], *params[param_makeup], *params[param_detection], *params[param_stereo_link], *params[param_bypass], 0.f, *params[param_range]);
2023 if (*params[param_f1_freq] != f1_freq_old1
2024 or *params[param_f2_freq] != f2_freq_old1
2025 or *params[param_f1_level] != f1_level_old1
2026 or *params[param_f2_level] != f2_level_old1
2027 or *params[param_sc_mode] != sc_mode_old1)
2029 f1_freq_old1 = *params[param_f1_freq];
2030 f2_freq_old1 = *params[param_f2_freq];
2031 f1_level_old1 = *params[param_f1_level];
2032 f2_level_old1 = *params[param_f2_level];
2033 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
2034 redraw_graph = true;
2038 void sidechaingate_audio_module::set_sample_rate(uint32_t sr)
2040 srate = sr;
2041 gate.set_sample_rate(srate);
2042 int meter[] = {param_meter_in, param_meter_out, -param_gating};
2043 int clip[] = {param_clip_in, param_clip_out, -1};
2044 meters.init(params, meter, clip, 3, srate);
2047 uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2049 bool bypass = *params[param_bypass] > 0.5f;
2050 numsamples += offset;
2051 if(bypass) {
2052 // everything bypassed
2053 while(offset < numsamples) {
2054 outs[0][offset] = ins[0][offset];
2055 outs[1][offset] = ins[1][offset];
2056 float values[] = {0, 0, 1};
2057 meters.process(values);
2058 ++offset;
2060 } else {
2061 // process
2063 gate.update_curve();
2065 while(offset < numsamples) {
2066 // cycle through samples
2067 float outL = 0.f;
2068 float outR = 0.f;
2069 float inL = ins[0][offset];
2070 float inR = ins[1][offset];
2072 float in2L = ins[2] ? ins[2][offset] : 0;
2073 float in2R = ins[3] ? ins[3][offset] : 0;
2075 // in level
2076 inR *= *params[param_level_in];
2077 inL *= *params[param_level_in];
2079 float leftAC = inL;
2080 float rightAC = inR;
2081 float leftSC = inL;
2082 float rightSC = inR;
2083 float leftMC = inL;
2084 float rightMC = inR;
2086 if (*params[param_sc_route] > 0.5) {
2087 leftAC = inL;
2088 rightAC = inR;
2089 leftSC = in2L * *params[param_sc_level];
2090 rightSC = in2R * *params[param_sc_level];
2091 leftMC = inL;
2092 rightMC = inR;
2095 switch ((CalfScModes)*params[param_sc_mode]) {
2096 default:
2097 case WIDEBAND:
2098 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2099 leftMC = leftSC;
2100 rightMC = rightSC;
2101 break;
2102 case HIGHGATE_WIDE:
2103 case LOWGATE_WIDE:
2104 case WEIGHTED_1:
2105 case WEIGHTED_2:
2106 case WEIGHTED_3:
2107 case BANDPASS_2:
2108 leftSC = f2L.process(f1L.process(leftSC));
2109 rightSC = f2R.process(f1R.process(rightSC));
2110 leftMC = leftSC;
2111 rightMC = rightSC;
2112 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2113 break;
2114 case HIGHGATE_SPLIT:
2115 leftSC = f2L.process(leftSC);
2116 rightSC = f2R.process(rightSC);
2117 leftMC = leftSC;
2118 rightMC = rightSC;
2119 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2120 leftAC = f1L.process(leftAC);
2121 rightAC = f1R.process(rightAC);
2122 leftAC += leftSC;
2123 rightAC += rightSC;
2124 break;
2125 case LOWGATE_SPLIT:
2126 leftSC = f1L.process(leftSC);
2127 rightSC = f1R.process(rightSC);
2128 leftMC = leftSC;
2129 rightMC = rightSC;
2130 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2131 leftAC = f2L.process(leftAC);
2132 rightAC = f2R.process(rightAC);
2133 leftAC += leftSC;
2134 rightAC += rightSC;
2135 break;
2136 case BANDPASS_1:
2137 leftSC = f1L.process(leftSC);
2138 rightSC = f1R.process(rightSC);
2139 leftMC = leftSC;
2140 rightMC = rightSC;
2141 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2142 break;
2145 if(*params[param_sc_listen] > 0.f) {
2146 outL = leftMC;
2147 outR = rightMC;
2148 } else {
2149 outL = leftAC;
2150 outR = rightAC;
2153 // send to output
2154 outs[0][offset] = outL;
2155 outs[1][offset] = outR;
2157 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
2158 meters.process(values);
2160 // next sample
2161 ++offset;
2162 } // cycle trough samples
2163 f1L.sanitize();
2164 f1R.sanitize();
2165 f2L.sanitize();
2166 f2R.sanitize();
2169 meters.fall(numsamples);
2170 return outputs_mask;
2172 bool sidechaingate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2174 if (!is_active or phase)
2175 return false;
2176 if (index == param_sc_listen && !subindex) {
2177 return ::get_graph(*this, subindex, data, points);
2178 } else if(index == param_bypass) {
2179 return gate.get_graph(subindex, data, points, context, mode);
2181 return false;
2184 bool sidechaingate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2186 if (!is_active or !phase)
2187 return false;
2188 if (index == param_bypass) {
2189 return gate.get_dot(subindex, x, y, size, context);
2191 return false;
2194 bool sidechaingate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2196 if (!is_active or phase)
2197 return false;
2198 if (index == param_bypass) {
2199 return gate.get_gridline(subindex, pos, vertical, legend, context);
2200 } else {
2201 return get_freq_gridline(subindex, pos, vertical, legend, context);
2203 return false;
2205 bool sidechaingate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2207 if(index == param_bypass)
2208 return gate.get_layers(index, generation, layers);
2209 bool redraw = redraw_graph || !generation;
2210 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
2211 redraw_graph = false;
2212 return redraw;
2216 /**********************************************************************
2217 * MULTIBAND GATE by Markus Schmidt
2218 **********************************************************************/
2220 multibandgate_audio_module::multibandgate_audio_module()
2222 is_active = false;
2223 srate = 0;
2224 mode = 0;
2225 redraw = 0;
2226 page = 0;
2227 bypass = 0;
2228 crossover.init(2, 4, 44100);
2231 void multibandgate_audio_module::activate()
2233 is_active = true;
2234 // set all filters and strips
2235 params_changed();
2236 // activate all strips
2237 for (int j = 0; j < strips; j ++) {
2238 gate[j].activate();
2239 gate[j].id = j;
2243 void multibandgate_audio_module::deactivate()
2245 is_active = false;
2246 // deactivate all strips
2247 for (int j = 0; j < strips; j ++) {
2248 gate[j].deactivate();
2252 void multibandgate_audio_module::params_changed()
2254 // determine mute/solo states
2255 solo[0] = *params[param_solo0] > 0.f ? true : false;
2256 solo[1] = *params[param_solo1] > 0.f ? true : false;
2257 solo[2] = *params[param_solo2] > 0.f ? true : false;
2258 solo[3] = *params[param_solo3] > 0.f ? true : false;
2259 no_solo = (*params[param_solo0] > 0.f ||
2260 *params[param_solo1] > 0.f ||
2261 *params[param_solo2] > 0.f ||
2262 *params[param_solo3] > 0.f) ? false : true;
2264 int m = *params[param_mode];
2265 if (m != mode) {
2266 mode = *params[param_mode];
2269 int p = (int)*params[param_notebook];
2270 if (p != page) {
2271 page = p;
2272 redraw = strips * 2 + strips;
2275 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
2276 if (b != bypass) {
2277 redraw = strips * 2 + strips;
2278 bypass = b;
2281 crossover.set_mode(mode + 1);
2282 crossover.set_filter(0, *params[param_freq0]);
2283 crossover.set_filter(1, *params[param_freq1]);
2284 crossover.set_filter(2, *params[param_freq2]);
2286 // set the params of all strips
2287 gate[0].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], !(solo[0] || no_solo), *params[param_range0]);
2288 gate[1].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], !(solo[1] || no_solo), *params[param_range1]);
2289 gate[2].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], !(solo[2] || no_solo), *params[param_range2]);
2290 gate[3].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], !(solo[3] || no_solo), *params[param_range3]);
2293 void multibandgate_audio_module::set_sample_rate(uint32_t sr)
2295 srate = sr;
2296 // set srate of all strips
2297 for (int j = 0; j < strips; j ++) {
2298 gate[j].set_sample_rate(srate);
2300 // set srate of crossover
2301 crossover.set_sample_rate(srate);
2302 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
2303 param_output0, -param_gating0,
2304 param_output1, -param_gating1,
2305 param_output2, -param_gating2,
2306 param_output3, -param_gating3 };
2307 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
2308 meters.init(params, meter, clip, 12, srate);
2311 uint32_t multibandgate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2313 bool bypass = *params[param_bypass] > 0.5f;
2314 numsamples += offset;
2315 for (int i = 0; i < strips; i++)
2316 gate[i].update_curve();
2317 if(bypass) {
2318 // everything bypassed
2319 while(offset < numsamples) {
2320 outs[0][offset] = ins[0][offset];
2321 outs[1][offset] = ins[1][offset];
2322 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
2323 meters.process(values);
2324 ++offset;
2326 } else {
2327 // process all strips
2328 while(offset < numsamples) {
2329 // cycle through samples
2330 float inL = ins[0][offset];
2331 float inR = ins[1][offset];
2332 // in level
2333 inR *= *params[param_level_in];
2334 inL *= *params[param_level_in];
2335 // process crossover
2336 xin[0] = inL;
2337 xin[1] = inR;
2338 crossover.process(xin);
2339 // out vars
2340 float outL = 0.f;
2341 float outR = 0.f;
2342 for (int i = 0; i < strips; i ++) {
2343 // cycle trough strips
2344 if (solo[i] || no_solo) {
2345 // strip unmuted
2346 float left = crossover.get_value(0, i);
2347 float right = crossover.get_value(1, i);
2348 gate[i].process(left, right);
2349 // sum up output
2350 outL += left;
2351 outR += right;
2353 } // process single strip
2355 // out level
2356 outL *= *params[param_level_out];
2357 outR *= *params[param_level_out];
2359 // send to output
2360 outs[0][offset] = outL;
2361 outs[1][offset] = outR;
2363 float values[] = {inL, inR, outL, outR,
2364 *params[param_bypass0] > 0.5f ? 0 : gate[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : gate[0].get_expander_level(),
2365 *params[param_bypass1] > 0.5f ? 0 : gate[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : gate[1].get_expander_level(),
2366 *params[param_bypass2] > 0.5f ? 0 : gate[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : gate[2].get_expander_level(),
2367 *params[param_bypass3] > 0.5f ? 0 : gate[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : gate[3].get_expander_level() };
2368 meters.process(values);
2370 // next sample
2371 ++offset;
2372 } // cycle trough samples
2374 } // process all strips (no bypass)
2375 meters.fall(numsamples);
2376 return outputs_mask;
2379 const expander_audio_module *multibandgate_audio_module::get_strip_by_param_index(int index) const
2381 // let's handle by the corresponding strip
2382 switch (index) {
2383 case param_solo0:
2384 return &gate[0];
2385 case param_solo1:
2386 return &gate[1];
2387 case param_solo2:
2388 return &gate[2];
2389 case param_solo3:
2390 return &gate[3];
2392 return NULL;
2395 bool multibandgate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2397 bool r;
2398 if (redraw)
2399 redraw = std::max(0, redraw - 1);
2401 const expander_audio_module *m = get_strip_by_param_index(index);
2402 if (m) {
2403 r = m->get_graph(subindex, data, points, context, mode);
2404 } else {
2405 r = crossover.get_graph(subindex, phase, data, points, context, mode);
2407 if ((index == param_solo0 + 12 * page and subindex == 1)
2408 or (index == param_bypass and subindex == page)) {
2409 *mode = 1;
2411 if ((subindex == 1 and index != param_bypass)
2412 or (index == param_bypass)) {
2413 if (r
2414 and ((index != param_bypass and *params[index - 1])
2415 or (index == param_bypass and *params[param_bypass0 + 12 * subindex])))
2416 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
2417 else
2418 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
2420 return r;
2423 bool multibandgate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2425 const expander_audio_module *m = get_strip_by_param_index(index);
2426 if (m)
2427 return m->get_dot(subindex, x, y, size, context);
2428 return false;
2431 bool multibandgate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2433 const expander_audio_module *m = get_strip_by_param_index(index);
2434 if (m)
2435 return m->get_gridline(subindex, pos, vertical, legend, context);
2436 if (phase) return false;
2437 return get_freq_gridline(subindex, pos, vertical, legend, context);
2440 bool multibandgate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2442 bool r;
2443 const expander_audio_module *m = get_strip_by_param_index(index);
2444 if (m) {
2445 r = m->get_layers(index, generation, layers);
2446 } else {
2447 r = crossover.get_layers(index, generation, layers);
2449 if (redraw) {
2450 layers |= LG_CACHE_GRAPH;
2451 r = true;
2453 return r;
2457 /**********************************************************************
2458 * TRANSIENT DESIGNER by Christian Holschuh and Markus Schmidt
2459 **********************************************************************/
2462 transientdesigner_audio_module::transientdesigner_audio_module() {
2463 active = false;
2464 pixels = 0;
2465 pbuffer_pos = 0;
2466 pbuffer_sample = 0;
2467 pbuffer_size = 0;
2468 attcount = 0;
2469 attacked = false;
2470 attack_pos = 0;
2471 display_old = 0.f;
2472 pbuffer_available = false;
2473 last_drawn = 0;
2474 display_max = pow(2,-12);
2475 transients.set_channels(channels);
2477 transientdesigner_audio_module::~transientdesigner_audio_module()
2479 free(pbuffer);
2481 void transientdesigner_audio_module::activate() {
2482 active = true;
2485 void transientdesigner_audio_module::deactivate() {
2486 active = false;
2489 void transientdesigner_audio_module::params_changed() {
2490 if (*params[param_display] != display_old) {
2491 dsp::zero(pbuffer, (int)(pixels * 2));
2492 display_old = *params[param_display];
2494 transients.set_params(*params[param_attack_time],
2495 *params[param_attack_boost],
2496 *params[param_release_time],
2497 *params[param_release_boost],
2498 *params[param_sustain_threshold],
2499 *params[param_lookahead],
2500 *params[param_mix]);
2503 uint32_t transientdesigner_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
2504 for(uint32_t i = offset; i < offset + numsamples; i++) {
2505 float L = ins[0][i];
2506 float R = ins[1][i];
2507 meter_inL = 0.f;
2508 meter_inR = 0.f;
2509 meter_outL = 0.f;
2510 meter_outR = 0.f;
2511 float s = (fabs(L) + fabs(R)) / 2;
2512 if(*params[param_bypass] > 0.5) {
2513 outs[0][i] = ins[0][i];
2514 outs[1][i] = ins[1][i];
2516 } else {
2517 // levels in
2518 L *= *params[param_level_in];
2519 R *= *params[param_level_in];
2521 // GUI stuff
2522 meter_inL = L;
2523 meter_inR = R;
2525 // transient designer
2526 float values[] = {L, R};
2527 transients.process(values);
2528 L = values[0];
2529 R = values[1];
2531 // levels out
2532 L *= *params[param_level_out];
2533 R *= *params[param_level_out];
2535 // output
2536 outs[0][i] = L;
2537 outs[1][i] = R;
2539 meter_outL = L;
2540 meter_outR = R;
2542 // fill pixel buffer
2543 if (pbuffer_available) {
2544 // sanitize the buffer position if enough samples have
2545 // been captured. This is recognized by a negative value
2546 for (int i = 0; i < 5; i++) {
2547 pbuffer[pbuffer_pos + i] = std::max(pbuffer[pbuffer_pos + i], 0.f);
2550 // add samples to the buffer at the actual address
2551 pbuffer[pbuffer_pos] = std::max(s, pbuffer[pbuffer_pos]);
2552 pbuffer[pbuffer_pos + 1] = std::max((float)(fabs(L) + fabs(R)), (float)pbuffer[pbuffer_pos + 1]);
2553 pbuffer[pbuffer_pos + 2] = transients.envelope;
2554 pbuffer[pbuffer_pos + 3] = transients.attack;
2555 pbuffer[pbuffer_pos + 4] = transients.release;
2557 pbuffer_sample += 1;
2559 if (pbuffer_sample >= (int)(srate * *params[param_display] / 1000.f / pixels)) {
2560 // we captured enough samples for one pixel on this
2561 // address. to keep track of the finalization invert
2562 // its values as a marker to sanitize in the next
2563 // cycle before adding samples again
2564 pbuffer[pbuffer_pos] *= -1.f * *params[param_level_in];
2565 pbuffer[pbuffer_pos + 1] /= -2.f;
2567 // advance the buffer position
2568 pbuffer_pos = (pbuffer_pos + 5) % pbuffer_size;
2570 // reset sample counter
2571 pbuffer_sample = 0;
2575 attcount += 1;
2576 if ( transients.envelope == transients.release
2577 and transients.envelope > *params[param_display_threshold]
2578 and attcount >= srate / 100
2579 and pbuffer_available) {
2580 int diff = (int)(srate / 10 / pixels);
2581 diff += diff & 1;
2582 attack_pos = (pbuffer_pos - diff + pbuffer_size) % pbuffer_size;
2583 attcount = 0;
2585 float values[] = {meter_inL, meter_inR, meter_outL, meter_outR};
2586 meters.process(values);
2588 meters.fall(numsamples);
2589 return outputs_mask;
2592 void transientdesigner_audio_module::set_sample_rate(uint32_t sr)
2594 srate = sr;
2595 attcount = srate / 5;
2596 transients.set_sample_rate(srate);
2597 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
2598 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
2599 meters.init(params, meter, clip, 4, srate);
2601 bool transientdesigner_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2603 if (points <= 0)
2604 return false;
2605 if (points != pixels) {
2606 // the zoom level changed or it's the first time we want to draw
2607 // some graphs
2609 // buffer size is the amount of pixels for the max display value
2610 // if drawn in the min display zoom level multiplied by 5 for
2611 // keeping the input and the output fabs signals and all graphs
2612 // of the envelopes
2613 pbuffer_size = (int)(points * 5.f * 100.f);
2614 // create array
2615 pbuffer = (float*) calloc(pbuffer_size, sizeof(float));
2617 // sanitize some indexes and addresses
2618 pbuffer_pos = 0;
2619 pbuffer_sample = 0;
2620 pbuffer_draw = 0;
2621 pbuffer_available = true;
2622 pixels = points;
2624 // check if threshold is above minimum - we want to see trigger hold
2625 bool hold = *params[param_display_threshold] > display_max;
2626 // set the address to start from in both drawing cycles
2627 // to amount of pixels before pbuffer_pos or to attack_pos
2628 if (subindex == 0) {
2629 int pos = hold ? attack_pos : pbuffer_pos;
2630 pbuffer_draw = *params[param_display_threshold] > display_max ? pos
2631 : (pbuffer_size + pos - pixels * 5) % pbuffer_size;
2634 // get outa here if max graph is reached
2635 if (last_drawn >= 5) {
2636 last_drawn = 0;
2637 return false;
2640 // get the next graph to draw leaving out inactive
2641 while (last_drawn < 5 and !*params[param_input + last_drawn] > 0.5)
2642 last_drawn ++;
2644 // get outa here if max graph is reached
2645 if (last_drawn >= 5) {
2646 last_drawn = 0;
2647 return false;
2649 if (!last_drawn) {
2650 // input is drawn as bars with less opacity
2651 *mode = 1;
2652 context->set_source_rgba(0.15, 0.2, 0.0, 0.2);
2653 } else if (last_drawn == 1) {
2654 // output is a precise line
2655 context->set_line_width(0.75);
2656 } else {
2657 // envelope, attack and release are dotted
2658 set_channel_dash(context, last_drawn - 2);
2659 context->set_line_width(1);
2662 // draw curve
2663 for (int i = 0; i <= points; i++) {
2664 int pos = (pbuffer_draw + i * 5) % pbuffer_size + last_drawn;
2665 if (hold
2666 and ((pos > pbuffer_pos and ((pbuffer_pos > attack_pos and pos > attack_pos)
2667 or (pbuffer_pos < attack_pos and pos < attack_pos)))
2668 or (pbuffer_pos > attack_pos and pos < attack_pos))) {
2669 // we are drawing trigger hold stuff outside the hold window
2670 // so we don't want to see old data - zero it out.
2671 data[i] = dB_grid(2.51e-10, 128, 0.6);
2672 } else {
2673 // draw normally
2674 data[i] = dB_grid(fabs(pbuffer[pos]) + 2.51e-10, 128, 0.6);
2677 last_drawn ++;
2678 return true;
2680 bool transientdesigner_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2682 if (subindex >= 16 or phase)
2683 return false;
2684 float gain = 16.f / (1 << subindex);
2685 pos = dB_grid(gain, 128, 0.6);
2686 context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2);
2687 if (!(subindex & 1) and subindex) {
2688 std::stringstream ss;
2689 ss << (24 - 6 * subindex) << " dB";
2690 legend = ss.str();
2692 return true;
2695 bool transientdesigner_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2697 layers = LG_REALTIME_GRAPH | (generation ? 0 : LG_CACHE_GRID);
2698 return true;