Transient Designer: image and text for manual, small change to the UI
[calf.git] / src / modules_comp.cpp
blob512745df29df01b592cff935eb9befd64c279221
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;
302 l = 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_numsamples = numsamples-offset;
781 uint32_t orig_offset = offset;
782 compressor.update_curve();
784 while(offset < numsamples) {
785 // cycle through samples
786 float outL = 0.f;
787 float outR = 0.f;
788 float inL = ins[0][offset];
789 float inR = ins[1][offset];
790 float Lin = ins[0][offset];
791 float Rin = ins[1][offset];
793 // in level
794 inR *= *params[param_level_in];
795 inL *= *params[param_level_in];
797 float leftAC = inL;
798 float rightAC = inR;
800 compressor.process(leftAC, rightAC);
802 outL = leftAC;
803 outR = rightAC;
805 // mix
806 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
807 outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
809 // send to output
810 outs[0][offset] = outL;
811 outs[1][offset] = outR;
813 float values[] = {std::max(inL, inR), std::max(outL, outR), compressor.get_comp_level()};
814 meters.process(values);
816 // next sample
817 ++offset;
818 } // cycle trough samples
819 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
821 meters.fall(numsamples);
822 return outputs_mask;
824 bool compressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
826 return compressor.get_graph(subindex, data, points, context, mode);
829 bool compressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
831 return compressor.get_dot(subindex, x, y, size, context);
834 bool compressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
836 return compressor.get_gridline(subindex, pos, vertical, legend, context);
839 bool compressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
841 return compressor.get_layers(index, generation, layers);
844 /**********************************************************************
845 * SIDECHAIN COMPRESSOR by Markus Schmidt
846 **********************************************************************/
848 sidechaincompressor_audio_module::sidechaincompressor_audio_module()
850 is_active = false;
851 srate = 0;
852 f1_freq_old1 = 0.f;
853 f2_freq_old1 = 0.f;
854 f1_level_old1 = 0.f;
855 f2_level_old1 = 0.f;
856 f1_freq_old = 0.f;
857 f2_freq_old = 0.f;
858 f1_level_old = 0.f;
859 f2_level_old = 0.f;
860 sc_mode_old1 = WIDEBAND;
861 redraw_graph = true;
864 void sidechaincompressor_audio_module::activate()
866 is_active = true;
867 // set all filters and strips
868 compressor.activate();
869 params_changed();
871 void sidechaincompressor_audio_module::deactivate()
873 is_active = false;
874 compressor.deactivate();
877 sidechaincompressor_audio_module::cfloat sidechaincompressor_audio_module::h_z(const cfloat &z) const
879 switch ((CalfScModes)sc_mode) {
880 default:
881 case WIDEBAND:
882 return false;
883 break;
884 case DEESSER_WIDE:
885 case DERUMBLER_WIDE:
886 case WEIGHTED_1:
887 case WEIGHTED_2:
888 case WEIGHTED_3:
889 case BANDPASS_2:
890 return f1L.h_z(z) * f2L.h_z(z);
891 break;
892 case DEESSER_SPLIT:
893 return f2L.h_z(z);
894 break;
895 case DERUMBLER_SPLIT:
896 case BANDPASS_1:
897 return f1L.h_z(z);
898 break;
902 float sidechaincompressor_audio_module::freq_gain(int index, double freq) const
904 typedef std::complex<double> cfloat;
905 freq *= 2.0 * M_PI / srate;
906 cfloat z = 1.0 / exp(cfloat(0.0, freq));
908 return std::abs(h_z(z));
911 void sidechaincompressor_audio_module::params_changed()
913 // set the params of all filters
914 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
915 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
916 or *params[param_sc_mode] != sc_mode) {
917 float q = 0.707;
918 switch ((CalfScModes)*params[param_sc_mode]) {
919 default:
920 case WIDEBAND:
921 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
922 f1R.copy_coeffs(f1L);
923 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
924 f2R.copy_coeffs(f2L);
925 f1_active = 0.f;
926 f2_active = 0.f;
927 break;
928 case DEESSER_WIDE:
929 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
930 f1R.copy_coeffs(f1L);
931 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
932 f2R.copy_coeffs(f2L);
933 f1_active = 0.5f;
934 f2_active = 1.f;
935 break;
936 case DEESSER_SPLIT:
937 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
938 f1R.copy_coeffs(f1L);
939 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
940 f2R.copy_coeffs(f2L);
941 f1_active = 0.f;
942 f2_active = 1.f;
943 break;
944 case DERUMBLER_WIDE:
945 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
946 f1R.copy_coeffs(f1L);
947 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
948 f2R.copy_coeffs(f2L);
949 f1_active = 1.f;
950 f2_active = 0.5f;
951 break;
952 case DERUMBLER_SPLIT:
953 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
954 f1R.copy_coeffs(f1L);
955 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
956 f2R.copy_coeffs(f2L);
957 f1_active = 1.f;
958 f2_active = 0.f;
959 break;
960 case WEIGHTED_1:
961 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
962 f1R.copy_coeffs(f1L);
963 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
964 f2R.copy_coeffs(f2L);
965 f1_active = 0.5f;
966 f2_active = 0.5f;
967 break;
968 case WEIGHTED_2:
969 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
970 f1R.copy_coeffs(f1L);
971 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
972 f2R.copy_coeffs(f2L);
973 f1_active = 0.5f;
974 f2_active = 0.5f;
975 break;
976 case WEIGHTED_3:
977 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
978 f1R.copy_coeffs(f1L);
979 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
980 f2R.copy_coeffs(f2L);
981 f1_active = 0.5f;
982 f2_active = 0.5f;
983 break;
984 case BANDPASS_1:
985 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
986 f1R.copy_coeffs(f1L);
987 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
988 f2R.copy_coeffs(f2L);
989 f1_active = 1.f;
990 f2_active = 0.f;
991 break;
992 case BANDPASS_2:
993 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
994 f1R.copy_coeffs(f1L);
995 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
996 f2R.copy_coeffs(f2L);
997 f1_active = 1.f;
998 f2_active = 1.f;
999 break;
1001 f1_freq_old = *params[param_f1_freq];
1002 f1_level_old = *params[param_f1_level];
1003 f2_freq_old = *params[param_f2_freq];
1004 f2_level_old = *params[param_f2_level];
1005 sc_mode = (CalfScModes)*params[param_sc_mode];
1007 // light LED's
1008 if(params[param_f1_active] != NULL) {
1009 *params[param_f1_active] = f1_active;
1011 if(params[param_f2_active] != NULL) {
1012 *params[param_f2_active] = f2_active;
1014 // and set the compressor module
1015 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);
1017 if (*params[param_f1_freq] != f1_freq_old1
1018 or *params[param_f2_freq] != f2_freq_old1
1019 or *params[param_f1_level] != f1_level_old1
1020 or *params[param_f2_level] != f2_level_old1
1021 or *params[param_sc_mode] != sc_mode_old1)
1023 f1_freq_old1 = *params[param_f1_freq];
1024 f2_freq_old1 = *params[param_f2_freq];
1025 f1_level_old1 = *params[param_f1_level];
1026 f2_level_old1 = *params[param_f2_level];
1027 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
1028 redraw_graph = true;
1032 void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr)
1034 srate = sr;
1035 compressor.set_sample_rate(srate);
1036 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1037 int clip[] = {param_clip_in, param_clip_out, -1};
1038 meters.init(params, meter, clip, 3, srate);
1041 uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1043 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1044 numsamples += offset;
1045 if(bypassed) {
1046 // everything bypassed
1047 while(offset < numsamples) {
1048 outs[0][offset] = ins[0][offset];
1049 outs[1][offset] = ins[1][offset];
1050 float values[] = {0, 0, 1};
1051 meters.process(values);
1052 ++offset;
1054 } else {
1055 // process
1056 uint32_t orig_numsamples = numsamples-offset;
1057 uint32_t orig_offset = offset;
1058 compressor.update_curve();
1060 while(offset < numsamples) {
1061 // cycle through samples
1062 float outL = 0.f;
1063 float outR = 0.f;
1064 float inL = ins[0][offset];
1065 float inR = ins[1][offset];
1066 float Lin = ins[0][offset];
1067 float Rin = ins[1][offset];
1069 float in2L = ins[2] ? ins[2][offset] : 0;
1070 float in2R = ins[3] ? ins[3][offset] : 0;
1072 // in level
1073 inR *= *params[param_level_in];
1074 inL *= *params[param_level_in];
1076 float leftAC = inL;
1077 float rightAC = inR;
1078 float leftSC = inL;
1079 float rightSC = inR;
1080 float leftMC = inL;
1081 float rightMC = inR;
1083 if (*params[param_sc_route] > 0.5) {
1084 leftAC = inL;
1085 rightAC = inR;
1086 leftSC = in2L * *params[param_sc_level];
1087 rightSC = in2R * *params[param_sc_level];
1088 leftMC = inL;
1089 rightMC = inR;
1092 switch ((CalfScModes)*params[param_sc_mode]) {
1093 default:
1094 case WIDEBAND:
1095 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1096 leftMC = leftSC;
1097 rightMC = rightSC;
1098 break;
1099 case DEESSER_WIDE:
1100 case DERUMBLER_WIDE:
1101 case WEIGHTED_1:
1102 case WEIGHTED_2:
1103 case WEIGHTED_3:
1104 case BANDPASS_2:
1105 leftSC = f2L.process(f1L.process(leftSC));
1106 rightSC = f2R.process(f1R.process(rightSC));
1107 leftMC = leftSC;
1108 rightMC = rightSC;
1109 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1110 break;
1111 case DEESSER_SPLIT:
1112 leftSC = f2L.process(leftSC);
1113 rightSC = f2R.process(rightSC);
1114 leftMC = leftSC;
1115 rightMC = rightSC;
1116 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1117 leftAC = f1L.process(leftAC);
1118 rightAC = f1R.process(rightAC);
1119 leftAC += leftSC;
1120 rightAC += rightSC;
1121 break;
1122 case DERUMBLER_SPLIT:
1123 leftSC = f1L.process(leftSC);
1124 rightSC = f1R.process(rightSC);
1125 leftMC = leftSC;
1126 rightMC = rightSC;
1127 compressor.process(leftSC, rightSC, &leftSC, &rightSC);
1128 leftAC = f2L.process(leftAC);
1129 rightAC = f2R.process(rightAC);
1130 leftAC += leftSC;
1131 rightAC += rightSC;
1132 break;
1133 case BANDPASS_1:
1134 leftSC = f1L.process(leftSC);
1135 rightSC = f1R.process(rightSC);
1136 leftMC = leftSC;
1137 rightMC = rightSC;
1138 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1139 break;
1142 if(*params[param_sc_listen] > 0.f) {
1143 outL = leftMC;
1144 outR = rightMC;
1145 } else {
1146 outL = leftAC;
1147 outR = rightAC;
1148 // mix
1149 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1150 outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1153 // send to output
1154 outs[0][offset] = outL;
1155 outs[1][offset] = outR;
1157 float values[] = {std::max(inL, inR), std::max(outL, outR), compressor.get_comp_level()};
1158 meters.process(values);
1160 // next sample
1161 ++offset;
1162 } // cycle trough samples
1163 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
1164 f1L.sanitize();
1165 f1R.sanitize();
1166 f2L.sanitize();
1167 f2R.sanitize();
1169 meters.fall(numsamples);
1170 return outputs_mask;
1172 bool sidechaincompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1174 if (!is_active or phase)
1175 return false;
1176 if (index == param_sc_listen && !subindex) {
1177 return ::get_graph(*this, subindex, data, points);
1178 } else if(index == param_bypass) {
1179 return compressor.get_graph(subindex, data, points, context, mode);
1181 return false;
1184 bool sidechaincompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1186 if (!is_active or !phase)
1187 return false;
1188 if (index == param_bypass) {
1189 return compressor.get_dot(subindex, x, y, size, context);
1191 return false;
1194 bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1196 if (!is_active or phase)
1197 return false;
1198 if (index == param_bypass) {
1199 return compressor.get_gridline(subindex, pos, vertical, legend, context);
1200 } else {
1201 return get_freq_gridline(subindex, pos, vertical, legend, context);
1203 return false;
1206 bool sidechaincompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1208 if(index == param_bypass)
1209 return compressor.get_layers(index, generation, layers);
1210 bool redraw = redraw_graph || !generation;
1211 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
1212 redraw_graph = false;
1213 return redraw;
1216 /**********************************************************************
1217 * MULTIBAND COMPRESSOR by Markus Schmidt
1218 **********************************************************************/
1220 multibandcompressor_audio_module::multibandcompressor_audio_module()
1222 is_active = false;
1223 srate = 0;
1224 mode = 0;
1225 redraw = 0;
1226 page = 0;
1227 bypass_ = 0;
1228 crossover.init(2, 4, 44100);
1231 void multibandcompressor_audio_module::activate()
1233 is_active = true;
1234 // set all filters and strips
1235 params_changed();
1236 // activate all strips
1237 for (int j = 0; j < strips; j ++) {
1238 strip[j].activate();
1239 strip[j].id = j;
1243 void multibandcompressor_audio_module::deactivate()
1245 is_active = false;
1246 // deactivate all strips
1247 for (int j = 0; j < strips; j ++) {
1248 strip[j].deactivate();
1252 void multibandcompressor_audio_module::params_changed()
1254 // determine mute/solo states
1255 solo[0] = *params[param_solo0] > 0.f ? true : false;
1256 solo[1] = *params[param_solo1] > 0.f ? true : false;
1257 solo[2] = *params[param_solo2] > 0.f ? true : false;
1258 solo[3] = *params[param_solo3] > 0.f ? true : false;
1259 no_solo = (*params[param_solo0] > 0.f ||
1260 *params[param_solo1] > 0.f ||
1261 *params[param_solo2] > 0.f ||
1262 *params[param_solo3] > 0.f) ? false : true;
1265 int m = *params[param_mode];
1266 if (m != mode) {
1267 mode = *params[param_mode];
1270 int p = (int)*params[param_notebook];
1271 if (p != page) {
1272 page = p;
1273 redraw = strips * 2 + strips;
1276 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
1277 if (b != bypass_) {
1278 redraw = strips * 2 + strips;
1279 bypass_ = b;
1282 crossover.set_mode(mode + 1);
1283 crossover.set_filter(0, *params[param_freq0]);
1284 crossover.set_filter(1, *params[param_freq1]);
1285 crossover.set_filter(2, *params[param_freq2]);
1287 // set the params of all strips
1288 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));
1289 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));
1290 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));
1291 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));
1294 void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
1296 srate = sr;
1297 // set srate of all strips
1298 for (int j = 0; j < strips; j ++) {
1299 strip[j].set_sample_rate(srate);
1301 // set srate of crossover
1302 crossover.set_sample_rate(srate);
1303 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
1304 param_output0, -param_compression0,
1305 param_output1, -param_compression1,
1306 param_output2, -param_compression2,
1307 param_output3, -param_compression3 };
1308 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
1309 meters.init(params, meter, clip, 12, srate);
1312 uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1314 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1315 numsamples += offset;
1317 for (int i = 0; i < strips; i++)
1318 strip[i].update_curve();
1319 if(bypassed) {
1320 // everything bypassed
1321 while(offset < numsamples) {
1322 outs[0][offset] = ins[0][offset];
1323 outs[1][offset] = ins[1][offset];
1324 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
1325 meters.process(values);
1326 ++offset;
1328 } else {
1329 // process all strips
1330 uint32_t orig_numsamples = numsamples-offset;
1331 uint32_t orig_offset = offset;
1332 while(offset < numsamples) {
1333 // cycle through samples
1334 float inL = ins[0][offset];
1335 float inR = ins[1][offset];
1336 // in level
1337 inR *= *params[param_level_in];
1338 inL *= *params[param_level_in];
1339 // process crossover
1340 xin[0] = inL;
1341 xin[1] = inR;
1342 crossover.process(xin);
1343 // out vars
1344 float outL = 0.f;
1345 float outR = 0.f;
1346 for (int i = 0; i < strips; i ++) {
1347 // cycle trough strips
1348 if (solo[i] || no_solo) {
1349 // strip unmuted
1350 float left = crossover.get_value(0, i);
1351 float right = crossover.get_value(1, i);
1352 // process gain reduction
1353 strip[i].process(left, right);
1354 // sum up output
1355 outL += left;
1356 outR += right;
1358 } // process single strip
1360 // out level
1361 outL *= *params[param_level_out];
1362 outR *= *params[param_level_out];
1364 // send to output
1365 outs[0][offset] = outL;
1366 outs[1][offset] = outR;
1368 float values[] = {inL, inR, outL, outR,
1369 *params[param_bypass0] > 0.5f ? 0 : strip[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : strip[0].get_comp_level(),
1370 *params[param_bypass1] > 0.5f ? 0 : strip[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : strip[1].get_comp_level(),
1371 *params[param_bypass2] > 0.5f ? 0 : strip[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : strip[2].get_comp_level(),
1372 *params[param_bypass3] > 0.5f ? 0 : strip[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : strip[3].get_comp_level() };
1373 meters.process(values);
1375 // next sample
1376 ++offset;
1377 } // cycle trough samples
1378 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
1379 } // process all strips (no bypass)
1380 meters.fall(numsamples);
1381 return outputs_mask;
1384 const gain_reduction_audio_module *multibandcompressor_audio_module::get_strip_by_param_index(int index) const
1386 // let's handle by the corresponding strip
1387 switch (index) {
1388 case param_solo0:
1389 return &strip[0];
1390 case param_solo1:
1391 return &strip[1];
1392 case param_solo2:
1393 return &strip[2];
1394 case param_solo3:
1395 return &strip[3];
1397 return NULL;
1400 bool multibandcompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1402 bool r;
1404 if (redraw)
1405 redraw = std::max(0, redraw - 1);
1407 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1408 if (m) {
1409 r = m->get_graph(subindex, data, points, context, mode);
1410 } else {
1411 r = crossover.get_graph(subindex, phase, data, points, context, mode);
1413 if ((index == param_solo0 + 11 * page and subindex == 1)
1414 or (index == param_bypass and subindex == page)) {
1415 *mode = 1;
1417 if ((subindex == 1 and index != param_bypass)
1418 or (index == param_bypass)) {
1419 if (r
1420 and ((index != param_bypass and *params[index - 1])
1421 or (index == param_bypass and *params[param_bypass0 + 11 * subindex])))
1422 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
1423 else
1424 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
1426 return r;
1429 bool multibandcompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1431 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1432 if (m)
1433 return m->get_dot(subindex, x, y, size, context);
1434 return false;
1437 bool multibandcompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1439 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1440 if (m)
1441 return m->get_gridline(subindex, pos, vertical, legend, context);
1442 if (phase) return false;
1443 return get_freq_gridline(subindex, pos, vertical, legend, context);
1446 bool multibandcompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1448 bool r;
1449 const gain_reduction_audio_module *m = get_strip_by_param_index(index);
1450 if (m) {
1451 r = m->get_layers(index, generation, layers);
1452 } else {
1453 r = crossover.get_layers(index, generation, layers);
1455 if (redraw) {
1456 layers |= LG_CACHE_GRAPH;
1457 r = true;
1459 return r;
1463 /**********************************************************************
1464 * MONO COMPRESSOR by Damien Zammit
1465 **********************************************************************/
1467 monocompressor_audio_module::monocompressor_audio_module()
1469 is_active = false;
1470 srate = 0;
1473 void monocompressor_audio_module::activate()
1475 is_active = true;
1476 // set all filters and strips
1477 monocompressor.activate();
1478 params_changed();
1480 void monocompressor_audio_module::deactivate()
1482 is_active = false;
1483 monocompressor.deactivate();
1486 void monocompressor_audio_module::params_changed()
1488 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);
1491 void monocompressor_audio_module::set_sample_rate(uint32_t sr)
1493 srate = sr;
1494 monocompressor.set_sample_rate(srate);
1495 int meter[] = {param_meter_in, param_meter_out, -param_compression};
1496 int clip[] = {param_clip_in, param_clip_out, -1};
1497 meters.init(params, meter, clip, 3, srate);
1500 uint32_t monocompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1502 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1503 numsamples += offset;
1504 if(bypassed) {
1505 // everything bypassed
1506 while(offset < numsamples) {
1507 outs[0][offset] = ins[0][offset];
1508 float values[] = {0, 0, 1};
1509 meters.process(values);
1510 ++offset;
1512 } else {
1513 // process
1514 uint32_t orig_numsamples = numsamples-offset;
1515 uint32_t orig_offset = offset;
1516 monocompressor.update_curve();
1518 while(offset < numsamples) {
1519 // cycle through samples
1520 float outL = 0.f;
1521 //float outR = 0.f;
1522 float inL = ins[0][offset];
1523 //float inR = ins[1][offset];
1524 float Lin = ins[0][offset];
1525 //float Rin = ins[1][offset];
1527 // in level
1528 //inR *= *params[param_level_in];
1529 inL *= *params[param_level_in];
1531 float leftAC = inL;
1532 //float rightAC = inR;
1534 monocompressor.process(leftAC);
1536 outL = leftAC;
1537 //outR = rightAC;
1539 // mix
1540 outL = outL * *params[param_mix] + Lin * (*params[param_mix] * -1 + 1);
1541 //outR = outR * *params[param_mix] + Rin * (*params[param_mix] * -1 + 1);
1543 // send to output
1544 outs[0][offset] = outL;
1545 //outs[1][offset] = 0.f;
1547 float values[] = {inL, outL, monocompressor.get_comp_level()};
1548 meters.process(values);
1550 // next sample
1551 ++offset;
1552 } // cycle trough samples
1553 bypass.crossfade(ins, outs, 1, orig_offset, orig_numsamples);
1555 meters.fall(numsamples);
1556 return outputs_mask;
1558 bool monocompressor_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1560 return monocompressor.get_graph(subindex, data, points, context, mode);
1563 bool monocompressor_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1565 return monocompressor.get_dot(subindex, x, y, size, context);
1568 bool monocompressor_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1570 return monocompressor.get_gridline(subindex, pos, vertical, legend, context);
1573 bool monocompressor_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1575 return monocompressor.get_layers(index, generation, layers);
1578 /**********************************************************************
1579 * DEESSER by Markus Schmidt
1580 **********************************************************************/
1582 deesser_audio_module::deesser_audio_module()
1584 is_active = false;
1585 srate = 0;
1586 f1_freq_old1 = 0.f;
1587 f2_freq_old1 = 0.f;
1588 f1_level_old1 = 0.f;
1589 f2_level_old1 = 0.f;
1590 f2_q_old1 = 0.f;
1591 f1_freq_old = 0.f;
1592 f2_freq_old = 0.f;
1593 f1_level_old = 0.f;
1594 f2_level_old = 0.f;
1595 f2_q_old = 0.f;
1596 detected_led = 0;
1597 redraw_graph = true;
1600 void deesser_audio_module::activate()
1602 is_active = true;
1603 // set all filters and strips
1604 compressor.activate();
1605 params_changed();
1606 detected = 0.f;
1607 detected_led = 0.f;
1609 void deesser_audio_module::deactivate()
1611 is_active = false;
1612 compressor.deactivate();
1615 void deesser_audio_module::params_changed()
1617 // set the params of all filters
1618 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1619 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1620 or *params[param_f2_q] != f2_q_old) {
1621 float q = 0.707;
1623 hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
1624 hpR.copy_coeffs(hpL);
1625 lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
1626 lpR.copy_coeffs(lpL);
1627 pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
1628 pR.copy_coeffs(pL);
1629 f1_freq_old = *params[param_f1_freq];
1630 f1_level_old = *params[param_f1_level];
1631 f2_freq_old = *params[param_f2_freq];
1632 f2_level_old = *params[param_f2_level];
1633 f2_q_old = *params[param_f2_q];
1635 // and set the compressor module
1636 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);
1637 if (*params[param_f1_freq] != f1_freq_old1
1638 or *params[param_f2_freq] != f2_freq_old1
1639 or *params[param_f1_level] != f1_level_old1
1640 or *params[param_f2_level] != f2_level_old1
1641 or *params[param_f2_q] !=f2_q_old1)
1643 f1_freq_old1 = *params[param_f1_freq];
1644 f2_freq_old1 = *params[param_f2_freq];
1645 f1_level_old1 = *params[param_f1_level];
1646 f2_level_old1 = *params[param_f2_level];
1647 f2_q_old1 = *params[param_f2_q];
1648 redraw_graph = true;
1652 void deesser_audio_module::set_sample_rate(uint32_t sr)
1654 srate = sr;
1655 compressor.set_sample_rate(srate);
1656 int meter[] = {param_detected, -param_compression};
1657 int clip[] = {param_clip_out, -1};
1658 meters.init(params, meter, clip, 2, srate);
1661 uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1663 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1664 numsamples += offset;
1665 if(bypassed) {
1666 // everything bypassed81e8da266
1667 while(offset < numsamples) {
1668 outs[0][offset] = ins[0][offset];
1669 outs[1][offset] = ins[1][offset];
1670 float values[] = {0, 1};
1671 meters.process(values);
1672 ++offset;
1674 } else {
1675 // process
1676 uint32_t orig_numsamples = numsamples-offset;
1677 uint32_t orig_offset = offset;
1678 detected_led -= std::min(detected_led, numsamples);
1679 compressor.update_curve();
1681 while(offset < numsamples) {
1682 // cycle through samples
1683 float outL = 0.f;
1684 float outR = 0.f;
1685 float inL = ins[0][offset];
1686 float inR = ins[1][offset];
1689 float leftAC = inL;
1690 float rightAC = inR;
1691 float leftSC = inL;
1692 float rightSC = inR;
1693 float leftRC = inL;
1694 float rightRC = inR;
1695 float leftMC = inL;
1696 float rightMC = inR;
1698 leftSC = pL.process(hpL.process(leftSC));
1699 rightSC = pR.process(hpR.process(rightSC));
1700 leftMC = leftSC;
1701 rightMC = rightSC;
1703 switch ((int)*params[param_mode]) {
1704 default:
1705 case WIDE:
1706 compressor.process(leftAC, rightAC, &leftSC, &rightSC);
1707 break;
1708 case SPLIT:
1709 hpL.sanitize();
1710 hpR.sanitize();
1711 leftRC = hpL.process(leftRC);
1712 rightRC = hpR.process(rightRC);
1713 compressor.process(leftRC, rightRC, &leftSC, &rightSC);
1714 leftAC = lpL.process(leftAC);
1715 rightAC = lpR.process(rightAC);
1716 leftAC += leftRC;
1717 rightAC += rightRC;
1718 break;
1721 if(*params[param_sc_listen] > 0.f) {
1722 outL = leftMC;
1723 outR = rightMC;
1724 } else {
1725 outL = leftAC;
1726 outR = rightAC;
1729 // send to output
1730 outs[0][offset] = outL;
1731 outs[1][offset] = outR;
1733 if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) {
1734 detected_led = srate >> 3;
1736 detected = std::max(fabs(leftMC), fabs(rightMC));
1738 float values[] = {detected, compressor.get_comp_level()};
1739 meters.process(values);
1741 // next sample
1742 ++offset;
1743 } // cycle trough samples
1744 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
1745 hpL.sanitize();
1746 hpR.sanitize();
1747 lpL.sanitize();
1748 lpR.sanitize();
1749 pL.sanitize();
1750 pR.sanitize();
1752 // draw meters
1753 if(params[param_detected_led] != NULL) {
1754 *params[param_detected_led] = detected_led;
1756 meters.fall(numsamples);
1757 return outputs_mask;
1761 /**********************************************************************
1762 * GATE AUDIO MODULE Damien Zammit
1763 **********************************************************************/
1765 gate_audio_module::gate_audio_module()
1767 is_active = false;
1768 srate = 0;
1771 void gate_audio_module::activate()
1773 is_active = true;
1774 // set all filters and strips
1775 gate.activate();
1776 params_changed();
1778 void gate_audio_module::deactivate()
1780 is_active = false;
1781 gate.deactivate();
1784 void gate_audio_module::params_changed()
1786 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]);
1789 void gate_audio_module::set_sample_rate(uint32_t sr)
1791 srate = sr;
1792 gate.set_sample_rate(srate);
1793 int meter[] = {param_meter_in, param_meter_out, -param_gating};
1794 int clip[] = {param_clip_in, param_clip_out, -1};
1795 meters.init(params, meter, clip, 3, srate);
1798 uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1800 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1801 numsamples += offset;
1802 if(bypassed) {
1803 // everything bypassed
1804 while(offset < numsamples) {
1805 outs[0][offset] = ins[0][offset];
1806 outs[1][offset] = ins[1][offset];
1807 float values[] = {0, 0, 1};
1808 meters.process(values);
1809 ++offset;
1811 } else {
1812 // process
1813 gate.update_curve();
1814 uint32_t orig_numsamples = numsamples-offset;
1815 uint32_t orig_offset = offset;
1816 while(offset < numsamples) {
1817 // cycle through samples
1818 float outL = 0.f;
1819 float outR = 0.f;
1820 float inL = ins[0][offset];
1821 float inR = ins[1][offset];
1822 // in level
1823 inR *= *params[param_level_in];
1824 inL *= *params[param_level_in];
1826 float leftAC = inL;
1827 float rightAC = inR;
1829 gate.process(leftAC, rightAC);
1831 outL = leftAC;
1832 outR = rightAC;
1834 // send to output
1835 outs[0][offset] = outL;
1836 outs[1][offset] = outR;
1838 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
1839 meters.process(values);
1841 // next sample
1842 ++offset;
1843 } // cycle trough samples
1844 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
1846 meters.fall(numsamples);
1847 return outputs_mask;
1849 bool gate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1851 return gate.get_graph(subindex, data, points, context, mode);
1854 bool gate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
1856 return gate.get_dot(subindex, x, y, size, context);
1859 bool gate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
1861 return gate.get_gridline(subindex, pos, vertical, legend, context);
1864 bool gate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1866 return gate.get_layers(index, generation, layers);
1869 /**********************************************************************
1870 * SIDECHAIN GATE by Markus Schmidt
1871 **********************************************************************/
1873 sidechaingate_audio_module::sidechaingate_audio_module()
1875 is_active = false;
1876 srate = 0;
1877 redraw_graph = true;
1878 f1_freq_old = f2_freq_old = f1_level_old = f2_level_old = 0;
1879 f1_freq_old1 = f2_freq_old1 = f1_level_old1 = f2_level_old1 = 0;
1880 sc_mode_old = sc_mode_old1 = WIDEBAND; // doesn't matter as long as it's sane
1883 void sidechaingate_audio_module::activate()
1885 is_active = true;
1886 // set all filters and strips
1887 gate.activate();
1888 params_changed();
1890 void sidechaingate_audio_module::deactivate()
1892 is_active = false;
1893 gate.deactivate();
1896 sidechaingate_audio_module::cfloat sidechaingate_audio_module::h_z(const cfloat &z) const
1898 switch ((CalfScModes)sc_mode) {
1899 default:
1900 case WIDEBAND:
1901 return false;
1902 break;
1903 case HIGHGATE_WIDE:
1904 case LOWGATE_WIDE:
1905 case WEIGHTED_1:
1906 case WEIGHTED_2:
1907 case WEIGHTED_3:
1908 case BANDPASS_2:
1909 return f1L.h_z(z) * f2L.h_z(z);
1910 break;
1911 case HIGHGATE_SPLIT:
1912 return f2L.h_z(z);
1913 break;
1914 case LOWGATE_SPLIT:
1915 case BANDPASS_1:
1916 return f1L.h_z(z);
1917 break;
1921 float sidechaingate_audio_module::freq_gain(int index, double freq) const
1923 typedef std::complex<double> cfloat;
1924 freq *= 2.0 * M_PI / srate;
1925 cfloat z = 1.0 / exp(cfloat(0.0, freq));
1927 return std::abs(h_z(z));
1930 void sidechaingate_audio_module::params_changed()
1932 // set the params of all filters
1933 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1934 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1935 or *params[param_sc_mode] != sc_mode) {
1936 float q = 0.707;
1937 switch ((CalfScModes)*params[param_sc_mode]) {
1938 default:
1939 case WIDEBAND:
1940 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1941 f1R.copy_coeffs(f1L);
1942 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1943 f2R.copy_coeffs(f2L);
1944 f1_active = 0.f;
1945 f2_active = 0.f;
1946 break;
1947 case HIGHGATE_WIDE:
1948 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1949 f1R.copy_coeffs(f1L);
1950 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1951 f2R.copy_coeffs(f2L);
1952 f1_active = 0.5f;
1953 f2_active = 1.f;
1954 break;
1955 case HIGHGATE_SPLIT:
1956 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
1957 f1R.copy_coeffs(f1L);
1958 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
1959 f2R.copy_coeffs(f2L);
1960 f1_active = 0.f;
1961 f2_active = 1.f;
1962 break;
1963 case LOWGATE_WIDE:
1964 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1965 f1R.copy_coeffs(f1L);
1966 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1967 f2R.copy_coeffs(f2L);
1968 f1_active = 1.f;
1969 f2_active = 0.5f;
1970 break;
1971 case LOWGATE_SPLIT:
1972 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
1973 f1R.copy_coeffs(f1L);
1974 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
1975 f2R.copy_coeffs(f2L);
1976 f1_active = 1.f;
1977 f2_active = 0.f;
1978 break;
1979 case WEIGHTED_1:
1980 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1981 f1R.copy_coeffs(f1L);
1982 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1983 f2R.copy_coeffs(f2L);
1984 f1_active = 0.5f;
1985 f2_active = 0.5f;
1986 break;
1987 case WEIGHTED_2:
1988 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1989 f1R.copy_coeffs(f1L);
1990 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1991 f2R.copy_coeffs(f2L);
1992 f1_active = 0.5f;
1993 f2_active = 0.5f;
1994 break;
1995 case WEIGHTED_3:
1996 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1997 f1R.copy_coeffs(f1L);
1998 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1999 f2R.copy_coeffs(f2L);
2000 f1_active = 0.5f;
2001 f2_active = 0.5f;
2002 break;
2003 case BANDPASS_1:
2004 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
2005 f1R.copy_coeffs(f1L);
2006 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
2007 f2R.copy_coeffs(f2L);
2008 f1_active = 1.f;
2009 f2_active = 0.f;
2010 break;
2011 case BANDPASS_2:
2012 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
2013 f1R.copy_coeffs(f1L);
2014 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
2015 f2R.copy_coeffs(f2L);
2016 f1_active = 1.f;
2017 f2_active = 1.f;
2018 break;
2020 f1_freq_old = *params[param_f1_freq];
2021 f1_level_old = *params[param_f1_level];
2022 f2_freq_old = *params[param_f2_freq];
2023 f2_level_old = *params[param_f2_level];
2024 sc_mode = (CalfScModes)*params[param_sc_mode];
2026 // light LED's
2027 if(params[param_f1_active] != NULL) {
2028 *params[param_f1_active] = f1_active;
2030 if(params[param_f2_active] != NULL) {
2031 *params[param_f2_active] = f2_active;
2033 // and set the expander module
2034 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]);
2036 if (*params[param_f1_freq] != f1_freq_old1
2037 or *params[param_f2_freq] != f2_freq_old1
2038 or *params[param_f1_level] != f1_level_old1
2039 or *params[param_f2_level] != f2_level_old1
2040 or *params[param_sc_mode] != sc_mode_old1)
2042 f1_freq_old1 = *params[param_f1_freq];
2043 f2_freq_old1 = *params[param_f2_freq];
2044 f1_level_old1 = *params[param_f1_level];
2045 f2_level_old1 = *params[param_f2_level];
2046 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
2047 redraw_graph = true;
2051 void sidechaingate_audio_module::set_sample_rate(uint32_t sr)
2053 srate = sr;
2054 gate.set_sample_rate(srate);
2055 int meter[] = {param_meter_in, param_meter_out, -param_gating};
2056 int clip[] = {param_clip_in, param_clip_out, -1};
2057 meters.init(params, meter, clip, 3, srate);
2060 uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2062 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2063 numsamples += offset;
2064 if(bypassed) {
2065 // everything bypassed
2066 while(offset < numsamples) {
2067 outs[0][offset] = ins[0][offset];
2068 outs[1][offset] = ins[1][offset];
2069 float values[] = {0, 0, 1};
2070 meters.process(values);
2071 ++offset;
2073 } else {
2074 // process
2075 uint32_t orig_numsamples = numsamples-offset;
2076 uint32_t orig_offset = offset;
2077 gate.update_curve();
2079 while(offset < numsamples) {
2080 // cycle through samples
2081 float outL = 0.f;
2082 float outR = 0.f;
2083 float inL = ins[0][offset];
2084 float inR = ins[1][offset];
2086 float in2L = ins[2] ? ins[2][offset] : 0;
2087 float in2R = ins[3] ? ins[3][offset] : 0;
2089 // in level
2090 inR *= *params[param_level_in];
2091 inL *= *params[param_level_in];
2093 float leftAC = inL;
2094 float rightAC = inR;
2095 float leftSC = inL;
2096 float rightSC = inR;
2097 float leftMC = inL;
2098 float rightMC = inR;
2100 if (*params[param_sc_route] > 0.5) {
2101 leftAC = inL;
2102 rightAC = inR;
2103 leftSC = in2L * *params[param_sc_level];
2104 rightSC = in2R * *params[param_sc_level];
2105 leftMC = inL;
2106 rightMC = inR;
2109 switch ((CalfScModes)*params[param_sc_mode]) {
2110 default:
2111 case WIDEBAND:
2112 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2113 leftMC = leftSC;
2114 rightMC = rightSC;
2115 break;
2116 case HIGHGATE_WIDE:
2117 case LOWGATE_WIDE:
2118 case WEIGHTED_1:
2119 case WEIGHTED_2:
2120 case WEIGHTED_3:
2121 case BANDPASS_2:
2122 leftSC = f2L.process(f1L.process(leftSC));
2123 rightSC = f2R.process(f1R.process(rightSC));
2124 leftMC = leftSC;
2125 rightMC = rightSC;
2126 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2127 break;
2128 case HIGHGATE_SPLIT:
2129 leftSC = f2L.process(leftSC);
2130 rightSC = f2R.process(rightSC);
2131 leftMC = leftSC;
2132 rightMC = rightSC;
2133 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2134 leftAC = f1L.process(leftAC);
2135 rightAC = f1R.process(rightAC);
2136 leftAC += leftSC;
2137 rightAC += rightSC;
2138 break;
2139 case LOWGATE_SPLIT:
2140 leftSC = f1L.process(leftSC);
2141 rightSC = f1R.process(rightSC);
2142 leftMC = leftSC;
2143 rightMC = rightSC;
2144 gate.process(leftSC, rightSC, &leftSC, &rightSC);
2145 leftAC = f2L.process(leftAC);
2146 rightAC = f2R.process(rightAC);
2147 leftAC += leftSC;
2148 rightAC += rightSC;
2149 break;
2150 case BANDPASS_1:
2151 leftSC = f1L.process(leftSC);
2152 rightSC = f1R.process(rightSC);
2153 leftMC = leftSC;
2154 rightMC = rightSC;
2155 gate.process(leftAC, rightAC, &leftSC, &rightSC);
2156 break;
2159 if(*params[param_sc_listen] > 0.f) {
2160 outL = leftMC;
2161 outR = rightMC;
2162 } else {
2163 outL = leftAC;
2164 outR = rightAC;
2167 // send to output
2168 outs[0][offset] = outL;
2169 outs[1][offset] = outR;
2171 float values[] = {std::max(inL, inR), std::max(outL, outR), gate.get_expander_level()};
2172 meters.process(values);
2174 // next sample
2175 ++offset;
2176 } // cycle trough samples
2177 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
2178 f1L.sanitize();
2179 f1R.sanitize();
2180 f2L.sanitize();
2181 f2R.sanitize();
2184 meters.fall(numsamples);
2185 return outputs_mask;
2187 bool sidechaingate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2189 if (!is_active or phase)
2190 return false;
2191 if (index == param_sc_listen && !subindex) {
2192 return ::get_graph(*this, subindex, data, points);
2193 } else if(index == param_bypass) {
2194 return gate.get_graph(subindex, data, points, context, mode);
2196 return false;
2199 bool sidechaingate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2201 if (!is_active or !phase)
2202 return false;
2203 if (index == param_bypass) {
2204 return gate.get_dot(subindex, x, y, size, context);
2206 return false;
2209 bool sidechaingate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2211 if (!is_active or phase)
2212 return false;
2213 if (index == param_bypass) {
2214 return gate.get_gridline(subindex, pos, vertical, legend, context);
2215 } else {
2216 return get_freq_gridline(subindex, pos, vertical, legend, context);
2218 return false;
2220 bool sidechaingate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2222 if(index == param_bypass)
2223 return gate.get_layers(index, generation, layers);
2224 bool redraw = redraw_graph || !generation;
2225 layers = 0 | (generation ? 0 : LG_CACHE_GRID) | (redraw ? LG_CACHE_GRAPH : 0);
2226 redraw_graph = false;
2227 return redraw;
2231 /**********************************************************************
2232 * MULTIBAND GATE by Markus Schmidt
2233 **********************************************************************/
2235 multibandgate_audio_module::multibandgate_audio_module()
2237 is_active = false;
2238 srate = 0;
2239 mode = 0;
2240 redraw = 0;
2241 page = 0;
2242 bypass_ = 0;
2243 crossover.init(2, 4, 44100);
2246 void multibandgate_audio_module::activate()
2248 is_active = true;
2249 // set all filters and strips
2250 params_changed();
2251 // activate all strips
2252 for (int j = 0; j < strips; j ++) {
2253 gate[j].activate();
2254 gate[j].id = j;
2258 void multibandgate_audio_module::deactivate()
2260 is_active = false;
2261 // deactivate all strips
2262 for (int j = 0; j < strips; j ++) {
2263 gate[j].deactivate();
2267 void multibandgate_audio_module::params_changed()
2269 // determine mute/solo states
2270 solo[0] = *params[param_solo0] > 0.f ? true : false;
2271 solo[1] = *params[param_solo1] > 0.f ? true : false;
2272 solo[2] = *params[param_solo2] > 0.f ? true : false;
2273 solo[3] = *params[param_solo3] > 0.f ? true : false;
2274 no_solo = (*params[param_solo0] > 0.f ||
2275 *params[param_solo1] > 0.f ||
2276 *params[param_solo2] > 0.f ||
2277 *params[param_solo3] > 0.f) ? false : true;
2279 int m = *params[param_mode];
2280 if (m != mode) {
2281 mode = *params[param_mode];
2284 int p = (int)*params[param_notebook];
2285 if (p != page) {
2286 page = p;
2287 redraw = strips * 2 + strips;
2290 int b = (int)*params[param_bypass0] + (int)*params[param_bypass1] + (int)*params[param_bypass2] + (int)*params[param_bypass3];
2291 if (b != bypass_) {
2292 redraw = strips * 2 + strips;
2293 bypass_ = b;
2296 crossover.set_mode(mode + 1);
2297 crossover.set_filter(0, *params[param_freq0]);
2298 crossover.set_filter(1, *params[param_freq1]);
2299 crossover.set_filter(2, *params[param_freq2]);
2301 // set the params of all strips
2302 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]);
2303 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]);
2304 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]);
2305 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]);
2308 void multibandgate_audio_module::set_sample_rate(uint32_t sr)
2310 srate = sr;
2311 // set srate of all strips
2312 for (int j = 0; j < strips; j ++) {
2313 gate[j].set_sample_rate(srate);
2315 // set srate of crossover
2316 crossover.set_sample_rate(srate);
2317 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR,
2318 param_output0, -param_gating0,
2319 param_output1, -param_gating1,
2320 param_output2, -param_gating2,
2321 param_output3, -param_gating3 };
2322 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1, -1, -1, -1, -1, -1, -1};
2323 meters.init(params, meter, clip, 12, srate);
2326 uint32_t multibandgate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2328 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2329 numsamples += offset;
2330 for (int i = 0; i < strips; i++)
2331 gate[i].update_curve();
2332 if(bypassed) {
2333 // everything bypassed
2334 while(offset < numsamples) {
2335 outs[0][offset] = ins[0][offset];
2336 outs[1][offset] = ins[1][offset];
2337 float values[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1};
2338 meters.process(values);
2339 ++offset;
2341 } else {
2342 // process all strips
2343 uint32_t orig_numsamples = numsamples-offset;
2344 uint32_t orig_offset = offset;
2345 while(offset < numsamples) {
2346 // cycle through samples
2347 float inL = ins[0][offset];
2348 float inR = ins[1][offset];
2349 // in level
2350 inR *= *params[param_level_in];
2351 inL *= *params[param_level_in];
2352 // process crossover
2353 xin[0] = inL;
2354 xin[1] = inR;
2355 crossover.process(xin);
2356 // out vars
2357 float outL = 0.f;
2358 float outR = 0.f;
2359 for (int i = 0; i < strips; i ++) {
2360 // cycle trough strips
2361 if (solo[i] || no_solo) {
2362 // strip unmuted
2363 float left = crossover.get_value(0, i);
2364 float right = crossover.get_value(1, i);
2365 gate[i].process(left, right);
2366 // sum up output
2367 outL += left;
2368 outR += right;
2370 } // process single strip
2372 // out level
2373 outL *= *params[param_level_out];
2374 outR *= *params[param_level_out];
2376 // send to output
2377 outs[0][offset] = outL;
2378 outs[1][offset] = outR;
2380 float values[] = {inL, inR, outL, outR,
2381 *params[param_bypass0] > 0.5f ? 0 : gate[0].get_output_level(), *params[param_bypass0] > 0.5f ? 1 : gate[0].get_expander_level(),
2382 *params[param_bypass1] > 0.5f ? 0 : gate[1].get_output_level(), *params[param_bypass1] > 0.5f ? 1 : gate[1].get_expander_level(),
2383 *params[param_bypass2] > 0.5f ? 0 : gate[2].get_output_level(), *params[param_bypass2] > 0.5f ? 1 : gate[2].get_expander_level(),
2384 *params[param_bypass3] > 0.5f ? 0 : gate[3].get_output_level(), *params[param_bypass3] > 0.5f ? 1 : gate[3].get_expander_level() };
2385 meters.process(values);
2387 // next sample
2388 ++offset;
2389 } // cycle trough samples
2390 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
2392 } // process all strips (no bypass)
2393 meters.fall(numsamples);
2394 return outputs_mask;
2397 const expander_audio_module *multibandgate_audio_module::get_strip_by_param_index(int index) const
2399 // let's handle by the corresponding strip
2400 switch (index) {
2401 case param_solo0:
2402 return &gate[0];
2403 case param_solo1:
2404 return &gate[1];
2405 case param_solo2:
2406 return &gate[2];
2407 case param_solo3:
2408 return &gate[3];
2410 return NULL;
2413 bool multibandgate_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2415 bool r;
2416 if (redraw)
2417 redraw = std::max(0, redraw - 1);
2419 const expander_audio_module *m = get_strip_by_param_index(index);
2420 if (m) {
2421 r = m->get_graph(subindex, data, points, context, mode);
2422 } else {
2423 r = crossover.get_graph(subindex, phase, data, points, context, mode);
2425 if ((index == param_solo0 + 12 * page and subindex == 1)
2426 or (index == param_bypass and subindex == page)) {
2427 *mode = 1;
2429 if ((subindex == 1 and index != param_bypass)
2430 or (index == param_bypass)) {
2431 if (r
2432 and ((index != param_bypass and *params[index - 1])
2433 or (index == param_bypass and *params[param_bypass0 + 12 * subindex])))
2434 context->set_source_rgba(0.15, 0.2, 0.0, 0.15);
2435 else
2436 context->set_source_rgba(0.15, 0.2, 0.0, 0.5);
2438 return r;
2441 bool multibandgate_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
2443 const expander_audio_module *m = get_strip_by_param_index(index);
2444 if (m)
2445 return m->get_dot(subindex, x, y, size, context);
2446 return false;
2449 bool multibandgate_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2451 const expander_audio_module *m = get_strip_by_param_index(index);
2452 if (m)
2453 return m->get_gridline(subindex, pos, vertical, legend, context);
2454 if (phase) return false;
2455 return get_freq_gridline(subindex, pos, vertical, legend, context);
2458 bool multibandgate_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2460 bool r;
2461 const expander_audio_module *m = get_strip_by_param_index(index);
2462 if (m) {
2463 r = m->get_layers(index, generation, layers);
2464 } else {
2465 r = crossover.get_layers(index, generation, layers);
2467 if (redraw) {
2468 layers |= LG_CACHE_GRAPH;
2469 r = true;
2471 return r;
2475 /**********************************************************************
2476 * TRANSIENT DESIGNER by Christian Holschuh and Markus Schmidt
2477 **********************************************************************/
2480 transientdesigner_audio_module::transientdesigner_audio_module() {
2481 active = false;
2482 pixels = 0;
2483 pbuffer_pos = 0;
2484 pbuffer_sample = 0;
2485 pbuffer_size = 0;
2486 attcount = 0;
2487 attacked = false;
2488 attack_pos = 0;
2489 display_old = 0;
2490 pbuffer_available = false;
2491 display_max = pow(2,-12);
2492 transients.set_channels(channels);
2493 hp_f_old = hp_m_old = lp_f_old = lp_m_old = 0;
2494 redraw = false;
2496 transientdesigner_audio_module::~transientdesigner_audio_module()
2498 free(pbuffer);
2500 void transientdesigner_audio_module::activate() {
2501 active = true;
2504 void transientdesigner_audio_module::deactivate() {
2505 active = false;
2508 void transientdesigner_audio_module::params_changed() {
2509 if (*params[param_display] != display_old) {
2510 dsp::zero(pbuffer, (int)(pixels * 2));
2511 display_old = *params[param_display];
2513 transients.set_params(*params[param_attack_time],
2514 *params[param_attack_boost],
2515 *params[param_release_time],
2516 *params[param_release_boost],
2517 *params[param_sustain_threshold],
2518 *params[param_lookahead]);
2519 if (hp_f_old != *params[param_hipass]) {
2520 hp[0].set_hp_rbj(*params[param_hipass], 0.707, (float)srate, 1.0);
2521 hp[1].copy_coeffs(hp[0]);
2522 hp[2].copy_coeffs(hp[0]);
2523 redraw = true;
2524 hp_f_old = *params[param_hipass];
2526 if (lp_f_old != *params[param_lopass]) {
2527 lp[0].set_lp_rbj(*params[param_lopass], 0.707, (float)srate, 1.0);
2528 lp[1].copy_coeffs(lp[0]);
2529 lp[2].copy_coeffs(lp[0]);
2530 redraw = true;
2531 lp_f_old = *params[param_lopass];
2533 if (hp_m_old != *params[param_hp_mode]) {
2534 redraw = true;
2535 hp_m_old = *params[param_hp_mode];
2537 if (lp_m_old != *params[param_lp_mode]) {
2538 redraw = true;
2539 lp_m_old = *params[param_lp_mode];
2543 uint32_t transientdesigner_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
2544 uint32_t orig_offset = offset;
2545 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
2546 for(uint32_t i = offset; i < offset + numsamples; i++) {
2547 float L = ins[0][i];
2548 float R = ins[1][i];
2549 meter_inL = 0.f;
2550 meter_inR = 0.f;
2551 meter_outL = 0.f;
2552 meter_outR = 0.f;
2553 float s = (fabs(L) + fabs(R)) / 2;
2554 if(bypassed) {
2555 outs[0][i] = ins[0][i];
2556 outs[1][i] = ins[1][i];
2558 } else {
2559 // levels in
2560 L *= *params[param_level_in];
2561 R *= *params[param_level_in];
2563 // GUI stuff
2564 meter_inL = L;
2565 meter_inR = R;
2567 // transient designer
2568 float s = (L + R) / 2.f;
2569 for (int k = 0; k < *params[param_hp_mode]; k ++)
2570 s = hp[k].process(s);
2571 for (int j = 0; j < *params[param_lp_mode]; j ++)
2572 s = lp[j].process(s);
2574 float values[] = {L, R};
2575 transients.process(values, s);
2577 L = values[0] * *params[param_mix] + L * (*params[param_mix] * -1 + 1);
2578 R = values[1] * *params[param_mix] + R * (*params[param_mix] * -1 + 1);
2580 // levels out
2581 L *= *params[param_level_out];
2582 R *= *params[param_level_out];
2584 // output
2585 if (*params[param_listen] > 0.5) {
2586 outs[0][i] = s;
2587 outs[1][i] = s;
2588 } else {
2589 outs[0][i] = L;
2590 outs[1][i] = R;
2592 meter_outL = L;
2593 meter_outR = R;
2595 // fill pixel buffer (pbuffer)
2597 // the pixel buffer is an array holding all necessary values for
2598 // the line graph per pixel. its length is 5 times the available
2599 // pixel width of the graph multiplied with the maximum zoom
2600 // to hold input, output, attack, release and envelope data.
2602 // here we write the pixel buffer, get_graph will read its
2603 // contents later in a drawing event.
2605 // pbuffer_pos is the actual position in the array we are writing
2606 // to. It points to the first position of a set of the 5 values.
2608 // Since we have more audio samples than pixels we add a couple
2609 // of samples to one pixel before we step forward with pbuffer_pos.
2611 if (pbuffer_available) {
2612 // sanitize the buffer position if enough samples have
2613 // been captured. This is recognized by a negative value
2614 for (int i = 0; i < 5; i++) {
2615 pbuffer[pbuffer_pos + i] = std::max(pbuffer[pbuffer_pos + i], 0.f);
2618 // add samples to the buffer at the actual address
2619 pbuffer[pbuffer_pos] = std::max(s, pbuffer[pbuffer_pos]);
2620 pbuffer[pbuffer_pos + 1] = std::max((float)(fabs(L) + fabs(R)), (float)pbuffer[pbuffer_pos + 1]);
2622 if (bypassed) {
2623 pbuffer[pbuffer_pos + 2] = 0;
2624 pbuffer[pbuffer_pos + 3] = 0;
2625 pbuffer[pbuffer_pos + 4] = 0;
2626 } else {
2627 pbuffer[pbuffer_pos + 2] = transients.envelope;
2628 pbuffer[pbuffer_pos + 3] = transients.attack;
2629 pbuffer[pbuffer_pos + 4] = transients.release;
2632 pbuffer_sample += 1;
2634 if (pbuffer_sample >= (int)(srate * *params[param_display] / 1000.f / pixels)) {
2635 // we captured enough samples for one pixel on this
2636 // address. to keep track of the finalization invert
2637 // its values as a marker to sanitize in the next
2638 // cycle before adding samples again
2639 pbuffer[pbuffer_pos] *= -1.f * *params[param_level_in];
2640 pbuffer[pbuffer_pos + 1] /= -2.f;
2642 // advance the buffer position
2643 pbuffer_pos = (pbuffer_pos + 5) % pbuffer_size;
2645 // reset sample counter
2646 pbuffer_sample = 0;
2650 attcount += 1;
2651 if ( transients.envelope == transients.release
2652 and transients.envelope > *params[param_display_threshold]
2653 and attcount >= srate / 100
2654 and pbuffer_available) {
2655 int diff = (int)(srate / 10 / pixels);
2656 diff += diff & 1;
2657 attack_pos = (pbuffer_pos - diff * 5 + pbuffer_size) % pbuffer_size;
2658 attcount = 0;
2660 float mval[] = {meter_inL, meter_inR, meter_outL, meter_outR};
2661 meters.process(mval);
2663 if (!bypassed)
2664 bypass.crossfade(ins, outs, 2, orig_offset, numsamples);
2665 meters.fall(numsamples);
2666 return outputs_mask;
2669 void transientdesigner_audio_module::set_sample_rate(uint32_t sr)
2671 srate = sr;
2672 attcount = srate / 5;
2673 transients.set_sample_rate(srate);
2674 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
2675 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
2676 meters.init(params, meter, clip, 4, srate);
2678 bool transientdesigner_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
2680 if (index == param_hipass) {
2681 // frequency response
2682 if (subindex) return false;
2683 float ret;
2684 double freq;
2685 for (int i = 0; i < points; i++) {
2686 ret = 1.f;
2687 freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
2688 if(*params[param_hp_mode])
2689 ret *= pow(hp[0].freq_gain(freq, (float)srate), *params[param_hp_mode]);
2690 if(*params[param_lp_mode])
2691 ret *= pow(lp[0].freq_gain(freq, (float)srate), *params[param_lp_mode]);
2692 data[i] = dB_grid(ret);
2694 redraw = false;
2695 return true;
2698 if (subindex >= 2 or (*params[param_bypass] > 0.5f and subindex >= 1))
2699 return false;
2700 if (points <= 0)
2701 return false;
2702 if (points != pixels) {
2703 // the zoom level changed or it's the first time we want to draw
2704 // some graphs
2706 // buffer size is the amount of pixels for the max display value
2707 // if drawn in the min display zoom level multiplied by 5 for
2708 // keeping the input and the output fabs signals and all graphs
2709 // of the envelopes
2710 pbuffer_size = (int)(points * 5 * 100);
2711 // create array
2712 pbuffer = (float*) calloc(pbuffer_size, sizeof(float));
2714 // sanitize some indexes and addresses
2715 pbuffer_pos = 0;
2716 pbuffer_sample = 0;
2717 pbuffer_draw = 0;
2718 pbuffer_available = true;
2719 pixels = points;
2721 // check if threshold is above minimum - we want to see trigger hold
2722 bool hold = *params[param_display_threshold] > display_max;
2723 // set the address to start from in both drawing cycles
2724 // to amount of pixels before pbuffer_pos or to attack_pos
2725 if (subindex == 0) {
2726 int pos = hold ? attack_pos : pbuffer_pos;
2727 pbuffer_draw = hold ? pos : (pbuffer_size + pos - pixels * 5) % pbuffer_size;
2730 int draw_curve = 0;
2731 if (subindex)
2732 draw_curve = subindex + *params[param_view];
2734 if (!draw_curve) {
2735 // input is drawn as bars with less opacity
2736 *mode = 1;
2737 context->set_source_rgba(0.15, 0.2, 0.0, 0.2);
2738 } else {
2739 // output/envelope is a precise line
2740 context->set_line_width(0.75);
2743 // draw curve
2744 for (int i = 0; i <= points; i++) {
2745 int pos = (pbuffer_draw + i * 5) % pbuffer_size + draw_curve;
2746 if (hold
2747 and ((pos > pbuffer_pos and ((pbuffer_pos > attack_pos and pos > attack_pos)
2748 or (pbuffer_pos < attack_pos and pos < attack_pos)))
2749 or (pbuffer_pos > attack_pos and pos < attack_pos))) {
2750 // we are drawing trigger hold stuff outside the hold window
2751 // so we don't want to see old data - zero it out.
2752 data[i] = dB_grid(2.51e-10, 128, 0.6);
2753 } else {
2754 // draw normally
2755 data[i] = dB_grid(fabs(pbuffer[pos]) + 2.51e-10, 128, 0.6);
2758 return true;
2760 bool transientdesigner_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
2762 if (index == param_hipass)
2763 // frequency response
2764 return get_freq_gridline(subindex, pos, vertical, legend, context);
2766 if (subindex >= 16 or phase)
2767 return false;
2768 float gain = 16.f / (1 << subindex);
2769 pos = dB_grid(gain, 128, 0.6);
2770 context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2);
2771 if (!(subindex & 1) and subindex) {
2772 std::stringstream ss;
2773 ss << (24 - 6 * subindex) << " dB";
2774 legend = ss.str();
2776 return true;
2779 bool transientdesigner_audio_module::get_layers(int index, int generation, unsigned int &layers) const
2781 if (index == param_hipass) {
2782 layers = (redraw || !generation ? LG_CACHE_GRAPH : LG_NONE) | (generation ? LG_NONE : LG_CACHE_GRID);
2783 return true;
2785 layers = LG_REALTIME_GRAPH | (generation ? 0 : LG_CACHE_GRID);
2786 return true;