Crusher: fix UI crash
[calf.git] / src / modules_comp.cpp
bloba26758bead1629ffa264d25cc06238901185d51d
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 bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
767 numsamples += offset;
768 if(bypassed) {
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
780 uint32_t orig_offset = offset;
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
818 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
820 meters.fall(numsamples);
821 return outputs_mask;
823 bool compressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
825 return compressor.get_graph(subindex, data, points, context, mode);
828 bool compressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
830 return compressor.get_dot(subindex, x, y, size, context);
833 bool compressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
835 return compressor.get_gridline(subindex, pos, vertical, legend, context);
838 bool compressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
840 return compressor.get_layers(index, generation, layers);
843 /**********************************************************************
844 * SIDECHAIN COMPRESSOR by Markus Schmidt
845 **********************************************************************/
847 sidechaincompressor_audio_module::sidechaincompressor_audio_module()
849 is_active = false;
850 srate = 0;
851 f1_freq_old1 = 0.f;
852 f2_freq_old1 = 0.f;
853 f1_level_old1 = 0.f;
854 f2_level_old1 = 0.f;
855 f1_freq_old = 0.f;
856 f2_freq_old = 0.f;
857 f1_level_old = 0.f;
858 f2_level_old = 0.f;
859 sc_mode_old1 = WIDEBAND;
860 redraw_graph = true;
863 void sidechaincompressor_audio_module::activate()
865 is_active = true;
866 // set all filters and strips
867 compressor.activate();
868 params_changed();
870 void sidechaincompressor_audio_module::deactivate()
872 is_active = false;
873 compressor.deactivate();
876 sidechaincompressor_audio_module::cfloat sidechaincompressor_audio_module::h_z(const cfloat &z) const
878 switch ((CalfScModes)sc_mode) {
879 default:
880 case WIDEBAND:
881 return false;
882 break;
883 case DEESSER_WIDE:
884 case DERUMBLER_WIDE:
885 case WEIGHTED_1:
886 case WEIGHTED_2:
887 case WEIGHTED_3:
888 case BANDPASS_2:
889 return f1L.h_z(z) * f2L.h_z(z);
890 break;
891 case DEESSER_SPLIT:
892 return f2L.h_z(z);
893 break;
894 case DERUMBLER_SPLIT:
895 case BANDPASS_1:
896 return f1L.h_z(z);
897 break;
901 float sidechaincompressor_audio_module::freq_gain(int index, double freq) const
903 typedef std::complex<double> cfloat;
904 freq *= 2.0 * M_PI / srate;
905 cfloat z = 1.0 / exp(cfloat(0.0, freq));
907 return std::abs(h_z(z));
910 void sidechaincompressor_audio_module::params_changed()
912 // set the params of all filters
913 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
914 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
915 or *params[param_sc_mode] != sc_mode) {
916 float q = 0.707;
917 switch ((CalfScModes)*params[param_sc_mode]) {
918 default:
919 case WIDEBAND:
920 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
921 f1R.copy_coeffs(f1L);
922 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
923 f2R.copy_coeffs(f2L);
924 f1_active = 0.f;
925 f2_active = 0.f;
926 break;
927 case DEESSER_WIDE:
928 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
929 f1R.copy_coeffs(f1L);
930 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
931 f2R.copy_coeffs(f2L);
932 f1_active = 0.5f;
933 f2_active = 1.f;
934 break;
935 case DEESSER_SPLIT:
936 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
937 f1R.copy_coeffs(f1L);
938 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
939 f2R.copy_coeffs(f2L);
940 f1_active = 0.f;
941 f2_active = 1.f;
942 break;
943 case DERUMBLER_WIDE:
944 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
945 f1R.copy_coeffs(f1L);
946 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
947 f2R.copy_coeffs(f2L);
948 f1_active = 1.f;
949 f2_active = 0.5f;
950 break;
951 case DERUMBLER_SPLIT:
952 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
953 f1R.copy_coeffs(f1L);
954 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
955 f2R.copy_coeffs(f2L);
956 f1_active = 1.f;
957 f2_active = 0.f;
958 break;
959 case WEIGHTED_1:
960 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
961 f1R.copy_coeffs(f1L);
962 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
963 f2R.copy_coeffs(f2L);
964 f1_active = 0.5f;
965 f2_active = 0.5f;
966 break;
967 case WEIGHTED_2:
968 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
969 f1R.copy_coeffs(f1L);
970 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
971 f2R.copy_coeffs(f2L);
972 f1_active = 0.5f;
973 f2_active = 0.5f;
974 break;
975 case WEIGHTED_3:
976 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
977 f1R.copy_coeffs(f1L);
978 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
979 f2R.copy_coeffs(f2L);
980 f1_active = 0.5f;
981 f2_active = 0.5f;
982 break;
983 case BANDPASS_1:
984 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
985 f1R.copy_coeffs(f1L);
986 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
987 f2R.copy_coeffs(f2L);
988 f1_active = 1.f;
989 f2_active = 0.f;
990 break;
991 case BANDPASS_2:
992 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
993 f1R.copy_coeffs(f1L);
994 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
995 f2R.copy_coeffs(f2L);
996 f1_active = 1.f;
997 f2_active = 1.f;
998 break;
1000 f1_freq_old = *params[param_f1_freq];
1001 f1_level_old = *params[param_f1_level];
1002 f2_freq_old = *params[param_f2_freq];
1003 f2_level_old = *params[param_f2_level];
1004 sc_mode = (CalfScModes)*params[param_sc_mode];
1006 // light LED's
1007 if(params[param_f1_active] != NULL) {
1008 *params[param_f1_active] = f1_active;
1010 if(params[param_f2_active] != NULL) {
1011 *params[param_f2_active] = f2_active;
1013 // and set the compressor module
1014 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);
1016 if (*params[param_f1_freq] != f1_freq_old1
1017 or *params[param_f2_freq] != f2_freq_old1
1018 or *params[param_f1_level] != f1_level_old1
1019 or *params[param_f2_level] != f2_level_old1
1020 or *params[param_sc_mode] != sc_mode_old1)
1022 f1_freq_old1 = *params[param_f1_freq];
1023 f2_freq_old1 = *params[param_f2_freq];
1024 f1_level_old1 = *params[param_f1_level];
1025 f2_level_old1 = *params[param_f2_level];
1026 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
1027 redraw_graph = true;
1031 void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr)
1033 srate = sr;
1034 compressor.set_sample_rate(srate);
1035 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1036 int clip[] = {param_clip_in, param_clip_out, -1};
1037 meters.init(params, meter, clip, 3, srate);
1040 uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1042 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1043 numsamples += offset;
1044 if(bypassed) {
1045 // everything bypassed
1046 while(offset < numsamples) {
1047 outs[0][offset] = ins[0][offset];
1048 outs[1][offset] = ins[1][offset];
1049 float values[] = {0, 0, 1};
1050 meters.process(values);
1051 ++offset;
1053 } else {
1054 // process
1055 uint32_t orig_offset = offset;
1056 compressor.update_curve();
1058 while(offset < numsamples) {
1059 // cycle through samples
1060 float outL = 0.f;
1061 float outR = 0.f;
1062 float inL = ins[0][offset];
1063 float inR = ins[1][offset];
1064 float Lin = ins[0][offset];
1065 float Rin = ins[1][offset];
1067 float in2L = ins[2] ? ins[2][offset] : 0;
1068 float in2R = ins[3] ? ins[3][offset] : 0;
1070 // in level
1071 inR *= *params[param_level_in];
1072 inL *= *params[param_level_in];
1074 float leftAC = inL;
1075 float rightAC = inR;
1076 float leftSC = inL;
1077 float rightSC = inR;
1078 float leftMC = inL;
1079 float rightMC = inR;
1081 if (*params[param_sc_route] > 0.5) {
1082 leftAC = inL;
1083 rightAC = inR;
1084 leftSC = in2L * *params[param_sc_level];
1085 rightSC = in2R * *params[param_sc_level];
1086 leftMC = inL;
1087 rightMC = inR;
1090 switch ((CalfScModes)*params[param_sc_mode]) {
1091 default:
1092 case WIDEBAND:
1093 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1094 leftMC = leftSC;
1095 rightMC = rightSC;
1096 break;
1097 case DEESSER_WIDE:
1098 case DERUMBLER_WIDE:
1099 case WEIGHTED_1:
1100 case WEIGHTED_2:
1101 case WEIGHTED_3:
1102 case BANDPASS_2:
1103 leftSC = f2L.process(f1L.process(leftSC));
1104 rightSC = f2R.process(f1R.process(rightSC));
1105 leftMC = leftSC;
1106 rightMC = rightSC;
1107 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1108 break;
1109 case DEESSER_SPLIT:
1110 leftSC = f2L.process(leftSC);
1111 rightSC = f2R.process(rightSC);
1112 leftMC = leftSC;
1113 rightMC = rightSC;
1114 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1115 leftAC = f1L.process(leftAC);
1116 rightAC = f1R.process(rightAC);
1117 leftAC += leftSC;
1118 rightAC += rightSC;
1119 break;
1120 case DERUMBLER_SPLIT:
1121 leftSC = f1L.process(leftSC);
1122 rightSC = f1R.process(rightSC);
1123 leftMC = leftSC;
1124 rightMC = rightSC;
1125 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1126 leftAC = f2L.process(leftAC);
1127 rightAC = f2R.process(rightAC);
1128 leftAC += leftSC;
1129 rightAC += rightSC;
1130 break;
1131 case BANDPASS_1:
1132 leftSC = f1L.process(leftSC);
1133 rightSC = f1R.process(rightSC);
1134 leftMC = leftSC;
1135 rightMC = rightSC;
1136 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1137 break;
1140 if(*params[param_sc_listen] > 0.f) {
1141 outL = leftMC;
1142 outR = rightMC;
1143 } else {
1144 outL = leftAC;
1145 outR = rightAC;
1146 // mix
1147 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1148 outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1151 // send to output
1152 outs[0][offset] = outL;
1153 outs[1][offset] = outR;
1155 float values[] = {std::max(inL, inR), std::max(outL, outR), compressor.get_comp_level()};
1156 meters.process(values);
1158 // next sample
1159 ++offset;
1160 } // cycle trough samples
1161 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
1162 f1L.sanitize();
1163 f1R.sanitize();
1164 f2L.sanitize();
1165 f2R.sanitize();
1167 meters.fall(numsamples);
1168 return outputs_mask;
1170 bool sidechaincompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1172 if (!is_active or phase)
1173 return false;
1174 if (index == param_sc_listen && !subindex) {
1175 return ::get_graph(*this, subindex, data, points);
1176 } else if(index == param_bypass) {
1177 return compressor.get_graph(subindex, data, points, context, mode);
1179 return false;
1182 bool sidechaincompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1184 if (!is_active or !phase)
1185 return false;
1186 if (index == param_bypass) {
1187 return compressor.get_dot(subindex, x, y, size, context);
1189 return false;
1192 bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1194 if (!is_active or phase)
1195 return false;
1196 if (index == param_bypass) {
1197 return compressor.get_gridline(subindex, pos, vertical, legend, context);
1198 } else {
1199 return get_freq_gridline(subindex, pos, vertical, legend, context);
1201 return false;
1204 bool sidechaincompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1206 if(index == param_bypass)
1207 return compressor.get_layers(index, generation, layers);
1208 bool redraw = redraw_graph || !generation;
1209 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
1210 redraw_graph = false;
1211 return redraw;
1214 /**********************************************************************
1215 * MULTIBAND COMPRESSOR by Markus Schmidt
1216 **********************************************************************/
1218 multibandcompressor_audio_module::multibandcompressor_audio_module()
1220 is_active = false;
1221 srate = 0;
1222 mode = 0;
1223 redraw = 0;
1224 page = 0;
1225 bypass_ = 0;
1226 crossover.init(2, 4, 44100);
1229 void multibandcompressor_audio_module::activate()
1231 is_active = true;
1232 // set all filters and strips
1233 params_changed();
1234 // activate all strips
1235 for (int j = 0; j < strips; j ++) {
1236 strip[j].activate();
1237 strip[j].id = j;
1241 void multibandcompressor_audio_module::deactivate()
1243 is_active = false;
1244 // deactivate all strips
1245 for (int j = 0; j < strips; j ++) {
1246 strip[j].deactivate();
1250 void multibandcompressor_audio_module::params_changed()
1252 // determine mute/solo states
1253 solo[0] = *params[param_solo0] > 0.f ? true : false;
1254 solo[1] = *params[param_solo1] > 0.f ? true : false;
1255 solo[2] = *params[param_solo2] > 0.f ? true : false;
1256 solo[3] = *params[param_solo3] > 0.f ? true : false;
1257 no_solo = (*params[param_solo0] > 0.f ||
1258 *params[param_solo1] > 0.f ||
1259 *params[param_solo2] > 0.f ||
1260 *params[param_solo3] > 0.f) ? false : true;
1263 int m = *params[param_mode];
1264 if (m != mode) {
1265 mode = *params[param_mode];
1268 int p = (int)*params[param_notebook];
1269 if (p != page) {
1270 page = p;
1271 redraw = strips * 2 + strips;
1274 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
1275 if (b != bypass_) {
1276 redraw = strips * 2 + strips;
1277 bypass_ = b;
1280 crossover.set_mode(mode + 1);
1281 crossover.set_filter(0, *params[param_freq0]);
1282 crossover.set_filter(1, *params[param_freq1]);
1283 crossover.set_filter(2, *params[param_freq2]);
1285 // set the params of all strips
1286 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));
1287 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));
1288 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));
1289 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));
1292 void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
1294 srate = sr;
1295 // set srate of all strips
1296 for (int j = 0; j < strips; j ++) {
1297 strip[j].set_sample_rate(srate);
1299 // set srate of crossover
1300 crossover.set_sample_rate(srate);
1301 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
1302 param_output0, -param_compression0,
1303 param_output1, -param_compression1,
1304 param_output2, -param_compression2,
1305 param_output3, -param_compression3 };
1306 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
1307 meters.init(params, meter, clip, 12, srate);
1310 uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1312 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1313 numsamples += offset;
1315 for (int i = 0; i < strips; i++)
1316 strip[i].update_curve();
1317 if(bypassed) {
1318 // everything bypassed
1319 while(offset < numsamples) {
1320 outs[0][offset] = ins[0][offset];
1321 outs[1][offset] = ins[1][offset];
1322 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
1323 meters.process(values);
1324 ++offset;
1326 } else {
1327 // process all strips
1328 uint32_t orig_offset = offset;
1329 while(offset < numsamples) {
1330 // cycle through samples
1331 float inL = ins[0][offset];
1332 float inR = ins[1][offset];
1333 // in level
1334 inR *= *params[param_level_in];
1335 inL *= *params[param_level_in];
1336 // process crossover
1337 xin[0] = inL;
1338 xin[1] = inR;
1339 crossover.process(xin);
1340 // out vars
1341 float outL = 0.f;
1342 float outR = 0.f;
1343 for (int i = 0; i < strips; i ++) {
1344 // cycle trough strips
1345 if (solo[i] || no_solo) {
1346 // strip unmuted
1347 float left = crossover.get_value(0, i);
1348 float right = crossover.get_value(1, i);
1349 // process gain reduction
1350 strip[i].process(left, right);
1351 // sum up output
1352 outL += left;
1353 outR += right;
1355 } // process single strip
1357 // out level
1358 outL *= *params[param_level_out];
1359 outR *= *params[param_level_out];
1361 // send to output
1362 outs[0][offset] = outL;
1363 outs[1][offset] = outR;
1365 float values[] = {inL, inR, outL, outR,
1366 *params[param_bypass0] > 0.5f ? 0 : strip[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : strip[0].get_comp_level(),
1367 *params[param_bypass1] > 0.5f ? 0 : strip[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : strip[1].get_comp_level(),
1368 *params[param_bypass2] > 0.5f ? 0 : strip[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : strip[2].get_comp_level(),
1369 *params[param_bypass3] > 0.5f ? 0 : strip[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : strip[3].get_comp_level() };
1370 meters.process(values);
1372 // next sample
1373 ++offset;
1374 } // cycle trough samples
1375 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
1376 } // process all strips (no bypass)
1377 meters.fall(numsamples);
1378 return outputs_mask;
1381 const gain_reduction_audio_module *multibandcompressor_audio_module::get_strip_by_param_index(int index) const
1383 // let's handle by the corresponding strip
1384 switch (index) {
1385 case param_solo0:
1386 return &strip[0];
1387 case param_solo1:
1388 return &strip[1];
1389 case param_solo2:
1390 return &strip[2];
1391 case param_solo3:
1392 return &strip[3];
1394 return NULL;
1397 bool multibandcompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1399 bool r;
1401 if (redraw)
1402 redraw = std::max(0, redraw - 1);
1404 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1405 if (m) {
1406 r = m->get_graph(subindex, data, points, context, mode);
1407 } else {
1408 r = crossover.get_graph(subindex, phase, data, points, context, mode);
1410 if ((index == param_solo0 + 11 * page and subindex == 1)
1411 or (index == param_bypass and subindex == page)) {
1412 *mode = 1;
1414 if ((subindex == 1 and index != param_bypass)
1415 or (index == param_bypass)) {
1416 if (r
1417 and ((index != param_bypass and *params[index - 1])
1418 or (index == param_bypass and *params[param_bypass0 + 11 * subindex])))
1419 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
1420 else
1421 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
1423 return r;
1426 bool multibandcompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1428 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1429 if (m)
1430 return m->get_dot(subindex, x, y, size, context);
1431 return false;
1434 bool multibandcompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1436 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1437 if (m)
1438 return m->get_gridline(subindex, pos, vertical, legend, context);
1439 if (phase) return false;
1440 return get_freq_gridline(subindex, pos, vertical, legend, context);
1443 bool multibandcompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1445 bool r;
1446 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1447 if (m) {
1448 r = m->get_layers(index, generation, layers);
1449 } else {
1450 r = crossover.get_layers(index, generation, layers);
1452 if (redraw) {
1453 layers |= LG_CACHE_GRAPH;
1454 r = true;
1456 return r;
1460 /**********************************************************************
1461 * MONO COMPRESSOR by Damien Zammit
1462 **********************************************************************/
1464 monocompressor_audio_module::monocompressor_audio_module()
1466 is_active = false;
1467 srate = 0;
1470 void monocompressor_audio_module::activate()
1472 is_active = true;
1473 // set all filters and strips
1474 monocompressor.activate();
1475 params_changed();
1477 void monocompressor_audio_module::deactivate()
1479 is_active = false;
1480 monocompressor.deactivate();
1483 void monocompressor_audio_module::params_changed()
1485 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);
1488 void monocompressor_audio_module::set_sample_rate(uint32_t sr)
1490 srate = sr;
1491 monocompressor.set_sample_rate(srate);
1492 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1493 int clip[] = {param_clip_in, param_clip_out, -1};
1494 meters.init(params, meter, clip, 3, srate);
1497 uint32_t monocompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1499 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1500 numsamples += offset;
1501 if(bypassed) {
1502 // everything bypassed
1503 while(offset < numsamples) {
1504 outs[0][offset] = ins[0][offset];
1505 float values[] = {0, 0, 1};
1506 meters.process(values);
1507 ++offset;
1509 } else {
1510 // process
1511 uint32_t orig_offset = offset;
1512 monocompressor.update_curve();
1514 while(offset < numsamples) {
1515 // cycle through samples
1516 float outL = 0.f;
1517 //float outR = 0.f;
1518 float inL = ins[0][offset];
1519 //float inR = ins[1][offset];
1520 float Lin = ins[0][offset];
1521 //float Rin = ins[1][offset];
1523 // in level
1524 //inR *= *params[param_level_in];
1525 inL *= *params[param_level_in];
1527 float leftAC = inL;
1528 //float rightAC = inR;
1530 monocompressor.process(leftAC);
1532 outL = leftAC;
1533 //outR = rightAC;
1535 // mix
1536 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1537 //outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1539 // send to output
1540 outs[0][offset] = outL;
1541 //outs[1][offset] = 0.f;
1543 float values[] = {inL, outL, monocompressor.get_comp_level()};
1544 meters.process(values);
1546 // next sample
1547 ++offset;
1548 } // cycle trough samples
1549 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
1551 meters.fall(numsamples);
1552 return outputs_mask;
1554 bool monocompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1556 return monocompressor.get_graph(subindex, data, points, context, mode);
1559 bool monocompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1561 return monocompressor.get_dot(subindex, x, y, size, context);
1564 bool monocompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1566 return monocompressor.get_gridline(subindex, pos, vertical, legend, context);
1569 bool monocompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1571 return monocompressor.get_layers(index, generation, layers);
1574 /**********************************************************************
1575 * DEESSER by Markus Schmidt
1576 **********************************************************************/
1578 deesser_audio_module::deesser_audio_module()
1580 is_active = false;
1581 srate = 0;
1582 f1_freq_old1 = 0.f;
1583 f2_freq_old1 = 0.f;
1584 f1_level_old1 = 0.f;
1585 f2_level_old1 = 0.f;
1586 f2_q_old1 = 0.f;
1587 f1_freq_old = 0.f;
1588 f2_freq_old = 0.f;
1589 f1_level_old = 0.f;
1590 f2_level_old = 0.f;
1591 f2_q_old = 0.f;
1592 detected_led = 0;
1593 redraw_graph = true;
1596 void deesser_audio_module::activate()
1598 is_active = true;
1599 // set all filters and strips
1600 compressor.activate();
1601 params_changed();
1602 detected = 0.f;
1603 detected_led = 0.f;
1605 void deesser_audio_module::deactivate()
1607 is_active = false;
1608 compressor.deactivate();
1611 void deesser_audio_module::params_changed()
1613 // set the params of all filters
1614 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1615 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1616 or *params[param_f2_q] != f2_q_old) {
1617 float q = 0.707;
1619 hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
1620 hpR.copy_coeffs(hpL);
1621 lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
1622 lpR.copy_coeffs(lpL);
1623 pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
1624 pR.copy_coeffs(pL);
1625 f1_freq_old = *params[param_f1_freq];
1626 f1_level_old = *params[param_f1_level];
1627 f2_freq_old = *params[param_f2_freq];
1628 f2_level_old = *params[param_f2_level];
1629 f2_q_old = *params[param_f2_q];
1631 // and set the compressor module
1632 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);
1633 if (*params[param_f1_freq] != f1_freq_old1
1634 or *params[param_f2_freq] != f2_freq_old1
1635 or *params[param_f1_level] != f1_level_old1
1636 or *params[param_f2_level] != f2_level_old1
1637 or *params[param_f2_q] !=f2_q_old1)
1639 f1_freq_old1 = *params[param_f1_freq];
1640 f2_freq_old1 = *params[param_f2_freq];
1641 f1_level_old1 = *params[param_f1_level];
1642 f2_level_old1 = *params[param_f2_level];
1643 f2_q_old1 = *params[param_f2_q];
1644 redraw_graph = true;
1648 void deesser_audio_module::set_sample_rate(uint32_t sr)
1650 srate = sr;
1651 compressor.set_sample_rate(srate);
1652 int meter[] = {param_detected, -param_compression};
1653 int clip[] = {param_clip_out, -1};
1654 meters.init(params, meter, clip, 2, srate);
1657 uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1659 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1660 numsamples += offset;
1661 if(bypassed) {
1662 // everything bypassed81e8da266
1663 while(offset < numsamples) {
1664 outs[0][offset] = ins[0][offset];
1665 outs[1][offset] = ins[1][offset];
1666 float values[] = {0, 1};
1667 meters.process(values);
1668 ++offset;
1670 } else {
1671 // process
1672 uint32_t orig_offset = offset;
1673 detected_led -= std::min(detected_led, numsamples);
1674 compressor.update_curve();
1676 while(offset < numsamples) {
1677 // cycle through samples
1678 float outL = 0.f;
1679 float outR = 0.f;
1680 float inL = ins[0][offset];
1681 float inR = ins[1][offset];
1684 float leftAC = inL;
1685 float rightAC = inR;
1686 float leftSC = inL;
1687 float rightSC = inR;
1688 float leftRC = inL;
1689 float rightRC = inR;
1690 float leftMC = inL;
1691 float rightMC = inR;
1693 leftSC = pL.process(hpL.process(leftSC));
1694 rightSC = pR.process(hpR.process(rightSC));
1695 leftMC = leftSC;
1696 rightMC = rightSC;
1698 switch ((int)*params[param_mode]) {
1699 default:
1700 case WIDE:
1701 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1702 break;
1703 case SPLIT:
1704 hpL.sanitize();
1705 hpR.sanitize();
1706 leftRC = hpL.process(leftRC);
1707 rightRC = hpR.process(rightRC);
1708 compressor.process(leftRC, rightRC, &leftSC, &rightSC);
1709 leftAC = lpL.process(leftAC);
1710 rightAC = lpR.process(rightAC);
1711 leftAC += leftRC;
1712 rightAC += rightRC;
1713 break;
1716 if(*params[param_sc_listen] > 0.f) {
1717 outL = leftMC;
1718 outR = rightMC;
1719 } else {
1720 outL = leftAC;
1721 outR = rightAC;
1724 // send to output
1725 outs[0][offset] = outL;
1726 outs[1][offset] = outR;
1728 if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) {
1729 detected_led = srate >> 3;
1731 detected = std::max(fabs(leftMC), fabs(rightMC));
1733 float values[] = {detected, compressor.get_comp_level()};
1734 meters.process(values);
1736 // next sample
1737 ++offset;
1738 } // cycle trough samples
1739 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
1740 hpL.sanitize();
1741 hpR.sanitize();
1742 lpL.sanitize();
1743 lpR.sanitize();
1744 pL.sanitize();
1745 pR.sanitize();
1747 // draw meters
1748 if(params[param_detected_led] != NULL) {
1749 *params[param_detected_led] = detected_led;
1751 meters.fall(numsamples);
1752 return outputs_mask;
1756 /**********************************************************************
1757 * GATE AUDIO MODULE Damien Zammit
1758 **********************************************************************/
1760 gate_audio_module::gate_audio_module()
1762 is_active = false;
1763 srate = 0;
1766 void gate_audio_module::activate()
1768 is_active = true;
1769 // set all filters and strips
1770 gate.activate();
1771 params_changed();
1773 void gate_audio_module::deactivate()
1775 is_active = false;
1776 gate.deactivate();
1779 void gate_audio_module::params_changed()
1781 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]);
1784 void gate_audio_module::set_sample_rate(uint32_t sr)
1786 srate = sr;
1787 gate.set_sample_rate(srate);
1788 int meter[] = {param_meter_in, param_meter_out, -param_gating};
1789 int clip[] = {param_clip_in, param_clip_out, -1};
1790 meters.init(params, meter, clip, 3, srate);
1793 uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1795 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1796 numsamples += offset;
1797 if(bypassed) {
1798 // everything bypassed
1799 while(offset < numsamples) {
1800 outs[0][offset] = ins[0][offset];
1801 outs[1][offset] = ins[1][offset];
1802 float values[] = {0, 0, 1};
1803 meters.process(values);
1804 ++offset;
1806 } else {
1807 // process
1808 gate.update_curve();
1809 uint32_t orig_offset = offset;
1810 while(offset < numsamples) {
1811 // cycle through samples
1812 float outL = 0.f;
1813 float outR = 0.f;
1814 float inL = ins[0][offset];
1815 float inR = ins[1][offset];
1816 // in level
1817 inR *= *params[param_level_in];
1818 inL *= *params[param_level_in];
1820 float leftAC = inL;
1821 float rightAC = inR;
1823 gate.process(leftAC, rightAC);
1825 outL = leftAC;
1826 outR = rightAC;
1828 // send to output
1829 outs[0][offset] = outL;
1830 outs[1][offset] = outR;
1832 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
1833 meters.process(values);
1835 // next sample
1836 ++offset;
1837 } // cycle trough samples
1838 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
1840 meters.fall(numsamples);
1841 return outputs_mask;
1843 bool gate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1845 return gate.get_graph(subindex, data, points, context, mode);
1848 bool gate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1850 return gate.get_dot(subindex, x, y, size, context);
1853 bool gate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1855 return gate.get_gridline(subindex, pos, vertical, legend, context);
1858 bool gate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1860 return gate.get_layers(index, generation, layers);
1863 /**********************************************************************
1864 * SIDECHAIN GATE by Markus Schmidt
1865 **********************************************************************/
1867 sidechaingate_audio_module::sidechaingate_audio_module()
1869 is_active = false;
1870 srate = 0;
1871 redraw_graph = true;
1872 f1_freq_old = f2_freq_old = f1_level_old = f2_level_old = 0;
1873 f1_freq_old1 = f2_freq_old1 = f1_level_old1 = f2_level_old1 = 0;
1874 sc_mode_old = sc_mode_old1 = WIDEBAND; // doesn't matter as long as it's sane
1877 void sidechaingate_audio_module::activate()
1879 is_active = true;
1880 // set all filters and strips
1881 gate.activate();
1882 params_changed();
1884 void sidechaingate_audio_module::deactivate()
1886 is_active = false;
1887 gate.deactivate();
1890 sidechaingate_audio_module::cfloat sidechaingate_audio_module::h_z(const cfloat &z) const
1892 switch ((CalfScModes)sc_mode) {
1893 default:
1894 case WIDEBAND:
1895 return false;
1896 break;
1897 case HIGHGATE_WIDE:
1898 case LOWGATE_WIDE:
1899 case WEIGHTED_1:
1900 case WEIGHTED_2:
1901 case WEIGHTED_3:
1902 case BANDPASS_2:
1903 return f1L.h_z(z) * f2L.h_z(z);
1904 break;
1905 case HIGHGATE_SPLIT:
1906 return f2L.h_z(z);
1907 break;
1908 case LOWGATE_SPLIT:
1909 case BANDPASS_1:
1910 return f1L.h_z(z);
1911 break;
1915 float sidechaingate_audio_module::freq_gain(int index, double freq) const
1917 typedef std::complex<double> cfloat;
1918 freq *= 2.0 * M_PI / srate;
1919 cfloat z = 1.0 / exp(cfloat(0.0, freq));
1921 return std::abs(h_z(z));
1924 void sidechaingate_audio_module::params_changed()
1926 // set the params of all filters
1927 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1928 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1929 or *params[param_sc_mode] != sc_mode) {
1930 float q = 0.707;
1931 switch ((CalfScModes)*params[param_sc_mode]) {
1932 default:
1933 case WIDEBAND:
1934 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1935 f1R.copy_coeffs(f1L);
1936 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1937 f2R.copy_coeffs(f2L);
1938 f1_active = 0.f;
1939 f2_active = 0.f;
1940 break;
1941 case HIGHGATE_WIDE:
1942 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1943 f1R.copy_coeffs(f1L);
1944 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1945 f2R.copy_coeffs(f2L);
1946 f1_active = 0.5f;
1947 f2_active = 1.f;
1948 break;
1949 case HIGHGATE_SPLIT:
1950 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
1951 f1R.copy_coeffs(f1L);
1952 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
1953 f2R.copy_coeffs(f2L);
1954 f1_active = 0.f;
1955 f2_active = 1.f;
1956 break;
1957 case LOWGATE_WIDE:
1958 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1959 f1R.copy_coeffs(f1L);
1960 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1961 f2R.copy_coeffs(f2L);
1962 f1_active = 1.f;
1963 f2_active = 0.5f;
1964 break;
1965 case LOWGATE_SPLIT:
1966 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
1967 f1R.copy_coeffs(f1L);
1968 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
1969 f2R.copy_coeffs(f2L);
1970 f1_active = 1.f;
1971 f2_active = 0.f;
1972 break;
1973 case WEIGHTED_1:
1974 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1975 f1R.copy_coeffs(f1L);
1976 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1977 f2R.copy_coeffs(f2L);
1978 f1_active = 0.5f;
1979 f2_active = 0.5f;
1980 break;
1981 case WEIGHTED_2:
1982 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1983 f1R.copy_coeffs(f1L);
1984 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1985 f2R.copy_coeffs(f2L);
1986 f1_active = 0.5f;
1987 f2_active = 0.5f;
1988 break;
1989 case WEIGHTED_3:
1990 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1991 f1R.copy_coeffs(f1L);
1992 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1993 f2R.copy_coeffs(f2L);
1994 f1_active = 0.5f;
1995 f2_active = 0.5f;
1996 break;
1997 case BANDPASS_1:
1998 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1999 f1R.copy_coeffs(f1L);
2000 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
2001 f2R.copy_coeffs(f2L);
2002 f1_active = 1.f;
2003 f2_active = 0.f;
2004 break;
2005 case BANDPASS_2:
2006 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
2007 f1R.copy_coeffs(f1L);
2008 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
2009 f2R.copy_coeffs(f2L);
2010 f1_active = 1.f;
2011 f2_active = 1.f;
2012 break;
2014 f1_freq_old = *params[param_f1_freq];
2015 f1_level_old = *params[param_f1_level];
2016 f2_freq_old = *params[param_f2_freq];
2017 f2_level_old = *params[param_f2_level];
2018 sc_mode = (CalfScModes)*params[param_sc_mode];
2020 // light LED's
2021 if(params[param_f1_active] != NULL) {
2022 *params[param_f1_active] = f1_active;
2024 if(params[param_f2_active] != NULL) {
2025 *params[param_f2_active] = f2_active;
2027 // and set the expander module
2028 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]);
2030 if (*params[param_f1_freq] != f1_freq_old1
2031 or *params[param_f2_freq] != f2_freq_old1
2032 or *params[param_f1_level] != f1_level_old1
2033 or *params[param_f2_level] != f2_level_old1
2034 or *params[param_sc_mode] != sc_mode_old1)
2036 f1_freq_old1 = *params[param_f1_freq];
2037 f2_freq_old1 = *params[param_f2_freq];
2038 f1_level_old1 = *params[param_f1_level];
2039 f2_level_old1 = *params[param_f2_level];
2040 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
2041 redraw_graph = true;
2045 void sidechaingate_audio_module::set_sample_rate(uint32_t sr)
2047 srate = sr;
2048 gate.set_sample_rate(srate);
2049 int meter[] = {param_meter_in, param_meter_out, -param_gating};
2050 int clip[] = {param_clip_in, param_clip_out, -1};
2051 meters.init(params, meter, clip, 3, srate);
2054 uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2056 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2057 numsamples += offset;
2058 if(bypassed) {
2059 // everything bypassed
2060 while(offset < numsamples) {
2061 outs[0][offset] = ins[0][offset];
2062 outs[1][offset] = ins[1][offset];
2063 float values[] = {0, 0, 1};
2064 meters.process(values);
2065 ++offset;
2067 } else {
2068 // process
2069 uint32_t orig_offset = offset;
2070 gate.update_curve();
2072 while(offset < numsamples) {
2073 // cycle through samples
2074 float outL = 0.f;
2075 float outR = 0.f;
2076 float inL = ins[0][offset];
2077 float inR = ins[1][offset];
2079 float in2L = ins[2] ? ins[2][offset] : 0;
2080 float in2R = ins[3] ? ins[3][offset] : 0;
2082 // in level
2083 inR *= *params[param_level_in];
2084 inL *= *params[param_level_in];
2086 float leftAC = inL;
2087 float rightAC = inR;
2088 float leftSC = inL;
2089 float rightSC = inR;
2090 float leftMC = inL;
2091 float rightMC = inR;
2093 if (*params[param_sc_route] > 0.5) {
2094 leftAC = inL;
2095 rightAC = inR;
2096 leftSC = in2L * *params[param_sc_level];
2097 rightSC = in2R * *params[param_sc_level];
2098 leftMC = inL;
2099 rightMC = inR;
2102 switch ((CalfScModes)*params[param_sc_mode]) {
2103 default:
2104 case WIDEBAND:
2105 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2106 leftMC = leftSC;
2107 rightMC = rightSC;
2108 break;
2109 case HIGHGATE_WIDE:
2110 case LOWGATE_WIDE:
2111 case WEIGHTED_1:
2112 case WEIGHTED_2:
2113 case WEIGHTED_3:
2114 case BANDPASS_2:
2115 leftSC = f2L.process(f1L.process(leftSC));
2116 rightSC = f2R.process(f1R.process(rightSC));
2117 leftMC = leftSC;
2118 rightMC = rightSC;
2119 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2120 break;
2121 case HIGHGATE_SPLIT:
2122 leftSC = f2L.process(leftSC);
2123 rightSC = f2R.process(rightSC);
2124 leftMC = leftSC;
2125 rightMC = rightSC;
2126 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2127 leftAC = f1L.process(leftAC);
2128 rightAC = f1R.process(rightAC);
2129 leftAC += leftSC;
2130 rightAC += rightSC;
2131 break;
2132 case LOWGATE_SPLIT:
2133 leftSC = f1L.process(leftSC);
2134 rightSC = f1R.process(rightSC);
2135 leftMC = leftSC;
2136 rightMC = rightSC;
2137 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2138 leftAC = f2L.process(leftAC);
2139 rightAC = f2R.process(rightAC);
2140 leftAC += leftSC;
2141 rightAC += rightSC;
2142 break;
2143 case BANDPASS_1:
2144 leftSC = f1L.process(leftSC);
2145 rightSC = f1R.process(rightSC);
2146 leftMC = leftSC;
2147 rightMC = rightSC;
2148 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2149 break;
2152 if(*params[param_sc_listen] > 0.f) {
2153 outL = leftMC;
2154 outR = rightMC;
2155 } else {
2156 outL = leftAC;
2157 outR = rightAC;
2160 // send to output
2161 outs[0][offset] = outL;
2162 outs[1][offset] = outR;
2164 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
2165 meters.process(values);
2167 // next sample
2168 ++offset;
2169 } // cycle trough samples
2170 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
2171 f1L.sanitize();
2172 f1R.sanitize();
2173 f2L.sanitize();
2174 f2R.sanitize();
2177 meters.fall(numsamples);
2178 return outputs_mask;
2180 bool sidechaingate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2182 if (!is_active or phase)
2183 return false;
2184 if (index == param_sc_listen && !subindex) {
2185 return ::get_graph(*this, subindex, data, points);
2186 } else if(index == param_bypass) {
2187 return gate.get_graph(subindex, data, points, context, mode);
2189 return false;
2192 bool sidechaingate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2194 if (!is_active or !phase)
2195 return false;
2196 if (index == param_bypass) {
2197 return gate.get_dot(subindex, x, y, size, context);
2199 return false;
2202 bool sidechaingate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2204 if (!is_active or phase)
2205 return false;
2206 if (index == param_bypass) {
2207 return gate.get_gridline(subindex, pos, vertical, legend, context);
2208 } else {
2209 return get_freq_gridline(subindex, pos, vertical, legend, context);
2211 return false;
2213 bool sidechaingate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2215 if(index == param_bypass)
2216 return gate.get_layers(index, generation, layers);
2217 bool redraw = redraw_graph || !generation;
2218 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
2219 redraw_graph = false;
2220 return redraw;
2224 /**********************************************************************
2225 * MULTIBAND GATE by Markus Schmidt
2226 **********************************************************************/
2228 multibandgate_audio_module::multibandgate_audio_module()
2230 is_active = false;
2231 srate = 0;
2232 mode = 0;
2233 redraw = 0;
2234 page = 0;
2235 bypass_ = 0;
2236 crossover.init(2, 4, 44100);
2239 void multibandgate_audio_module::activate()
2241 is_active = true;
2242 // set all filters and strips
2243 params_changed();
2244 // activate all strips
2245 for (int j = 0; j < strips; j ++) {
2246 gate[j].activate();
2247 gate[j].id = j;
2251 void multibandgate_audio_module::deactivate()
2253 is_active = false;
2254 // deactivate all strips
2255 for (int j = 0; j < strips; j ++) {
2256 gate[j].deactivate();
2260 void multibandgate_audio_module::params_changed()
2262 // determine mute/solo states
2263 solo[0] = *params[param_solo0] > 0.f ? true : false;
2264 solo[1] = *params[param_solo1] > 0.f ? true : false;
2265 solo[2] = *params[param_solo2] > 0.f ? true : false;
2266 solo[3] = *params[param_solo3] > 0.f ? true : false;
2267 no_solo = (*params[param_solo0] > 0.f ||
2268 *params[param_solo1] > 0.f ||
2269 *params[param_solo2] > 0.f ||
2270 *params[param_solo3] > 0.f) ? false : true;
2272 int m = *params[param_mode];
2273 if (m != mode) {
2274 mode = *params[param_mode];
2277 int p = (int)*params[param_notebook];
2278 if (p != page) {
2279 page = p;
2280 redraw = strips * 2 + strips;
2283 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
2284 if (b != bypass_) {
2285 redraw = strips * 2 + strips;
2286 bypass_ = b;
2289 crossover.set_mode(mode + 1);
2290 crossover.set_filter(0, *params[param_freq0]);
2291 crossover.set_filter(1, *params[param_freq1]);
2292 crossover.set_filter(2, *params[param_freq2]);
2294 // set the params of all strips
2295 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]);
2296 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]);
2297 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]);
2298 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]);
2301 void multibandgate_audio_module::set_sample_rate(uint32_t sr)
2303 srate = sr;
2304 // set srate of all strips
2305 for (int j = 0; j < strips; j ++) {
2306 gate[j].set_sample_rate(srate);
2308 // set srate of crossover
2309 crossover.set_sample_rate(srate);
2310 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
2311 param_output0, -param_gating0,
2312 param_output1, -param_gating1,
2313 param_output2, -param_gating2,
2314 param_output3, -param_gating3 };
2315 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
2316 meters.init(params, meter, clip, 12, srate);
2319 uint32_t multibandgate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2321 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2322 numsamples += offset;
2323 for (int i = 0; i < strips; i++)
2324 gate[i].update_curve();
2325 if(bypassed) {
2326 // everything bypassed
2327 while(offset < numsamples) {
2328 outs[0][offset] = ins[0][offset];
2329 outs[1][offset] = ins[1][offset];
2330 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
2331 meters.process(values);
2332 ++offset;
2334 } else {
2335 // process all strips
2336 uint32_t orig_offset = offset;
2337 while(offset < numsamples) {
2338 // cycle through samples
2339 float inL = ins[0][offset];
2340 float inR = ins[1][offset];
2341 // in level
2342 inR *= *params[param_level_in];
2343 inL *= *params[param_level_in];
2344 // process crossover
2345 xin[0] = inL;
2346 xin[1] = inR;
2347 crossover.process(xin);
2348 // out vars
2349 float outL = 0.f;
2350 float outR = 0.f;
2351 for (int i = 0; i < strips; i ++) {
2352 // cycle trough strips
2353 if (solo[i] || no_solo) {
2354 // strip unmuted
2355 float left = crossover.get_value(0, i);
2356 float right = crossover.get_value(1, i);
2357 gate[i].process(left, right);
2358 // sum up output
2359 outL += left;
2360 outR += right;
2362 } // process single strip
2364 // out level
2365 outL *= *params[param_level_out];
2366 outR *= *params[param_level_out];
2368 // send to output
2369 outs[0][offset] = outL;
2370 outs[1][offset] = outR;
2372 float values[] = {inL, inR, outL, outR,
2373 *params[param_bypass0] > 0.5f ? 0 : gate[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : gate[0].get_expander_level(),
2374 *params[param_bypass1] > 0.5f ? 0 : gate[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : gate[1].get_expander_level(),
2375 *params[param_bypass2] > 0.5f ? 0 : gate[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : gate[2].get_expander_level(),
2376 *params[param_bypass3] > 0.5f ? 0 : gate[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : gate[3].get_expander_level() };
2377 meters.process(values);
2379 // next sample
2380 ++offset;
2381 } // cycle trough samples
2382 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
2384 } // process all strips (no bypass)
2385 meters.fall(numsamples);
2386 return outputs_mask;
2389 const expander_audio_module *multibandgate_audio_module::get_strip_by_param_index(int index) const
2391 // let's handle by the corresponding strip
2392 switch (index) {
2393 case param_solo0:
2394 return &gate[0];
2395 case param_solo1:
2396 return &gate[1];
2397 case param_solo2:
2398 return &gate[2];
2399 case param_solo3:
2400 return &gate[3];
2402 return NULL;
2405 bool multibandgate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2407 bool r;
2408 if (redraw)
2409 redraw = std::max(0, redraw - 1);
2411 const expander_audio_module *m = get_strip_by_param_index(index);
2412 if (m) {
2413 r = m->get_graph(subindex, data, points, context, mode);
2414 } else {
2415 r = crossover.get_graph(subindex, phase, data, points, context, mode);
2417 if ((index == param_solo0 + 12 * page and subindex == 1)
2418 or (index == param_bypass and subindex == page)) {
2419 *mode = 1;
2421 if ((subindex == 1 and index != param_bypass)
2422 or (index == param_bypass)) {
2423 if (r
2424 and ((index != param_bypass and *params[index - 1])
2425 or (index == param_bypass and *params[param_bypass0 + 12 * subindex])))
2426 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
2427 else
2428 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
2430 return r;
2433 bool multibandgate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2435 const expander_audio_module *m = get_strip_by_param_index(index);
2436 if (m)
2437 return m->get_dot(subindex, x, y, size, context);
2438 return false;
2441 bool multibandgate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2443 const expander_audio_module *m = get_strip_by_param_index(index);
2444 if (m)
2445 return m->get_gridline(subindex, pos, vertical, legend, context);
2446 if (phase) return false;
2447 return get_freq_gridline(subindex, pos, vertical, legend, context);
2450 bool multibandgate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2452 bool r;
2453 const expander_audio_module *m = get_strip_by_param_index(index);
2454 if (m) {
2455 r = m->get_layers(index, generation, layers);
2456 } else {
2457 r = crossover.get_layers(index, generation, layers);
2459 if (redraw) {
2460 layers |= LG_CACHE_GRAPH;
2461 r = true;
2463 return r;
2467 /**********************************************************************
2468 * TRANSIENT DESIGNER by Christian Holschuh and Markus Schmidt
2469 **********************************************************************/
2472 transientdesigner_audio_module::transientdesigner_audio_module() {
2473 active = false;
2474 pixels = 0;
2475 pbuffer_pos = 0;
2476 pbuffer_sample = 0;
2477 pbuffer_size = 0;
2478 attcount = 0;
2479 attacked = false;
2480 attack_pos = 0;
2481 display_old = 0.f;
2482 pbuffer_available = false;
2483 last_drawn = 0;
2484 display_max = pow(2,-12);
2485 transients.set_channels(channels);
2487 transientdesigner_audio_module::~transientdesigner_audio_module()
2489 free(pbuffer);
2491 void transientdesigner_audio_module::activate() {
2492 active = true;
2495 void transientdesigner_audio_module::deactivate() {
2496 active = false;
2499 void transientdesigner_audio_module::params_changed() {
2500 if (*params[param_display] != display_old) {
2501 dsp::zero(pbuffer, (int)(pixels * 2));
2502 display_old = *params[param_display];
2504 transients.set_params(*params[param_attack_time],
2505 *params[param_attack_boost],
2506 *params[param_release_time],
2507 *params[param_release_boost],
2508 *params[param_sustain_threshold],
2509 *params[param_lookahead],
2510 *params[param_mix]);
2513 uint32_t transientdesigner_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
2514 uint32_t orig_offset = offset;
2515 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2516 for(uint32_t i = offset; i < offset + numsamples; i++) {
2517 float L = ins[0][i];
2518 float R = ins[1][i];
2519 meter_inL = 0.f;
2520 meter_inR = 0.f;
2521 meter_outL = 0.f;
2522 meter_outR = 0.f;
2523 float s = (fabs(L) + fabs(R)) / 2;
2524 if(bypassed) {
2525 outs[0][i] = ins[0][i];
2526 outs[1][i] = ins[1][i];
2528 } else {
2529 // levels in
2530 L *= *params[param_level_in];
2531 R *= *params[param_level_in];
2533 // GUI stuff
2534 meter_inL = L;
2535 meter_inR = R;
2537 // transient designer
2538 float values[] = {L, R};
2539 transients.process(values);
2540 L = values[0];
2541 R = values[1];
2543 // levels out
2544 L *= *params[param_level_out];
2545 R *= *params[param_level_out];
2547 // output
2548 outs[0][i] = L;
2549 outs[1][i] = R;
2551 meter_outL = L;
2552 meter_outR = R;
2554 // fill pixel buffer
2555 if (pbuffer_available) {
2556 // sanitize the buffer position if enough samples have
2557 // been captured. This is recognized by a negative value
2558 for (int i = 0; i < 5; i++) {
2559 pbuffer[pbuffer_pos + i] = std::max(pbuffer[pbuffer_pos + i], 0.f);
2562 // add samples to the buffer at the actual address
2563 pbuffer[pbuffer_pos] = std::max(s, pbuffer[pbuffer_pos]);
2564 pbuffer[pbuffer_pos + 1] = std::max((float)(fabs(L) + fabs(R)), (float)pbuffer[pbuffer_pos + 1]);
2565 pbuffer[pbuffer_pos + 2] = transients.envelope;
2566 pbuffer[pbuffer_pos + 3] = transients.attack;
2567 pbuffer[pbuffer_pos + 4] = transients.release;
2569 pbuffer_sample += 1;
2571 if (pbuffer_sample >= (int)(srate * *params[param_display] / 1000.f / pixels)) {
2572 // we captured enough samples for one pixel on this
2573 // address. to keep track of the finalization invert
2574 // its values as a marker to sanitize in the next
2575 // cycle before adding samples again
2576 pbuffer[pbuffer_pos] *= -1.f * *params[param_level_in];
2577 pbuffer[pbuffer_pos + 1] /= -2.f;
2579 // advance the buffer position
2580 pbuffer_pos = (pbuffer_pos + 5) % pbuffer_size;
2582 // reset sample counter
2583 pbuffer_sample = 0;
2587 attcount += 1;
2588 if ( transients.envelope == transients.release
2589 and transients.envelope > *params[param_display_threshold]
2590 and attcount >= srate / 100
2591 and pbuffer_available) {
2592 int diff = (int)(srate / 10 / pixels);
2593 diff += diff & 1;
2594 attack_pos = (pbuffer_pos - diff + pbuffer_size) % pbuffer_size;
2595 attcount = 0;
2597 float values[] = {meter_inL, meter_inR, meter_outL, meter_outR};
2598 meters.process(values);
2600 if (!bypassed)
2601 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
2602 meters.fall(numsamples);
2603 return outputs_mask;
2606 void transientdesigner_audio_module::set_sample_rate(uint32_t sr)
2608 srate = sr;
2609 attcount = srate / 5;
2610 transients.set_sample_rate(srate);
2611 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
2612 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
2613 meters.init(params, meter, clip, 4, srate);
2615 bool transientdesigner_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2617 if (points <= 0)
2618 return false;
2619 if (points != pixels) {
2620 // the zoom level changed or it's the first time we want to draw
2621 // some graphs
2623 // buffer size is the amount of pixels for the max display value
2624 // if drawn in the min display zoom level multiplied by 5 for
2625 // keeping the input and the output fabs signals and all graphs
2626 // of the envelopes
2627 pbuffer_size = (int)(points * 5.f * 100.f);
2628 // create array
2629 pbuffer = (float*) calloc(pbuffer_size, sizeof(float));
2631 // sanitize some indexes and addresses
2632 pbuffer_pos = 0;
2633 pbuffer_sample = 0;
2634 pbuffer_draw = 0;
2635 pbuffer_available = true;
2636 pixels = points;
2638 // check if threshold is above minimum - we want to see trigger hold
2639 bool hold = *params[param_display_threshold] > display_max;
2640 // set the address to start from in both drawing cycles
2641 // to amount of pixels before pbuffer_pos or to attack_pos
2642 if (subindex == 0) {
2643 int pos = hold ? attack_pos : pbuffer_pos;
2644 pbuffer_draw = *params[param_display_threshold] > display_max ? pos
2645 : (pbuffer_size + pos - pixels * 5) % pbuffer_size;
2648 // get outa here if max graph is reached
2649 if (last_drawn >= 5) {
2650 last_drawn = 0;
2651 return false;
2654 // get the next graph to draw leaving out inactive
2655 while (last_drawn < 5 and !*params[param_input + last_drawn] > 0.5)
2656 last_drawn ++;
2658 // get outa here if max graph is reached
2659 if (last_drawn >= 5) {
2660 last_drawn = 0;
2661 return false;
2663 if (!last_drawn) {
2664 // input is drawn as bars with less opacity
2665 *mode = 1;
2666 context->set_source_rgba(0.15, 0.2, 0.0, 0.2);
2667 } else if (last_drawn == 1) {
2668 // output is a precise line
2669 context->set_line_width(0.75);
2670 } else {
2671 // envelope, attack and release are dotted
2672 set_channel_dash(context, last_drawn - 2);
2673 context->set_line_width(1);
2676 // draw curve
2677 for (int i = 0; i <= points; i++) {
2678 int pos = (pbuffer_draw + i * 5) % pbuffer_size + last_drawn;
2679 if (hold
2680 and ((pos > pbuffer_pos and ((pbuffer_pos > attack_pos and pos > attack_pos)
2681 or (pbuffer_pos < attack_pos and pos < attack_pos)))
2682 or (pbuffer_pos > attack_pos and pos < attack_pos))) {
2683 // we are drawing trigger hold stuff outside the hold window
2684 // so we don't want to see old data - zero it out.
2685 data[i] = dB_grid(2.51e-10, 128, 0.6);
2686 } else {
2687 // draw normally
2688 data[i] = dB_grid(fabs(pbuffer[pos]) + 2.51e-10, 128, 0.6);
2691 last_drawn ++;
2692 return true;
2694 bool transientdesigner_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2696 if (subindex >= 16 or phase)
2697 return false;
2698 float gain = 16.f / (1 << subindex);
2699 pos = dB_grid(gain, 128, 0.6);
2700 context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2);
2701 if (!(subindex & 1) and subindex) {
2702 std::stringstream ss;
2703 ss << (24 - 6 * subindex) << " dB";
2704 legend = ss.str();
2706 return true;
2709 bool transientdesigner_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2711 layers = LG_REALTIME_GRAPH | (generation ? 0 : LG_CACHE_GRID);
2712 return true;