1 /*
2 * ZaMultiComp multiband compressor
3 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16 */
17
18 #include "ZaMultiCompPlugin.hpp"
19
20 START_NAMESPACE_DISTRHO
21
22 // -----------------------------------------------------------------------
23
ZaMultiCompPlugin()24 ZaMultiCompPlugin::ZaMultiCompPlugin()
25 : Plugin(paramCount, 2, 0)
26 {
27 // set default values
28 loadProgram(0);
29 }
30
31 // -----------------------------------------------------------------------
32 // Init
33
initParameter(uint32_t index,Parameter & parameter)34 void ZaMultiCompPlugin::initParameter(uint32_t index, Parameter& parameter)
35 {
36 switch (index)
37 {
38 case paramAttack1:
39 parameter.hints = kParameterIsAutomable;
40 parameter.name = "Attack1";
41 parameter.symbol = "att1";
42 parameter.unit = "ms";
43 parameter.ranges.def = 10.0f;
44 parameter.ranges.min = 0.1f;
45 parameter.ranges.max = 100.0f;
46 break;
47 case paramAttack2:
48 parameter.hints = kParameterIsAutomable;
49 parameter.name = "Attack2";
50 parameter.symbol = "att2";
51 parameter.unit = "ms";
52 parameter.ranges.def = 10.0f;
53 parameter.ranges.min = 0.1f;
54 parameter.ranges.max = 100.0f;
55 break;
56 case paramAttack3:
57 parameter.hints = kParameterIsAutomable;
58 parameter.name = "Attack3";
59 parameter.symbol = "att3";
60 parameter.unit = "ms";
61 parameter.ranges.def = 10.0f;
62 parameter.ranges.min = 0.1f;
63 parameter.ranges.max = 100.0f;
64 break;
65 case paramRelease1:
66 parameter.hints = kParameterIsAutomable;
67 parameter.name = "Release1";
68 parameter.symbol = "rel1";
69 parameter.unit = "ms";
70 parameter.ranges.def = 80.0f;
71 parameter.ranges.min = 1.0f;
72 parameter.ranges.max = 500.0f;
73 break;
74 case paramRelease2:
75 parameter.hints = kParameterIsAutomable;
76 parameter.name = "Release2";
77 parameter.symbol = "rel2";
78 parameter.unit = "ms";
79 parameter.ranges.def = 80.0f;
80 parameter.ranges.min = 1.0f;
81 parameter.ranges.max = 500.0f;
82 break;
83 case paramRelease3:
84 parameter.hints = kParameterIsAutomable;
85 parameter.name = "Release3";
86 parameter.symbol = "rel3";
87 parameter.unit = "ms";
88 parameter.ranges.def = 80.0f;
89 parameter.ranges.min = 1.0f;
90 parameter.ranges.max = 500.0f;
91 break;
92 case paramKnee1:
93 parameter.hints = kParameterIsAutomable;
94 parameter.name = "Knee1";
95 parameter.symbol = "kn1";
96 parameter.unit = "dB";
97 parameter.ranges.def = 0.0f;
98 parameter.ranges.min = 0.0f;
99 parameter.ranges.max = 8.0f;
100 break;
101 case paramKnee2:
102 parameter.hints = kParameterIsAutomable;
103 parameter.name = "Knee2";
104 parameter.symbol = "kn2";
105 parameter.unit = "dB";
106 parameter.ranges.def = 0.0f;
107 parameter.ranges.min = 0.0f;
108 parameter.ranges.max = 8.0f;
109 break;
110 case paramKnee3:
111 parameter.hints = kParameterIsAutomable;
112 parameter.name = "Knee3";
113 parameter.symbol = "kn3";
114 parameter.unit = "dB";
115 parameter.ranges.def = 0.0f;
116 parameter.ranges.min = 0.0f;
117 parameter.ranges.max = 8.0f;
118 break;
119 case paramRatio1:
120 parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic;
121 parameter.name = "Ratio1";
122 parameter.symbol = "rat1";
123 parameter.unit = " ";
124 parameter.ranges.def = 4.0f;
125 parameter.ranges.min = 1.0f;
126 parameter.ranges.max = 20.0f;
127 break;
128 case paramRatio2:
129 parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic;
130 parameter.name = "Ratio2";
131 parameter.symbol = "rat2";
132 parameter.unit = " ";
133 parameter.ranges.def = 4.0f;
134 parameter.ranges.min = 1.0f;
135 parameter.ranges.max = 20.0f;
136 break;
137 case paramRatio3:
138 parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic;
139 parameter.name = "Ratio3";
140 parameter.symbol = "rat3";
141 parameter.unit = " ";
142 parameter.ranges.def = 4.0f;
143 parameter.ranges.min = 1.0f;
144 parameter.ranges.max = 20.0f;
145 break;
146 case paramThresh1:
147 parameter.hints = kParameterIsAutomable;
148 parameter.name = "Threshold 1";
149 parameter.symbol = "thr1";
150 parameter.unit = "dB";
151 parameter.ranges.def = -20.0f;
152 parameter.ranges.min = -60.0f;
153 parameter.ranges.max = 0.0f;
154 break;
155 case paramThresh2:
156 parameter.hints = kParameterIsAutomable;
157 parameter.name = "Threshold 2";
158 parameter.symbol = "thr2";
159 parameter.unit = "dB";
160 parameter.ranges.def = -18.0f;
161 parameter.ranges.min = -60.0f;
162 parameter.ranges.max = 0.0f;
163 break;
164 case paramThresh3:
165 parameter.hints = kParameterIsAutomable;
166 parameter.name = "Threshold 3";
167 parameter.symbol = "thr3";
168 parameter.unit = "dB";
169 parameter.ranges.def = -16.0f;
170 parameter.ranges.min = -60.0f;
171 parameter.ranges.max = 0.0f;
172 break;
173 case paramMakeup1:
174 parameter.hints = kParameterIsAutomable;
175 parameter.name = "Makeup 1";
176 parameter.symbol = "mak1";
177 parameter.unit = "dB";
178 parameter.ranges.def = 0.0f;
179 parameter.ranges.min = 0.0f;
180 parameter.ranges.max = 30.0f;
181 break;
182 case paramMakeup2:
183 parameter.hints = kParameterIsAutomable;
184 parameter.name = "Makeup 2";
185 parameter.symbol = "mak2";
186 parameter.unit = "dB";
187 parameter.ranges.def = 0.0f;
188 parameter.ranges.min = 0.0f;
189 parameter.ranges.max = 30.0f;
190 break;
191 case paramMakeup3:
192 parameter.hints = kParameterIsAutomable;
193 parameter.name = "Makeup 3";
194 parameter.symbol = "mak3";
195 parameter.unit = "dB";
196 parameter.ranges.def = 0.0f;
197 parameter.ranges.min = 0.0f;
198 parameter.ranges.max = 30.0f;
199 break;
200 case paramGainR1:
201 parameter.hints = kParameterIsAutomable | kParameterIsOutput;
202 parameter.name = "Gain Reduction 1";
203 parameter.symbol = "gr1";
204 parameter.unit = "dB";
205 parameter.ranges.def = 0.0f;
206 parameter.ranges.min = 0.0f;
207 parameter.ranges.max = 20.0f;
208 break;
209 case paramGainR2:
210 parameter.hints = kParameterIsAutomable | kParameterIsOutput;
211 parameter.name = "Gain Reduction 2";
212 parameter.symbol = "gr2";
213 parameter.unit = "dB";
214 parameter.ranges.def = 0.0f;
215 parameter.ranges.min = 0.0f;
216 parameter.ranges.max = 20.0f;
217 break;
218 case paramGainR3:
219 parameter.hints = kParameterIsAutomable | kParameterIsOutput;
220 parameter.name = "Gain Reduction 3";
221 parameter.symbol = "gr3";
222 parameter.unit = "dB";
223 parameter.ranges.def = 0.0f;
224 parameter.ranges.min = 0.0f;
225 parameter.ranges.max = 20.0f;
226 break;
227 case paramXover1:
228 parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic;
229 parameter.name = "Crossover freq 1";
230 parameter.symbol = "xover1";
231 parameter.unit = "Hz";
232 parameter.ranges.def = 160.0f;
233 parameter.ranges.min = 20.0f;
234 parameter.ranges.max = 1400.0f;
235 break;
236 case paramXover2:
237 parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic;
238 parameter.name = "Crossover freq 2";
239 parameter.symbol = "xover2";
240 parameter.unit = "Hz";
241 parameter.ranges.def = 1400.0f;
242 parameter.ranges.min = 1400.0f;
243 parameter.ranges.max = 14000.0f;
244 break;
245 case paramToggle1:
246 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
247 parameter.name = "ZamComp 1 ON";
248 parameter.symbol = "toggle1";
249 parameter.unit = " ";
250 parameter.ranges.def = 0.0f;
251 parameter.ranges.min = 0.0f;
252 parameter.ranges.max = 1.0f;
253 break;
254 case paramToggle2:
255 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
256 parameter.name = "ZamComp 2 ON";
257 parameter.symbol = "toggle2";
258 parameter.unit = " ";
259 parameter.ranges.def = 0.0f;
260 parameter.ranges.min = 0.0f;
261 parameter.ranges.max = 1.0f;
262 break;
263 case paramToggle3:
264 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
265 parameter.name = "ZamComp 3 ON";
266 parameter.symbol = "toggle3";
267 parameter.unit = " ";
268 parameter.ranges.def = 0.0f;
269 parameter.ranges.min = 0.0f;
270 parameter.ranges.max = 1.0f;
271 break;
272 case paramListen1:
273 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
274 parameter.name = "Listen 1";
275 parameter.symbol = "listen1";
276 parameter.unit = " ";
277 parameter.ranges.def = 0.0f;
278 parameter.ranges.min = 0.0f;
279 parameter.ranges.max = 1.0f;
280 break;
281 case paramListen2:
282 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
283 parameter.name = "Listen 2";
284 parameter.symbol = "listen2";
285 parameter.unit = " ";
286 parameter.ranges.def = 0.0f;
287 parameter.ranges.min = 0.0f;
288 parameter.ranges.max = 1.0f;
289 break;
290 case paramListen3:
291 parameter.hints = kParameterIsAutomable | kParameterIsBoolean;
292 parameter.name = "Listen 3";
293 parameter.symbol = "listen3";
294 parameter.unit = " ";
295 parameter.ranges.def = 0.0f;
296 parameter.ranges.min = 0.0f;
297 parameter.ranges.max = 1.0f;
298 break;
299 case paramGlobalGain:
300 parameter.hints = kParameterIsAutomable;
301 parameter.name = "Master Trim";
302 parameter.symbol = "globalgain";
303 parameter.unit = "dB";
304 parameter.ranges.def = 0.0f;
305 parameter.ranges.min = -12.0f;
306 parameter.ranges.max = 12.0f;
307 break;
308 case paramOutputLevel:
309 parameter.hints = kParameterIsOutput;
310 parameter.name = "Output";
311 parameter.symbol = "out";
312 parameter.unit = "dB";
313 parameter.ranges.def = -45.0f;
314 parameter.ranges.min = -45.0f;
315 parameter.ranges.max = 20.0f;
316 break;
317 case paramOutputLevelLow:
318 parameter.hints = kParameterIsOutput;
319 parameter.name = "Output low";
320 parameter.symbol = "outlo";
321 parameter.unit = "dB";
322 parameter.ranges.def = -45.0f;
323 parameter.ranges.min = -45.0f;
324 parameter.ranges.max = 20.0f;
325 break;
326 case paramOutputLevelMed:
327 parameter.hints = kParameterIsOutput;
328 parameter.name = "Output medium";
329 parameter.symbol = "outmed";
330 parameter.unit = "dB";
331 parameter.ranges.def = -45.0f;
332 parameter.ranges.min = -45.0f;
333 parameter.ranges.max = 20.0f;
334 break;
335 case paramOutputLevelHigh:
336 parameter.hints = kParameterIsOutput;
337 parameter.name = "Output high";
338 parameter.symbol = "outhi";
339 parameter.unit = "dB";
340 parameter.ranges.def = -45.0f;
341 parameter.ranges.min = -45.0f;
342 parameter.ranges.max = 20.0f;
343 break;
344 }
345 }
346
initProgramName(uint32_t index,String & programName)347 void ZaMultiCompPlugin::initProgramName(uint32_t index, String& programName)
348 {
349 switch(index) {
350 case 0:
351 programName = "Zero";
352 break;
353 case 1:
354 programName = "Presence";
355 break;
356 }
357 }
358
loadProgram(uint32_t index)359 void ZaMultiCompPlugin::loadProgram(uint32_t index)
360 {
361 switch(index) {
362 case 0:
363 attack[0] = 10.0;
364 attack[1] = 10.0;
365 attack[2] = 10.0;
366 release[0] = 80.0;
367 release[1] = 80.0;
368 release[2] = 80.0;
369 knee[0] = 0.0;
370 knee[1] = 0.0;
371 knee[2] = 0.0;
372 ratio[0] = 4.0;
373 ratio[1] = 4.0;
374 ratio[2] = 4.0;
375 thresdb[0] = -20.0;
376 thresdb[1] = -18.0;
377 thresdb[2] = -16.0;
378 makeup[0] = 0.0;
379 makeup[1] = 0.0;
380 makeup[2] = 0.0;
381 xover1 = 160.0;
382 xover2 = 1400.0;
383 gainr[0] = 0.0;
384 gainr[1] = 0.0;
385 gainr[2] = 0.0;
386 toggle[0] = 0.0;
387 toggle[1] = 0.0;
388 toggle[2] = 0.0;
389 listen[0] = 0.0;
390 listen[1] = 0.0;
391 listen[2] = 0.0;
392 globalgain = 0.0;
393 out = -45.0;
394 outlevel[0] = -45;
395 outlevel[1] = -45;
396 outlevel[2] = -45;
397 break;
398 case 1:
399 attack[0] = 10.0;
400 attack[1] = 10.0;
401 attack[2] = 10.0;
402 release[0] = 200.0;
403 release[1] = 200.0;
404 release[2] = 200.0;
405 knee[0] = 3.0;
406 knee[1] = 3.0;
407 knee[2] = 3.0;
408 ratio[0] = 5.0;
409 ratio[1] = 5.0;
410 ratio[2] = 5.0;
411 thresdb[0] = -20.0;
412 thresdb[1] = -18.0;
413 thresdb[2] = -16.0;
414 makeup[0] = 9.0;
415 makeup[1] = 6.0;
416 makeup[2] = 6.0;
417 xover1 = 160.0;
418 xover2 = 1400.0;
419 gainr[0] = 0.0;
420 gainr[1] = 0.0;
421 gainr[2] = 0.0;
422 toggle[0] = 1.0;
423 toggle[1] = 1.0;
424 toggle[2] = 1.0;
425 listen[0] = 0.0;
426 listen[1] = 0.0;
427 listen[2] = 0.0;
428 globalgain = 0.0;
429 out = -45.0;
430 outlevel[0] = -45.0;
431 outlevel[1] = -45.0;
432 outlevel[2] = -45.0;
433 break;
434 }
435 /* Default variable values */
436 max = 0.f;
437 limit = 0.f;
438
439 /* reset filter values */
440 activate();
441 }
442
443 // -----------------------------------------------------------------------
444 // Internal data
445
getParameterValue(uint32_t index) const446 float ZaMultiCompPlugin::getParameterValue(uint32_t index) const
447 {
448 switch (index)
449 {
450 case paramAttack1:
451 return attack[0];
452 break;
453 case paramAttack2:
454 return attack[1];
455 break;
456 case paramAttack3:
457 return attack[2];
458 break;
459 case paramRelease1:
460 return release[0];
461 break;
462 case paramRelease2:
463 return release[1];
464 break;
465 case paramRelease3:
466 return release[2];
467 break;
468 case paramKnee1:
469 return knee[0];
470 break;
471 case paramKnee2:
472 return knee[1];
473 break;
474 case paramKnee3:
475 return knee[2];
476 break;
477 case paramRatio1:
478 return ratio[0];
479 break;
480 case paramRatio2:
481 return ratio[1];
482 break;
483 case paramRatio3:
484 return ratio[2];
485 break;
486 case paramThresh1:
487 return thresdb[0];
488 break;
489 case paramThresh2:
490 return thresdb[1];
491 break;
492 case paramThresh3:
493 return thresdb[2];
494 break;
495 case paramMakeup1:
496 return makeup[0];
497 break;
498 case paramMakeup2:
499 return makeup[1];
500 break;
501 case paramMakeup3:
502 return makeup[2];
503 break;
504 case paramGainR1:
505 return gainr[0];
506 break;
507 case paramGainR2:
508 return gainr[1];
509 break;
510 case paramGainR3:
511 return gainr[2];
512 break;
513 case paramXover1:
514 return xover1;
515 break;
516 case paramXover2:
517 return xover2;
518 break;
519 case paramToggle1:
520 return toggle[0];
521 break;
522 case paramToggle2:
523 return toggle[1];
524 break;
525 case paramToggle3:
526 return toggle[2];
527 break;
528 case paramListen1:
529 return listen[0];
530 break;
531 case paramListen2:
532 return listen[1];
533 break;
534 case paramListen3:
535 return listen[2];
536 break;
537 case paramGlobalGain:
538 return globalgain;
539 break;
540 case paramOutputLevel:
541 return out;
542 break;
543 case paramOutputLevelLow:
544 return outlevel[0];
545 break;
546 case paramOutputLevelMed:
547 return outlevel[1];
548 break;
549 case paramOutputLevelHigh:
550 return outlevel[2];
551 break;
552 default:
553 return 0.0f;
554 }
555 }
556
setParameterValue(uint32_t index,float value)557 void ZaMultiCompPlugin::setParameterValue(uint32_t index, float value)
558 {
559 switch (index)
560 {
561 case paramAttack1:
562 attack[0] = value;
563 break;
564 case paramAttack2:
565 attack[1] = value;
566 break;
567 case paramAttack3:
568 attack[2] = value;
569 break;
570 case paramRelease1:
571 release[0] = value;
572 break;
573 case paramRelease2:
574 release[1] = value;
575 break;
576 case paramRelease3:
577 release[2] = value;
578 break;
579 case paramKnee1:
580 knee[0] = value;
581 break;
582 case paramKnee2:
583 knee[1] = value;
584 break;
585 case paramKnee3:
586 knee[2] = value;
587 break;
588 case paramRatio1:
589 ratio[0] = value;
590 break;
591 case paramRatio2:
592 ratio[1] = value;
593 break;
594 case paramRatio3:
595 ratio[2] = value;
596 break;
597 case paramThresh1:
598 thresdb[0] = value;
599 break;
600 case paramThresh2:
601 thresdb[1] = value;
602 break;
603 case paramThresh3:
604 thresdb[2] = value;
605 break;
606 case paramMakeup1:
607 makeup[0] = value;
608 break;
609 case paramMakeup2:
610 makeup[1] = value;
611 break;
612 case paramMakeup3:
613 makeup[2] = value;
614 break;
615 case paramGainR1:
616 gainr[0] = value;
617 break;
618 case paramGainR2:
619 gainr[1] = value;
620 break;
621 case paramGainR3:
622 gainr[2] = value;
623 break;
624 case paramXover1:
625 xover1 = value;
626 break;
627 case paramXover2:
628 xover2 = value;
629 break;
630 case paramToggle1:
631 toggle[0] = value;
632 if (value == 0.f)
633 gainr[0] = 0.f;
634 break;
635 case paramToggle2:
636 toggle[1] = value;
637 if (value == 0.f)
638 gainr[1] = 0.f;
639 break;
640 case paramToggle3:
641 toggle[2] = value;
642 if (value == 0.f)
643 gainr[2] = 0.f;
644 break;
645 case paramListen1:
646 listen[0] = value;
647 if (value == 0.f)
648 gainr[0] = 0.f;
649 break;
650 case paramListen2:
651 listen[1] = value;
652 if (value == 0.f)
653 gainr[1] = 0.f;
654 break;
655 case paramListen3:
656 listen[2] = value;
657 if (value == 0.f)
658 gainr[2] = 0.f;
659 break;
660 case paramGlobalGain:
661 globalgain = value;
662 break;
663 case paramOutputLevel:
664 out = value;
665 break;
666 case paramOutputLevelLow:
667 outlevel[0] = value;
668 break;
669 case paramOutputLevelMed:
670 outlevel[1] = value;
671 break;
672 case paramOutputLevelHigh:
673 outlevel[2] = value;
674 break;
675 }
676 }
677
getState(const char *) const678 String ZaMultiCompPlugin::getState(const char*) const
679 {
680 return String();
681 }
682
setState(const char *,const char *)683 void ZaMultiCompPlugin::setState(const char*, const char*)
684 {
685 reset = true;
686 }
687
initState(unsigned int,String &,String &)688 void ZaMultiCompPlugin::initState(unsigned int, String&, String&)
689 {
690 }
691
692 // -----------------------------------------------------------------------
693 // Process
694
activate()695 void ZaMultiCompPlugin::activate()
696 {
697 int i;
698 for (i = 0; i < MAX_COMP; i++)
699 old_yl[i]=old_y1[i]=old_yg[i]=0.f;
700
701 old_ll=old_l1=0.f;
702
703 for (i = 0; i < MAX_FILT; i++) {
704 simper[0][i].k = 0.f;
705 simper[0][i].g = 0.f;
706 simper[0][i].s[0] = 0.f;
707 simper[0][i].s[1] = 0.f;
708
709 simper[1][i].k = 0.f;
710 simper[1][i].g = 0.f;
711 simper[1][i].s[0] = 0.f;
712 simper[1][i].s[1] = 0.f;
713 }
714 max = 0.f;
715 pos[0] = 0;
716 pos[1] = 0;
717 pos[2] = 0;
718
719 oldxover1 = 0.f;
720 oldxover2 = 0.f;
721 }
722
723 /*
724 * A. Simper's filters
725 * https://cytomic.com/files/dsp/SvfInputMixing.pdf
726 */
727
linear_svf_set_xover(struct linear_svf * self,float sample_rate,float cutoff,float resonance)728 void ZaMultiCompPlugin::linear_svf_set_xover(struct linear_svf *self, float sample_rate, float cutoff, float resonance)
729 {
730 double w;
731
732 self->k = 2. - 2. * resonance;
733 w = M_PI * cutoff / sample_rate;
734 self->g = tan(w);
735
736 }
737
linear_svf_reset(struct linear_svf * self)738 void ZaMultiCompPlugin::linear_svf_reset(struct linear_svf *self)
739 {
740 self->s[0] = self->s[1] = 0.f;
741 }
742
run_linear_svf_xover(struct linear_svf * self,float in,float mixlow,float mixhigh)743 float ZaMultiCompPlugin::run_linear_svf_xover(struct linear_svf *self, float in, float mixlow, float mixhigh)
744 {
745 double v[3];
746 double g = self->g;
747 double k = self->k;
748 double s0 = self->s[0];
749 double s1 = self->s[1];
750 double g2 = g*g;
751 double vhigh = in * mixhigh;
752 double vband = in * 0.75;
753 double vlow = in * mixlow;
754
755 v[0] = in;
756 v[1] = -1. / (1. + g2 + g*k) * (-s0 + g*s1 - g*k*s0 + g2*vband + g*vhigh - g*vlow - g2*k*vlow);
757 v[2] = -1. / (1. + g2 + g*k) * (-g*s0 - s1 - g*vband + g2*vhigh + g*k*vhigh - g2*vlow);
758 self->s[0] = 2. * v[1] - s0;
759 self->s[1] = 2. * v[2] - s1;
760
761 return (float)(vhigh + v[2]);
762 }
763
calc_lr4(float f,int i)764 void ZaMultiCompPlugin::calc_lr4(float f, int i)
765 {
766 float srate = getSampleRate();
767
768 linear_svf_set_xover(&simper[0][i], srate, f, 0.25);
769 linear_svf_set_xover(&simper[1][i], srate, f, 0.25);
770 }
771
run_lr4(int i,float in,float * outlo,float * outhi)772 void ZaMultiCompPlugin::run_lr4(int i, float in, float *outlo, float *outhi)
773 {
774 *outlo = run_linear_svf_xover(&simper[0][i], in, 1., 0.);
775 *outhi = run_linear_svf_xover(&simper[1][i], in, 0., 1.);
776 }
777
run_comp(int k,float in,float * out)778 void ZaMultiCompPlugin::run_comp(int k, float in, float *out)
779 {
780 float srate = getSampleRate();
781 float width = (6.f * knee[k]) + 0.01;
782 float attack_coeff = exp(-1000.f/(attack[k] * srate));
783 float release_coeff = exp(-1000.f/(release[k] * srate));
784
785 float checkwidth = 0.f;
786 float cdb=0.f;
787 float Lgain = 1.f;
788 float Lxg, Lyg;
789 float Lxl, Lyl;
790
791 Lyg = 0.f;
792 in = sanitize_denormal(in);
793 Lxg = (in==0.f) ? -160.f : to_dB(fabsf(in));
794 Lxg = sanitize_denormal(Lxg);
795
796 checkwidth = 2.f*fabsf(Lxg-thresdb[k]);
797 if (2.f*(Lxg-thresdb[k]) < -width) {
798 Lyg = Lxg;
799 } else if (checkwidth <= width) {
800 Lyg = Lxg + (1.f/ratio[k]-1.f)*(Lxg-thresdb[k]+width/2.f)*(Lxg-thresdb[k]+width/2.f)/(2.f*width);
801 Lyg = sanitize_denormal(Lyg);
802 } else if (2.f*(Lxg-thresdb[k]) > width) {
803 Lyg = thresdb[k] + (Lxg-thresdb[k])/ratio[k];
804 Lyg = sanitize_denormal(Lyg);
805 }
806
807 Lxl = Lxg - Lyg;
808
809 old_yl[k] = sanitize_denormal(old_yl[k]);
810
811 if (Lxl < old_yl[k]) {
812 Lyl = release_coeff * old_yl[k] + (1.f-release_coeff)*Lxl;
813 } else if (Lxl > old_yl[k]) {
814 Lyl = attack_coeff * old_yl[k]+(1.f-attack_coeff)*Lxl;
815 } else {
816 Lyl = Lxl;
817 }
818 Lyl = sanitize_denormal(Lyl);
819
820 cdb = -Lyl;
821 Lgain = from_dB(cdb);
822
823 gainr[k] = Lyl;
824
825 *out = in * Lgain;
826
827 old_yl[k] = Lyl;
828 old_yg[k] = Lyg;
829 }
830
pushsample(float sample,int k)831 void ZaMultiCompPlugin::pushsample(float sample, int k)
832 {
833 const float rate = 2. * M_PI * 5.;
834 float lpf = rate / (rate + getSampleRate());
835
836 average[k] += lpf * (sample*sample - average[k]);
837 }
838
run(const float ** inputs,float ** outputs,uint32_t frames)839 void ZaMultiCompPlugin::run(const float** inputs, float** outputs, uint32_t frames)
840 {
841 float maxx = max;
842
843 int tog1 = (toggle[0] > 0.5f) ? 1 : 0;
844 int tog2 = (toggle[1] > 0.5f) ? 1 : 0;
845 int tog3 = (toggle[2] > 0.5f) ? 1 : 0;
846
847 int listen1 = (listen[0] > 0.5f) ? 1 : 0;
848 int listen2 = (listen[1] > 0.5f) ? 1 : 0;
849 int listen3 = (listen[2] > 0.5f) ? 1 : 0;
850
851 if (oldxover1 != xover1) {
852 // recalculate coeffs
853 calc_lr4(xover1, 0);
854 oldxover1 = xover1;
855 }
856 if (oldxover2 != xover2) {
857 // recalculate coeffs
858 calc_lr4(xover2, 1);
859 oldxover2 = xover2;
860 }
861
862 for (uint32_t i = 0; i < frames; ++i) {
863 float tmp1[2], tmp2[2], tmp3[2];
864 float fil1[2], fil2[2], fil3[2], fil4[2];
865 float outL[MAX_COMP+1] = {0.f};
866 float inl = sanitize_denormal(inputs[0][i]);
867 inl = (fabsf(inl) < DANGER) ? inl : 0.f;
868
869 int listenmode = 0;
870
871 // Interleaved channel processing
872 run_lr4(0, inl, &fil1[0], &fil2[0]);
873 run_lr4(1, fil2[0], &fil3[0], &fil4[0]);
874
875 pushsample(fil1[0], 0);
876 outlevel[0] = sqrt(average[0]);
877 outlevel[0] = (outlevel[0] == 0.f) ? -45.0 : to_dB(outlevel[0]);
878 if (tog1)
879 run_comp(0, fil1[0], &outL[0]);
880
881 tmp1[0] = tog1 ? outL[0] * from_dB(makeup[0]) : fil1[0];
882
883 pushsample(fil3[0], 1);
884 outlevel[1] = sqrt(average[1]);
885 outlevel[1] = (outlevel[1] == 0.f) ? -45.0 : to_dB(outlevel[1]);
886 if (tog2)
887 run_comp(1, fil3[0], &outL[1]);
888
889 tmp2[0] = tog2 ? outL[1] * from_dB(makeup[1]) : fil3[0];
890
891 pushsample(fil4[0], 2);
892 outlevel[2] = sqrt(average[2]);
893 outlevel[2] = (outlevel[2] == 0.f) ? -45.0 : to_dB(outlevel[2]);
894 if (tog3)
895 run_comp(2, fil4[0], &outL[2]);
896
897 tmp3[0] = tog3 ? outL[2] * from_dB(makeup[2]) : fil4[0];
898
899 outputs[0][i] = 0.f;
900 if (listen1) {
901 listenmode = 1;
902 outputs[0][i] += outL[0] * tog1*from_dB(makeup[0])
903 + (1.-tog1) * tmp1[0];
904 }
905 if (listen2) {
906 listenmode = 1;
907 outputs[0][i] += outL[1] * tog2*from_dB(makeup[1])
908 + (1.-tog2) * tmp2[0];
909 }
910 if (listen3) {
911 listenmode = 1;
912 outputs[0][i] += outL[2] * tog3*from_dB(makeup[2])
913 + (1.-tog3) * tmp3[0];
914 }
915 if (!listenmode) {
916 outputs[0][i] = tmp1[0] + tmp2[0] + tmp3[0];
917 }
918 outputs[0][i] = sanitize_denormal(outputs[0][i]);
919 outputs[0][i] *= from_dB(globalgain);
920
921 if (reset) {
922 max = fabsf(outputs[0][i]);
923 reset = false;
924 } else {
925 maxx = (fabsf(outputs[0][i]) > maxx) ? fabsf(outputs[0][i]) : sanitize_denormal(maxx);
926 }
927 }
928 out = (maxx <= 0.f) ? -160.f : to_dB(maxx);
929 }
930
931 // -----------------------------------------------------------------------
932
createPlugin()933 Plugin* createPlugin()
934 {
935 return new ZaMultiCompPlugin();
936 }
937
938 // -----------------------------------------------------------------------
939
940 END_NAMESPACE_DISTRHO
941