Entry/spinbutton fixed
[calf.git] / src / modules_dsp.cpp
blobd7afa93dea2204ea458db01277788c1cecb723a0
1 /* Calf DSP Library
2 * Example audio modules - DSP code
4 * Copyright (C) 2001-2008 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <assert.h>
23 #include <limits.h>
24 #include <memory.h>
25 #if USE_JACK
26 #include <jack/jack.h>
27 #endif
28 #include <calf/giface.h>
29 #include <calf/modules.h>
30 #include <calf/modules_dev.h>
32 using namespace dsp;
33 using namespace calf_plugins;
35 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37 bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
39 return get_freq_gridline(subindex, pos, vertical, legend, context);
42 int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
44 subindex_graph = 0;
45 subindex_dot = 0;
46 subindex_gridline = generation ? INT_MAX : 0;
47 return 1;
50 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52 void flanger_audio_module::activate() {
53 left.reset();
54 right.reset();
55 last_r_phase = *params[par_stereo] * (1.f / 360.f);
56 left.reset_phase(0.f);
57 right.reset_phase(last_r_phase);
58 is_active = true;
61 void flanger_audio_module::set_sample_rate(uint32_t sr) {
62 srate = sr;
63 left.setup(sr);
64 right.setup(sr);
67 void flanger_audio_module::deactivate() {
68 is_active = false;
71 bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
73 if (!is_active)
74 return false;
75 if (index == par_delay && subindex < 2)
77 set_channel_color(context, subindex);
78 return ::get_graph(*this, subindex, data, points);
80 return false;
83 float flanger_audio_module::freq_gain(int subindex, float freq, float srate)
85 return (subindex ? right : left).freq_gain(freq, srate);
88 ///////////////////////////////////////////////////////////////////////////////////////////////
90 void phaser_audio_module::set_sample_rate(uint32_t sr)
92 srate = sr;
93 left.setup(sr);
94 right.setup(sr);
97 void phaser_audio_module::activate()
99 is_active = true;
100 left.reset();
101 right.reset();
102 last_r_phase = *params[par_stereo] * (1.f / 360.f);
103 left.reset_phase(0.f);
104 right.reset_phase(last_r_phase);
107 void phaser_audio_module::deactivate()
109 is_active = false;
112 bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
114 if (!is_active)
115 return false;
116 if (subindex < 2)
118 set_channel_color(context, subindex);
119 return ::get_graph(*this, subindex, data, points);
121 return false;
124 float phaser_audio_module::freq_gain(int subindex, float freq, float srate)
126 return (subindex ? right : left).freq_gain(freq, srate);
129 bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
131 return get_freq_gridline(subindex, pos, vertical, legend, context);
134 ///////////////////////////////////////////////////////////////////////////////////////////////
136 void reverb_audio_module::activate()
138 reverb.reset();
141 void reverb_audio_module::deactivate()
145 void reverb_audio_module::set_sample_rate(uint32_t sr)
147 srate = sr;
148 reverb.setup(sr);
149 amount.set_sample_rate(sr);
152 ///////////////////////////////////////////////////////////////////////////////////////////////
154 bool filter_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
156 if (!is_active)
157 return false;
158 if (index == par_cutoff && !subindex) {
159 context->set_line_width(1.5);
160 return ::get_graph(*this, subindex, data, points);
162 return false;
165 int filter_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
167 if (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
169 old_cutoff = inertia_cutoff.get_last();
170 old_resonance = inertia_resonance.get_last();
171 old_mode = *params[par_mode];
172 last_generation++;
173 subindex_graph = 0;
174 subindex_dot = INT_MAX;
175 subindex_gridline = INT_MAX;
177 else {
178 subindex_graph = 0;
179 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
181 if (generation == last_calculated_generation)
182 subindex_graph = INT_MAX;
183 return last_generation;
187 ///////////////////////////////////////////////////////////////////////////////////////////////
189 bool filterclavier_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
191 if (!is_active || index != par_mode) {
192 return false;
194 if (!subindex) {
195 context->set_line_width(1.5);
196 return ::get_graph(*this, subindex, data, points);
198 return false;
201 ///////////////////////////////////////////////////////////////////////////////////////////////
203 rotary_speaker_audio_module::rotary_speaker_audio_module()
205 mwhl_value = hold_value = 0.f;
206 phase_h = phase_l = 0.f;
207 aspeed_l = 1.f;
208 aspeed_h = 1.f;
209 dspeed = 0.f;
212 void rotary_speaker_audio_module::set_sample_rate(uint32_t sr)
214 srate = sr;
215 setup();
218 void rotary_speaker_audio_module::setup()
220 crossover1l.set_lp_rbj(800.f, 0.7, (float)srate);
221 crossover1r.set_lp_rbj(800.f, 0.7, (float)srate);
222 crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
223 crossover2r.set_hp_rbj(800.f, 0.7, (float)srate);
226 void rotary_speaker_audio_module::activate()
228 phase_h = phase_l = 0.f;
229 maspeed_h = maspeed_l = 0.f;
230 setup();
233 void rotary_speaker_audio_module::deactivate()
237 void rotary_speaker_audio_module::control_change(int ctl, int val)
239 if (vibrato_mode == 3 && ctl == 64)
241 hold_value = val / 127.f;
242 set_vibrato();
243 return;
245 if (vibrato_mode == 4 && ctl == 1)
247 mwhl_value = val / 127.f;
248 set_vibrato();
249 return;
253 ///////////////////////////////////////////////////////////////////////////////////////////////
255 void multichorus_audio_module::activate()
257 is_active = true;
258 params_changed();
261 void multichorus_audio_module::deactivate()
263 is_active = false;
266 void multichorus_audio_module::set_sample_rate(uint32_t sr) {
267 srate = sr;
268 left.setup(sr);
269 right.setup(sr);
272 bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
274 if (!is_active)
275 return false;
276 int nvoices = (int)*params[par_voices];
277 if (index == par_delay && subindex < 3)
279 if (subindex < 2)
280 set_channel_color(context, subindex);
281 else {
282 context->set_source_rgba(0.35, 0.4, 0.2);
283 context->set_line_width(1.0);
285 return ::get_graph(*this, subindex, data, points);
287 if (index == par_rate && subindex < nvoices) {
288 sine_multi_lfo<float, 8> &lfo = left.lfo;
289 for (int i = 0; i < points; i++) {
290 float phase = i * 2 * M_PI / points;
291 // original -65536 to 65535 value
292 float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536;
293 // scale to -1..1
294 data[i] = orig / 65536.0;
296 return true;
298 return false;
301 bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
303 int voice = subindex >> 1;
304 int nvoices = (int)*params[par_voices];
305 if ((index != par_rate && index != par_depth) || voice >= nvoices)
306 return false;
308 float unit = (1 - *params[par_overlap]);
309 float scw = 1 + unit * (nvoices - 1);
310 set_channel_color(context, subindex);
311 sine_multi_lfo<float, 8> &lfo = (subindex & 1 ? right : left).lfo;
312 if (index == par_rate)
314 x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
315 y = 0.95 * sin(x * 2 * M_PI);
316 y = (voice * unit + (y + 1) / 2) / scw * 2 - 1;
318 else
320 double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
321 x = 0.5 + 0.5 * sin(ph * 2 * M_PI);
322 y = subindex & 1 ? -0.75 : 0.75;
323 x = (voice * unit + x) / scw;
325 return true;
328 bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
330 if (index == par_rate && !subindex)
332 pos = 0;
333 vertical = false;
334 return true;
336 if (index == par_delay)
337 return get_freq_gridline(subindex, pos, vertical, legend, context);
338 return false;
341 float multichorus_audio_module::freq_gain(int subindex, float freq, float srate)
343 if (subindex == 2)
344 return *params[par_amount] * left.post.freq_gain(freq, srate);
345 return (subindex ? right : left).freq_gain(freq, srate);
348 /// Multibandcompressor by Markus Schmidt
350 /// This module splits the signal in four different bands
351 /// and sends them through multiple filters (implemented by
352 /// Krzysztof). They are processed by a compressing routine
353 /// (implemented by Thor) afterwards and summed up to the
354 /// final output again.
355 ///////////////////////////////////////////////////////////////////////////////////////////////
357 multibandcompressor_audio_module::multibandcompressor_audio_module()
359 is_active = false;
360 srate = 0;
361 // zero all displays
362 clip_inL = 0.f;
363 clip_inR = 0.f;
364 clip_outL = 0.f;
365 clip_outR = 0.f;
366 meter_inL = 0.f;
367 meter_inR = 0.f;
368 meter_outL = 0.f;
369 meter_outR = 0.f;
372 void multibandcompressor_audio_module::activate()
374 is_active = true;
375 // set all filters and strips
376 params_changed();
377 // activate all strips
378 for (int j = 0; j < strips; j ++) {
379 strip[j].activate();
380 strip[j].id = j;
384 void multibandcompressor_audio_module::deactivate()
386 is_active = false;
387 // deactivate all strips
388 for (int j = 0; j < strips; j ++) {
389 strip[j].deactivate();
393 void multibandcompressor_audio_module::params_changed()
395 // set the params of all filters
396 if(*params[param_freq0] != freq_old[0] or *params[param_sep0] != sep_old[0] or *params[param_q0] != q_old[0]) {
397 lpL0.set_lp_rbj((float)(*params[param_freq0] * (1 - *params[param_sep0])), *params[param_q0], (float)srate);
398 lpR0.copy_coeffs(lpL0);
399 hpL0.set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate);
400 hpR0.copy_coeffs(hpL0);
401 freq_old[0] = *params[param_freq0];
402 sep_old[0] = *params[param_sep2];
403 q_old[0] = *params[param_q2];
405 if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1]) {
406 lpL1.set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate);
407 lpR1.copy_coeffs(lpL1);
408 hpL1.set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate);
409 hpR1.copy_coeffs(hpL1);
410 freq_old[1] = *params[param_freq1];
411 sep_old[1] = *params[param_sep2];
412 q_old[1] = *params[param_q2];
414 if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2]) {
415 lpL2.set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate);
416 lpR2.copy_coeffs(lpL2);
417 hpL2.set_hp_rbj((float)(*params[param_freq2] * (1 + *params[param_sep2])), *params[param_q2], (float)srate);
418 hpR2.copy_coeffs(hpL2);
419 freq_old[2] = *params[param_freq2];
420 sep_old[2] = *params[param_sep2];
421 q_old[2] = *params[param_q2];
423 // set the params of all strips
424 for (int j = 0; j < strips; j ++) {
425 switch (j) {
426 case 0:
427 strip[j].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], *params[param_mute0]);
428 break;
429 case 1:
430 strip[j].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], *params[param_mute1]);
431 break;
432 case 2:
433 strip[j].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], *params[param_mute2]);
434 break;
435 case 3:
436 strip[j].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], *params[param_mute3]);
437 break;
442 void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
444 srate = sr;
445 // set srate of all strips
446 for (int j = 0; j < strips; j ++) {
447 strip[j].set_sample_rate(srate);
451 uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
453 bool bypass = *params[param_bypass] > 0.5f;
454 numsamples += offset;
455 if(bypass) {
456 // everything bypassed
457 while(offset < numsamples) {
458 outs[0][offset] = ins[0][offset];
459 outs[1][offset] = ins[1][offset];
460 ++offset;
462 // displays, too
463 clip_inL = 0.f;
464 clip_inR = 0.f;
465 clip_outL = 0.f;
466 clip_outR = 0.f;
467 meter_inL = 0.f;
468 meter_inR = 0.f;
469 meter_outL = 0.f;
470 meter_outR = 0.f;
471 } else {
472 // process all strips
474 // determine mute state of strips
475 mute[0] = *params[param_mute0] > 0.f ? true : false;
476 mute[1] = *params[param_mute1] > 0.f ? true : false;
477 mute[2] = *params[param_mute2] > 0.f ? true : false;
478 mute[3] = *params[param_mute3] > 0.f ? true : false;
480 // let meters fall a bit
481 clip_inL -= std::min(clip_inL, numsamples);
482 clip_inR -= std::min(clip_inR, numsamples);
483 clip_outL -= std::min(clip_outL, numsamples);
484 clip_outR -= std::min(clip_outR, numsamples);
485 meter_inL = 0.f;
486 meter_inR = 0.f;
487 meter_outL = 0.f;
488 meter_outR = 0.f;
489 while(offset < numsamples) {
490 // cycle through samples
491 float inL = ins[0][offset];
492 float inR = ins[1][offset];
493 // in level
494 inR *= *params[param_level_in];
495 inL *= *params[param_level_in];
496 // out vars
497 float outL = 0.f;
498 float outR = 0.f;
499 for (int i = 0; i < strips; i ++) {
500 // cycle trough strips
501 if (!mute[i]) {
502 // strip unmuted
503 float left = inL;
504 float right = inR;
505 // send trough filters
506 switch (i) {
507 case 0:
508 left = lpL0.process(left);
509 right = lpR0.process(right);
510 lpL0.sanitize();
511 lpR0.sanitize();
512 break;
513 case 1:
514 left = lpL1.process(left);
515 right = lpR1.process(right);
516 left = hpL0.process(left);
517 right = hpR0.process(right);
518 lpL1.sanitize();
519 lpR1.sanitize();
520 hpL0.sanitize();
521 hpR0.sanitize();
522 break;
523 case 2:
524 left = lpL2.process(left);
525 right = lpR2.process(right);
526 left = hpL1.process(left);
527 right = hpR1.process(right);
528 lpL2.sanitize();
529 lpR2.sanitize();
530 hpL1.sanitize();
531 hpR1.sanitize();
532 break;
533 case 3:
534 left = hpL2.process(left);
535 right = hpR2.process(right);
536 hpL2.sanitize();
537 hpR2.sanitize();
538 break;
540 // process gain reduction
541 strip[i].process(left, right);
542 // sum up output
543 outL += left;
544 outR += right;
545 } else {
546 // strip muted
551 } // process single strip
553 // even out filters gain reduction
554 // 3dB - levelled manually (based on default sep and q settings)
555 outL *= 1.414213562;
556 outR *= 1.414213562;
558 // out level
559 outL *= *params[param_level_out];
560 outR *= *params[param_level_out];
562 // send to output
563 outs[0][offset] = outL;
564 outs[1][offset] = outR;
566 // clip LED's
567 if(inL > 1.f) {
568 clip_inL = srate >> 3;
570 if(inR > 1.f) {
571 clip_inR = srate >> 3;
573 if(outL > 1.f) {
574 clip_outL = srate >> 3;
576 if(outR > 1.f) {
577 clip_outR = srate >> 3;
579 // set up in / out meters
580 if(inL > meter_inL) {
581 meter_inL = inL;
583 if(inR > meter_inR) {
584 meter_inR = inR;
586 if(outL > meter_outL) {
587 meter_outL = outL;
589 if(outR > meter_outR) {
590 meter_outR = outR;
592 // next sample
593 ++offset;
594 } // cycle trough samples
596 } // process all strips (no bypass)
598 // draw meters
599 if(params[param_clip_inL] != NULL) {
600 *params[param_clip_inL] = clip_inL;
602 if(params[param_clip_inR] != NULL) {
603 *params[param_clip_inR] = clip_inR;
605 if(params[param_clip_outL] != NULL) {
606 *params[param_clip_outL] = clip_outL;
608 if(params[param_clip_outR] != NULL) {
609 *params[param_clip_outR] = clip_outR;
612 if(params[param_meter_inL] != NULL) {
613 *params[param_meter_inL] = meter_inL;
615 if(params[param_meter_inR] != NULL) {
616 *params[param_meter_inR] = meter_inR;
618 if(params[param_meter_outL] != NULL) {
619 *params[param_meter_outL] = meter_outL;
621 if(params[param_meter_outR] != NULL) {
622 *params[param_meter_outR] = meter_outR;
624 // draw strip meters
625 if(bypass > 0.5f) {
626 if(params[param_compression0] != NULL) {
627 *params[param_compression0] = 1.0f;
629 if(params[param_compression1] != NULL) {
630 *params[param_compression1] = 1.0f;
632 if(params[param_compression2] != NULL) {
633 *params[param_compression2] = 1.0f;
635 if(params[param_compression3] != NULL) {
636 *params[param_compression3] = 1.0f;
639 if(params[param_output0] != NULL) {
640 *params[param_output0] = 0.0f;
642 if(params[param_output1] != NULL) {
643 *params[param_output1] = 0.0f;
645 if(params[param_output2] != NULL) {
646 *params[param_output2] = 0.0f;
648 if(params[param_output3] != NULL) {
649 *params[param_output3] = 0.0f;
651 } else {
652 if(params[param_compression0] != NULL) {
653 *params[param_compression0] = strip[0].get_comp_level();
655 if(params[param_compression1] != NULL) {
656 *params[param_compression1] = strip[1].get_comp_level();
658 if(params[param_compression2] != NULL) {
659 *params[param_compression2] = strip[2].get_comp_level();
661 if(params[param_compression3] != NULL) {
662 *params[param_compression3] = strip[3].get_comp_level();
665 if(params[param_output0] != NULL) {
666 *params[param_output0] = strip[0].get_output_level();
668 if(params[param_output1] != NULL) {
669 *params[param_output1] = strip[1].get_output_level();
671 if(params[param_output2] != NULL) {
672 *params[param_output2] = strip[2].get_output_level();
674 if(params[param_output3] != NULL) {
675 *params[param_output3] = strip[3].get_output_level();
678 // whatever has to be returned x)
679 return outputs_mask;
681 bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
683 // let's handle by the corresponding strip
684 switch (index) {
685 case param_compression0:
686 return strip[0].get_graph(subindex, data, points, context);
687 break;
688 case param_compression1:
689 return strip[1].get_graph(subindex, data, points, context);
690 break;
691 case param_compression2:
692 return strip[2].get_graph(subindex, data, points, context);
693 break;
694 case param_compression3:
695 return strip[3].get_graph(subindex, data, points, context);
696 break;
698 return false;
701 bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
703 // let's handle by the corresponding strip
704 switch (index) {
705 case param_compression0:
706 return strip[0].get_dot(subindex, x, y, size, context);
707 break;
708 case param_compression1:
709 return strip[1].get_dot(subindex, x, y, size, context);
710 break;
711 case param_compression2:
712 return strip[2].get_dot(subindex, x, y, size, context);
713 break;
714 case param_compression3:
715 return strip[3].get_dot(subindex, x, y, size, context);
716 break;
718 return false;
721 bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
723 // let's handle by the corresponding strip
724 switch (index) {
725 case param_compression0:
726 return strip[0].get_gridline(subindex, pos, vertical, legend, context);
727 break;
728 case param_compression1:
729 return strip[1].get_gridline(subindex, pos, vertical, legend, context);
730 break;
731 case param_compression2:
732 return strip[2].get_gridline(subindex, pos, vertical, legend, context);
733 break;
734 case param_compression3:
735 return strip[3].get_gridline(subindex, pos, vertical, legend, context);
736 break;
738 return false;
741 int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
743 // let's handle by the corresponding strip
744 switch (index) {
745 case param_compression0:
746 return strip[0].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
747 break;
748 case param_compression1:
749 return strip[1].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
750 break;
751 case param_compression2:
752 return strip[2].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
753 break;
754 case param_compression3:
755 return strip[3].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
756 break;
758 return 0;
761 /// Compressor originally by Thor
763 /// This module provides Thor's original compressor without any sidechain or weighting
764 ///////////////////////////////////////////////////////////////////////////////////////////////
766 compressor_audio_module::compressor_audio_module()
768 is_active = false;
769 srate = 0;
770 last_generation = 0;
773 void compressor_audio_module::activate()
775 is_active = true;
776 // set all filters and strips
777 compressor.activate();
778 params_changed();
779 meter_in = 0.f;
780 meter_out = 0.f;
781 clip_in = 0.f;
782 clip_out = 0.f;
784 void compressor_audio_module::deactivate()
786 is_active = false;
787 compressor.deactivate();
790 void compressor_audio_module::params_changed()
792 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);
795 void compressor_audio_module::set_sample_rate(uint32_t sr)
797 srate = sr;
798 compressor.set_sample_rate(srate);
801 uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
803 bool bypass = *params[param_bypass] > 0.5f;
804 numsamples += offset;
805 if(bypass) {
806 // everything bypassed
807 while(offset < numsamples) {
808 outs[0][offset] = ins[0][offset];
809 outs[1][offset] = ins[1][offset];
810 ++offset;
812 // displays, too
813 clip_in = 0.f;
814 clip_out = 0.f;
815 meter_in = 0.f;
816 meter_out = 0.f;
817 } else {
818 // process
820 clip_in -= std::min(clip_in, numsamples);
821 clip_out -= std::min(clip_out, numsamples);
823 while(offset < numsamples) {
824 // cycle through samples
825 float outL = 0.f;
826 float outR = 0.f;
827 float inL = ins[0][offset];
828 float inR = ins[1][offset];
829 // in level
830 inR *= *params[param_level_in];
831 inL *= *params[param_level_in];
833 float leftAC = inL;
834 float rightAC = inR;
835 float leftSC = inL;
836 float rightSC = inR;
838 compressor.process(leftAC, rightAC, leftSC, rightSC);
840 outL = leftAC;
841 outR = rightAC;
843 // send to output
844 outs[0][offset] = outL;
845 outs[1][offset] = outR;
847 // clip LED's
848 if(std::max(fabs(inL), fabs(inR)) > 1.f) {
849 clip_in = srate >> 3;
851 if(std::max(fabs(outL), fabs(outR)) > 1.f) {
852 clip_out = srate >> 3;
854 // rise up out meter
855 meter_in = std::max(fabs(inL), fabs(inR));;
856 meter_out = std::max(fabs(outL), fabs(outR));;
858 // next sample
859 ++offset;
860 } // cycle trough samples
862 // draw meters
863 if(params[param_clip_in] != NULL) {
864 *params[param_clip_in] = clip_in;
866 if(params[param_clip_out] != NULL) {
867 *params[param_clip_out] = clip_out;
869 if(params[param_meter_in] != NULL) {
870 *params[param_meter_in] = meter_in;
872 if(params[param_meter_out] != NULL) {
873 *params[param_meter_out] = meter_out;
875 // draw strip meter
876 if(bypass > 0.5f) {
877 if(params[param_compression] != NULL) {
878 *params[param_compression] = 1.0f;
880 } else {
881 if(params[param_compression] != NULL) {
882 *params[param_compression] = compressor.get_comp_level();
885 // whatever has to be returned x)
886 return outputs_mask;
888 bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
890 if (!is_active)
891 return false;
892 return compressor.get_graph(subindex, data, points, context);
895 bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
897 if (!is_active)
898 return false;
899 return compressor.get_dot(subindex, x, y, size, context);
902 bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
904 if (!is_active)
905 return false;
906 return compressor.get_gridline(subindex, pos, vertical, legend, context);
909 int compressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
911 if (!is_active)
912 return false;
913 return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
916 /// Sidecain Compressor by Markus Schmidt
918 /// This module splits the signal in a sidechain- and a process signal.
919 /// The sidechain is processed through Krzystofs filters and compresses
920 /// the process signal via Thor's compression routine afterwards.
921 ///////////////////////////////////////////////////////////////////////////////////////////////
923 sidechaincompressor_audio_module::sidechaincompressor_audio_module()
925 is_active = false;
926 srate = 0;
927 last_generation = 0;
930 void sidechaincompressor_audio_module::activate()
932 is_active = true;
933 // set all filters and strips
934 compressor.activate();
935 params_changed();
936 meter_in = 0.f;
937 meter_out = 0.f;
938 clip_in = 0.f;
939 clip_out = 0.f;
941 void sidechaincompressor_audio_module::deactivate()
943 is_active = false;
944 compressor.deactivate();
947 void sidechaincompressor_audio_module::params_changed()
949 // set the params of all filters
950 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
951 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
952 or *params[param_sc_mode] != sc_mode) {
953 float q = 0.707;
954 switch ((int)*params[param_sc_mode]) {
955 default:
956 case WIDEBAND:
957 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
958 f1R.copy_coeffs(f1L);
959 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
960 f2R.copy_coeffs(f2L);
961 f1_active = 0.f;
962 f2_active = 0.f;
963 break;
964 case DEESSER_WIDE:
965 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
966 f1R.copy_coeffs(f1L);
967 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
968 f2R.copy_coeffs(f2L);
969 f1_active = 0.5f;
970 f2_active = 1.f;
971 break;
972 case DEESSER_SPLIT:
973 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
974 f1R.copy_coeffs(f1L);
975 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
976 f2R.copy_coeffs(f2L);
977 f1_active = 0.f;
978 f2_active = 1.f;
979 break;
980 case DERUMBLER_WIDE:
981 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
982 f1R.copy_coeffs(f1L);
983 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
984 f2R.copy_coeffs(f2L);
985 f1_active = 1.f;
986 f2_active = 0.5f;
987 break;
988 case DERUMBLER_SPLIT:
989 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
990 f1R.copy_coeffs(f1L);
991 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
992 f2R.copy_coeffs(f2L);
993 f1_active = 1.f;
994 f2_active = 0.f;
995 break;
996 case WEIGHTED_1:
997 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
998 f1R.copy_coeffs(f1L);
999 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1000 f2R.copy_coeffs(f2L);
1001 f1_active = 0.5f;
1002 f2_active = 0.5f;
1003 break;
1004 case WEIGHTED_2:
1005 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1006 f1R.copy_coeffs(f1L);
1007 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1008 f2R.copy_coeffs(f2L);
1009 f1_active = 0.5f;
1010 f2_active = 0.5f;
1011 break;
1012 case WEIGHTED_3:
1013 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1014 f1R.copy_coeffs(f1L);
1015 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1016 f2R.copy_coeffs(f2L);
1017 f1_active = 0.5f;
1018 f2_active = 0.5f;
1019 break;
1020 case BANDPASS_1:
1021 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1022 f1R.copy_coeffs(f1L);
1023 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1024 f2R.copy_coeffs(f2L);
1025 f1_active = 1.f;
1026 f2_active = 0.f;
1027 break;
1028 case BANDPASS_2:
1029 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1030 f1R.copy_coeffs(f1L);
1031 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1032 f2R.copy_coeffs(f2L);
1033 f1_active = 1.f;
1034 f2_active = 1.f;
1035 break;
1037 f1_freq_old = *params[param_f1_freq];
1038 f1_level_old = *params[param_f1_level];
1039 f2_freq_old = *params[param_f2_freq];
1040 f2_level_old = *params[param_f2_level];
1041 sc_mode = (CalfScModes)*params[param_sc_mode];
1043 // light LED's
1044 if(params[param_f1_active] != NULL) {
1045 *params[param_f1_active] = f1_active;
1047 if(params[param_f2_active] != NULL) {
1048 *params[param_f2_active] = f2_active;
1050 // and set the compressor module
1051 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);
1054 void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr)
1056 srate = sr;
1057 compressor.set_sample_rate(srate);
1060 uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1062 bool bypass = *params[param_bypass] > 0.5f;
1063 numsamples += offset;
1064 if(bypass) {
1065 // everything bypassed
1066 while(offset < numsamples) {
1067 outs[0][offset] = ins[0][offset];
1068 outs[1][offset] = ins[1][offset];
1069 ++offset;
1071 // displays, too
1072 clip_in = 0.f;
1073 clip_out = 0.f;
1074 meter_in = 0.f;
1075 meter_out = 0.f;
1076 } else {
1077 // process
1079 clip_in -= std::min(clip_in, numsamples);
1080 clip_out -= std::min(clip_out, numsamples);
1082 while(offset < numsamples) {
1083 // cycle through samples
1084 float outL = 0.f;
1085 float outR = 0.f;
1086 float inL = ins[0][offset];
1087 float inR = ins[1][offset];
1088 // in level
1089 inR *= *params[param_level_in];
1090 inL *= *params[param_level_in];
1093 float leftAC = inL;
1094 float rightAC = inR;
1095 float leftSC = inL;
1096 float rightSC = inR;
1097 float leftMC = inL;
1098 float rightMC = inR;
1100 switch ((int)*params[param_sc_mode]) {
1101 default:
1102 case WIDEBAND:
1103 compressor.process(leftAC, rightAC, leftSC, rightSC);
1104 break;
1105 case DEESSER_WIDE:
1106 case DERUMBLER_WIDE:
1107 case WEIGHTED_1:
1108 case WEIGHTED_2:
1109 case WEIGHTED_3:
1110 case BANDPASS_2:
1111 leftSC = f2L.process(f1L.process(leftSC));
1112 rightSC = f2R.process(f1R.process(rightSC));
1113 leftMC = leftSC;
1114 rightMC = rightSC;
1115 compressor.process(leftAC, rightAC, leftSC, rightSC);
1116 break;
1117 case DEESSER_SPLIT:
1118 leftSC = f2L.process(leftSC);
1119 rightSC = f2R.process(rightSC);
1120 leftMC = leftSC;
1121 rightMC = rightSC;
1122 compressor.process(leftSC, rightSC, leftSC, rightSC);
1123 leftAC = f1L.process(leftAC);
1124 rightAC = f1R.process(rightAC);
1125 leftAC += leftSC;
1126 rightAC += rightSC;
1127 break;
1128 case DERUMBLER_SPLIT:
1129 leftSC = f1L.process(leftSC);
1130 rightSC = f1R.process(rightSC);
1131 leftMC = leftSC;
1132 rightMC = rightSC;
1133 compressor.process(leftSC, rightSC, leftSC, rightSC);
1134 leftAC = f2L.process(leftAC);
1135 rightAC = f2R.process(rightAC);
1136 leftAC += leftSC;
1137 rightAC += rightSC;
1138 break;
1139 case BANDPASS_1:
1140 leftSC = f1L.process(leftSC);
1141 rightSC = f1R.process(rightSC);
1142 leftMC = leftSC;
1143 rightMC = rightSC;
1144 compressor.process(leftAC, rightAC, leftSC, rightSC);
1145 break;
1148 if(*params[param_sc_listen] > 0.f) {
1149 outL = leftMC;
1150 outR = rightMC;
1151 } else {
1152 outL = leftAC;
1153 outR = rightAC;
1156 // send to output
1157 outs[0][offset] = outL;
1158 outs[1][offset] = outR;
1160 // clip LED's
1161 if(std::max(fabs(inL), fabs(inR)) > 1.f) {
1162 clip_in = srate >> 3;
1164 if(std::max(fabs(outL), fabs(outR)) > 1.f) {
1165 clip_out = srate >> 3;
1167 // rise up out meter
1168 meter_in = std::max(fabs(inL), fabs(inR));;
1169 meter_out = std::max(fabs(outL), fabs(outR));;
1171 // next sample
1172 ++offset;
1173 } // cycle trough samples
1174 f1L.sanitize();
1175 f1R.sanitize();
1176 f2L.sanitize();
1177 f2R.sanitize();
1180 // draw meters
1181 if(params[param_clip_in] != NULL) {
1182 *params[param_clip_in] = clip_in;
1184 if(params[param_clip_out] != NULL) {
1185 *params[param_clip_out] = clip_out;
1187 if(params[param_meter_in] != NULL) {
1188 *params[param_meter_in] = meter_in;
1190 if(params[param_meter_out] != NULL) {
1191 *params[param_meter_out] = meter_out;
1193 // draw strip meter
1194 if(bypass > 0.5f) {
1195 if(params[param_compression] != NULL) {
1196 *params[param_compression] = 1.0f;
1198 } else {
1199 if(params[param_compression] != NULL) {
1200 *params[param_compression] = compressor.get_comp_level();
1203 // whatever has to be returned x)
1204 return outputs_mask;
1206 bool sidechaincompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
1208 if (!is_active)
1209 return false;
1210 if (index == param_f1_freq && !subindex) {
1211 context->set_line_width(1.5);
1212 return ::get_graph(*this, subindex, data, points);
1213 } else if(index == param_compression) {
1214 return compressor.get_graph(subindex, data, points, context);
1216 return false;
1219 bool sidechaincompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
1221 if (!is_active)
1222 return false;
1223 if (index == param_compression) {
1224 return compressor.get_dot(subindex, x, y, size, context);
1226 return false;
1229 bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1231 if (!is_active)
1232 return false;
1233 if (index == param_compression) {
1234 return compressor.get_gridline(subindex, pos, vertical, legend, context);
1235 } else {
1236 return get_freq_gridline(subindex, pos, vertical, legend, context);
1238 // return false;
1241 int sidechaincompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1243 if (!is_active)
1244 return false;
1245 if(index == param_compression) {
1246 return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1247 } else {
1248 // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
1249 if (*params[param_f1_freq] != f1_freq_old1
1250 or *params[param_f2_freq] != f2_freq_old1
1251 or *params[param_f1_level] != f1_level_old1
1252 or *params[param_f2_level] != f2_level_old1
1253 or *params[param_sc_mode] !=sc_mode_old1)
1255 f1_freq_old1 = *params[param_f1_freq];
1256 f2_freq_old1 = *params[param_f2_freq];
1257 f1_level_old1 = *params[param_f1_level];
1258 f2_level_old1 = *params[param_f2_level];
1259 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
1260 last_generation++;
1261 subindex_graph = 0;
1262 subindex_dot = INT_MAX;
1263 subindex_gridline = INT_MAX;
1265 else {
1266 subindex_graph = 0;
1267 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
1269 if (generation == last_calculated_generation)
1270 subindex_graph = INT_MAX;
1271 return last_generation;
1273 return false;
1276 /// Deesser by Markus Schmidt
1278 /// This module splits the signal in a sidechain- and a process signal.
1279 /// The sidechain is processed through Krzystofs filters and compresses
1280 /// the process signal via Thor's compression routine afterwards.
1281 ///////////////////////////////////////////////////////////////////////////////////////////////
1283 deesser_audio_module::deesser_audio_module()
1285 is_active = false;
1286 srate = 0;
1287 last_generation = 0;
1290 void deesser_audio_module::activate()
1292 is_active = true;
1293 // set all filters and strips
1294 compressor.activate();
1295 params_changed();
1296 detected = 0.f;
1297 detected_led = 0.f;
1298 clip_out = 0.f;
1300 void deesser_audio_module::deactivate()
1302 is_active = false;
1303 compressor.deactivate();
1306 void deesser_audio_module::params_changed()
1308 // set the params of all filters
1309 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1310 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1311 or *params[param_f2_q] != f2_q_old) {
1312 float q = 0.707;
1314 hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
1315 hpR.copy_coeffs(hpL);
1316 lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
1317 lpR.copy_coeffs(lpL);
1318 pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
1319 pR.copy_coeffs(pL);
1320 f1_freq_old = *params[param_f1_freq];
1321 f1_level_old = *params[param_f1_level];
1322 f2_freq_old = *params[param_f2_freq];
1323 f2_level_old = *params[param_f2_level];
1324 f2_q_old = *params[param_f2_q];
1326 // and set the compressor module
1327 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);
1330 void deesser_audio_module::set_sample_rate(uint32_t sr)
1332 srate = sr;
1333 compressor.set_sample_rate(srate);
1336 uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1338 bool bypass = *params[param_bypass] > 0.5f;
1339 numsamples += offset;
1340 if(bypass) {
1341 // everything bypassed
1342 while(offset < numsamples) {
1343 outs[0][offset] = ins[0][offset];
1344 outs[1][offset] = ins[1][offset];
1345 ++offset;
1347 // displays, too
1348 clip_out = 0.f;
1349 detected = 0.f;
1350 detected_led = 0.f;
1351 } else {
1352 // process
1354 detected_led -= std::min(detected_led, numsamples);
1355 clip_led -= std::min(clip_led, numsamples);
1357 while(offset < numsamples) {
1358 // cycle through samples
1359 float outL = 0.f;
1360 float outR = 0.f;
1361 float inL = ins[0][offset];
1362 float inR = ins[1][offset];
1365 float leftAC = inL;
1366 float rightAC = inR;
1367 float leftSC = inL;
1368 float rightSC = inR;
1369 float leftRC = inL;
1370 float rightRC = inR;
1371 float leftMC = inL;
1372 float rightMC = inR;
1374 leftSC = pL.process(hpL.process(leftSC));
1375 rightSC = pR.process(hpR.process(rightSC));
1376 leftMC = leftSC;
1377 rightMC = rightSC;
1379 switch ((int)*params[param_mode]) {
1380 default:
1381 case WIDE:
1382 compressor.process(leftAC, rightAC, leftSC, rightSC);
1383 break;
1384 case SPLIT:
1385 hpL.sanitize();
1386 hpR.sanitize();
1387 leftRC = hpL.process(leftRC);
1388 rightRC = hpR.process(rightRC);
1389 compressor.process(leftRC, rightRC, leftSC, rightSC);
1390 leftAC = lpL.process(leftAC);
1391 rightAC = lpR.process(rightAC);
1392 leftAC += leftRC;
1393 rightAC += rightRC;
1394 break;
1397 if(*params[param_sc_listen] > 0.f) {
1398 outL = leftMC;
1399 outR = rightMC;
1400 } else {
1401 outL = leftAC;
1402 outR = rightAC;
1405 // send to output
1406 outs[0][offset] = outL;
1407 outs[1][offset] = outR;
1409 if(std::max(fabs(leftSC), fabs(rightSC)) > *params[param_threshold]) {
1410 detected_led = srate >> 3;
1412 if(std::max(fabs(leftAC), fabs(rightAC)) > 1.f) {
1413 clip_led = srate >> 3;
1415 if(clip_led > 0) {
1416 clip_out = 1.f;
1417 } else {
1418 clip_out = std::max(fabs(outL), fabs(outR));
1420 detected = std::max(fabs(leftMC), fabs(rightMC));
1422 // next sample
1423 ++offset;
1424 } // cycle trough samples
1425 hpL.sanitize();
1426 hpR.sanitize();
1427 lpL.sanitize();
1428 lpR.sanitize();
1429 pL.sanitize();
1430 pR.sanitize();
1432 // draw meters
1433 if(params[param_detected_led] != NULL) {
1434 *params[param_detected_led] = detected_led;
1436 if(params[param_clip_out] != NULL) {
1437 *params[param_clip_out] = clip_out;
1439 if(params[param_detected] != NULL) {
1440 *params[param_detected] = detected;
1442 // draw strip meter
1443 if(bypass > 0.5f) {
1444 if(params[param_compression] != NULL) {
1445 *params[param_compression] = 1.0f;
1447 } else {
1448 if(params[param_compression] != NULL) {
1449 *params[param_compression] = compressor.get_comp_level();
1452 // whatever has to be returned x)
1453 return outputs_mask;
1455 bool deesser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
1457 if (!is_active)
1458 return false;
1459 if (index == param_f1_freq && !subindex) {
1460 context->set_line_width(1.5);
1461 return ::get_graph(*this, subindex, data, points);
1463 return false;
1466 bool deesser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1468 return get_freq_gridline(subindex, pos, vertical, legend, context);
1470 // return false;
1473 int deesser_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1475 if (!is_active) {
1476 return false;
1477 } else {
1478 // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
1479 if (*params[param_f1_freq] != f1_freq_old1
1480 or *params[param_f2_freq] != f2_freq_old1
1481 or *params[param_f1_level] != f1_level_old1
1482 or *params[param_f2_level] != f2_level_old1
1483 or *params[param_f2_q] !=f2_q_old1)
1485 f1_freq_old1 = *params[param_f1_freq];
1486 f2_freq_old1 = *params[param_f2_freq];
1487 f1_level_old1 = *params[param_f1_level];
1488 f2_level_old1 = *params[param_f2_level];
1489 f2_q_old1 = *params[param_f2_q];
1490 last_generation++;
1491 subindex_graph = 0;
1492 subindex_dot = INT_MAX;
1493 subindex_gridline = INT_MAX;
1495 else {
1496 subindex_graph = 0;
1497 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
1499 if (generation == last_calculated_generation)
1500 subindex_graph = INT_MAX;
1501 return last_generation;
1503 return false;
1506 /// Gain reduction module by Thor
1507 /// All functions of this module are originally written
1508 /// by Thor, while some features have been stripped (mainly stereo linking
1509 /// and frequency correction as implemented in Sidechain Compressor above)
1510 /// To save some CPU.
1511 ////////////////////////////////////////////////////////////////////////////////
1512 gain_reduction_audio_module::gain_reduction_audio_module()
1514 is_active = false;
1515 last_generation = 0;
1518 void gain_reduction_audio_module::activate()
1520 is_active = true;
1521 linSlope = 0.f;
1522 meter_out = 0.f;
1523 meter_comp = 1.f;
1524 float l, r;
1525 l = r = 0.f;
1526 float byp = bypass;
1527 bypass = 0.0;
1528 process(l, r);
1529 bypass = byp;
1532 void gain_reduction_audio_module::deactivate()
1534 is_active = false;
1537 void gain_reduction_audio_module::process(float &left, float &right, float det_left, float det_right)
1539 if(!det_left) {
1540 det_left = left;
1542 if(!det_right) {
1543 det_right = right;
1545 float gain = 1.f;
1546 if(bypass < 0.5f) {
1547 // this routine is mainly copied from thor's compressor module
1548 // greatest sounding compressor I've heard!
1549 bool rms = detection == 0;
1550 bool average = stereo_link == 0;
1551 float linThreshold = threshold;
1552 float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
1553 float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
1554 float linKneeSqrt = sqrt(knee);
1555 linKneeStart = linThreshold / linKneeSqrt;
1556 adjKneeStart = linKneeStart*linKneeStart;
1557 float linKneeStop = linThreshold * linKneeSqrt;
1558 thres = log(linThreshold);
1559 kneeStart = log(linKneeStart);
1560 kneeStop = log(linKneeStop);
1561 compressedKneeStop = (kneeStop - thres) / ratio + thres;
1563 float absample = average ? (fabs(det_left) + fabs(det_right)) * 0.5f : std::max(fabs(det_left), fabs(det_right));
1564 if(rms) absample *= absample;
1566 linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
1568 if(linSlope > 0.f) {
1569 gain = output_gain(linSlope, rms);
1572 left *= gain * makeup;
1573 right *= gain * makeup;
1574 meter_out = std::max(fabs(left), fabs(right));;
1575 meter_comp = gain;
1576 detected = rms ? sqrt(linSlope) : linSlope;
1580 float gain_reduction_audio_module::output_level(float slope) {
1581 return slope * output_gain(slope, false) * makeup;
1584 float gain_reduction_audio_module::output_gain(float linSlope, bool rms) {
1585 //this calculation is also thor's work
1586 if(linSlope > (rms ? adjKneeStart : linKneeStart)) {
1587 float slope = log(linSlope);
1588 if(rms) slope *= 0.5f;
1590 float gain = 0.f;
1591 float delta = 0.f;
1592 if(IS_FAKE_INFINITY(ratio)) {
1593 gain = thres;
1594 delta = 0.f;
1595 } else {
1596 gain = (slope - thres) / ratio + thres;
1597 delta = 1.f / ratio;
1600 if(knee > 1.f && slope < kneeStop) {
1601 gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta);
1604 return exp(gain - slope);
1607 return 1.f;
1610 void gain_reduction_audio_module::set_sample_rate(uint32_t sr)
1612 srate = sr;
1614 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)
1616 // set all params
1617 attack = att;
1618 release = rel;
1619 threshold = thr;
1620 ratio = rat;
1621 knee = kn;
1622 makeup = mak;
1623 detection = det;
1624 stereo_link = stl;
1625 bypass = byp;
1626 mute = mu;
1627 if(mute > 0.f) {
1628 meter_out = 0.f;
1629 meter_comp = 1.f;
1632 float gain_reduction_audio_module::get_output_level() {
1633 // returns output level (max(left, right))
1634 return meter_out;
1636 float gain_reduction_audio_module::get_comp_level() {
1637 // returns amount of compression
1638 return meter_comp;
1641 bool gain_reduction_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context)
1643 if (!is_active)
1644 return false;
1645 if (subindex > 1) // 1
1646 return false;
1647 for (int i = 0; i < points; i++)
1649 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
1650 if (subindex == 0)
1651 data[i] = dB_grid(input);
1652 else {
1653 float output = output_level(input);
1654 data[i] = dB_grid(output);
1657 if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
1658 context->set_source_rgba(0.35, 0.4, 0.2, 0.3);
1659 else {
1660 context->set_source_rgba(0.35, 0.4, 0.2, 1);
1661 context->set_line_width(1.5);
1663 return true;
1666 bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context)
1668 if (!is_active)
1669 return false;
1670 if (!subindex)
1672 if(bypass > 0.5f or mute > 0.f) {
1673 return false;
1674 } else {
1675 bool rms = detection == 0;
1676 float det = rms ? sqrt(detected) : detected;
1677 x = 0.5 + 0.5 * dB_grid(det);
1678 y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
1679 return true;
1682 return false;
1685 bool gain_reduction_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1687 bool tmp;
1688 vertical = (subindex & 1) != 0;
1689 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
1690 if (result && vertical) {
1691 if ((subindex & 4) && !legend.empty()) {
1692 legend = "";
1694 else {
1695 size_t pos = legend.find(" dB");
1696 if (pos != std::string::npos)
1697 legend.erase(pos);
1699 pos = 0.5 + 0.5 * pos;
1701 return result;
1704 int gain_reduction_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1706 subindex_graph = 0;
1707 subindex_dot = 0;
1708 subindex_gridline = generation ? INT_MAX : 0;
1710 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)
1712 old_threshold = threshold;
1713 old_ratio = ratio;
1714 old_knee = knee;
1715 old_makeup = makeup;
1716 old_detection = detection;
1717 old_bypass = bypass;
1718 old_mute = mute;
1719 last_generation++;
1722 if (generation == last_generation)
1723 subindex_graph = 2;
1724 return last_generation;
1727 /// Equalizer 12 Band by Markus Schmidt
1729 /// This module is based on Krzysztof's filters. It provides a couple
1730 /// of different chained filters.
1731 ///////////////////////////////////////////////////////////////////////////////////////////////
1733 template<class BaseClass, bool has_lphp>
1734 equalizerNband_audio_module<BaseClass, has_lphp>::equalizerNband_audio_module()
1736 is_active = false;
1737 srate = 0;
1738 last_generation = 0;
1739 clip_inL = clip_inR = clip_outL = clip_outR = 0.f;
1740 meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
1743 template<class BaseClass, bool has_lphp>
1744 void equalizerNband_audio_module<BaseClass, has_lphp>::activate()
1746 is_active = true;
1747 // set all filters
1748 params_changed();
1751 template<class BaseClass, bool has_lphp>
1752 void equalizerNband_audio_module<BaseClass, has_lphp>::deactivate()
1754 is_active = false;
1757 static inline void copy_lphp(biquad_d2<float> filters[3][2])
1759 for (int i = 0; i < 3; i++)
1760 for (int j = 0; j < 2; j++)
1761 if (i || j)
1762 filters[i][j].copy_coeffs(filters[0][0]);
1765 template<class BaseClass, bool has_lphp>
1766 void equalizerNband_audio_module<BaseClass, has_lphp>::params_changed()
1768 // set the params of all filters
1770 // lp/hp first (if available)
1771 if (has_lphp)
1773 hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode];
1774 lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode];
1776 float hpfreq = *params[AM::param_hp_freq], lpfreq = *params[AM::param_lp_freq];
1778 if(hpfreq != hp_freq_old) {
1779 hp[0][0].set_hp_rbj(hpfreq, 0.707, (float)srate, 1.0);
1780 copy_lphp(hp);
1781 hp_freq_old = hpfreq;
1783 if(lpfreq != lp_freq_old) {
1784 lp[0][0].set_lp_rbj(lpfreq, 0.707, (float)srate, 1.0);
1785 copy_lphp(lp);
1786 lp_freq_old = lpfreq;
1790 // then shelves
1791 float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level];
1792 float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level];
1794 if(lsfreq != ls_freq_old or lslevel != ls_level_old) {
1795 lsL.set_lowshelf_rbj(lsfreq, 0.707, lslevel, (float)srate);
1796 lsR.copy_coeffs(lsL);
1797 ls_level_old = lslevel;
1798 ls_freq_old = lsfreq;
1800 if(hsfreq != hs_freq_old or hslevel != hs_level_old) {
1801 hsL.set_highshelf_rbj(hsfreq, 0.707, hslevel, (float)srate);
1802 hsR.copy_coeffs(hsL);
1803 hs_level_old = hslevel;
1804 hs_freq_old = hsfreq;
1806 for (int i = 0; i < AM::PeakBands; i++)
1808 int offset = i * params_per_band;
1809 float freq = *params[AM::param_p1_freq + offset];
1810 float level = *params[AM::param_p1_level + offset];
1811 float q = *params[AM::param_p1_q + offset];
1812 if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) {
1813 pL[i].set_peakeq_rbj(freq, q, level, (float)srate);
1814 pR[i].copy_coeffs(pL[i]);
1815 p_freq_old[i] = freq;
1816 p_level_old[i] = level;
1817 p_q_old[i] = q;
1822 template<class BaseClass, bool has_lphp>
1823 inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float &left, float &right)
1825 if (!has_lphp)
1826 return;
1827 if (*params[AM::param_lp_active] > 0.f)
1829 switch(lp_mode)
1831 case MODE12DB:
1832 left = lp[0][0].process(left);
1833 right = lp[0][1].process(right);
1834 break;
1835 case MODE24DB:
1836 left = lp[1][0].process(lp[0][0].process(left));
1837 right = lp[1][1].process(lp[0][1].process(right));
1838 break;
1839 case MODE36DB:
1840 left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left)));
1841 right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right)));
1842 break;
1845 if (*params[AM::param_hp_active] > 0.f)
1847 switch(hp_mode)
1849 case MODE12DB:
1850 left = hp[0][0].process(left);
1851 right = hp[0][1].process(right);
1852 break;
1853 case MODE24DB:
1854 left = hp[1][0].process(hp[0][0].process(left));
1855 right = hp[1][1].process(hp[0][1].process(right));
1856 break;
1857 case MODE36DB:
1858 left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left)));
1859 right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right)));
1860 break;
1865 #define SET_IF_CONNECTED(param) if (params[AM::param_##param] != NULL) *params[AM::param_##param] = param;
1867 template<class BaseClass, bool has_lphp>
1868 uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1870 bool bypass = *params[AM::param_bypass] > 0.f;
1871 numsamples += offset;
1872 if(bypass) {
1873 // everything bypassed
1874 while(offset < numsamples) {
1875 outs[0][offset] = ins[0][offset];
1876 outs[1][offset] = ins[1][offset];
1877 ++offset;
1879 // displays, too
1880 clip_inL = clip_inR = clip_outL = clip_outR = 0.f;
1881 meter_inL = meter_inR = meter_outL = meter_outR = 0.f;
1882 } else {
1884 clip_inL -= std::min(clip_inL, numsamples);
1885 clip_inR -= std::min(clip_inR, numsamples);
1886 clip_outL -= std::min(clip_outL, numsamples);
1887 clip_outR -= std::min(clip_outR, numsamples);
1888 meter_inL = 0.f;
1889 meter_inR = 0.f;
1890 meter_outL = 0.f;
1891 meter_outR = 0.f;
1893 // process
1894 while(offset < numsamples) {
1895 // cycle through samples
1896 float outL = 0.f;
1897 float outR = 0.f;
1898 float inL = ins[0][offset];
1899 float inR = ins[1][offset];
1900 // in level
1901 inR *= *params[AM::param_level_in];
1902 inL *= *params[AM::param_level_in];
1904 float procL = inL;
1905 float procR = inR;
1907 // all filters in chain
1908 process_hplp(procL, procR);
1909 if(*params[AM::param_ls_active] > 0.f) {
1910 procL = lsL.process(procL);
1911 procR = lsR.process(procR);
1913 if(*params[AM::param_hs_active] > 0.f) {
1914 procL = hsL.process(procL);
1915 procR = hsR.process(procR);
1917 for (int i = 0; i < AM::PeakBands; i++)
1919 if(*params[AM::param_p1_active + i * params_per_band] > 0.f) {
1920 procL = pL[i].process(procL);
1921 procR = pR[i].process(procR);
1925 outL = procL * *params[AM::param_level_out];
1926 outR = procR * *params[AM::param_level_out];
1928 // send to output
1929 outs[0][offset] = outL;
1930 outs[1][offset] = outR;
1932 // clip LED's
1933 if(inL > 1.f) {
1934 clip_inL = srate >> 3;
1936 if(inR > 1.f) {
1937 clip_inR = srate >> 3;
1939 if(outL > 1.f) {
1940 clip_outL = srate >> 3;
1942 if(outR > 1.f) {
1943 clip_outR = srate >> 3;
1945 // set up in / out meters
1946 if(inL > meter_inL) {
1947 meter_inL = inL;
1949 if(inR > meter_inR) {
1950 meter_inR = inR;
1952 if(outL > meter_outL) {
1953 meter_outL = outL;
1955 if(outR > meter_outR) {
1956 meter_outR = outR;
1959 // next sample
1960 ++offset;
1961 } // cycle trough samples
1962 // clean up
1963 for(int i = 0; i < 3; ++i) {
1964 hp[i][0].sanitize();
1965 hp[i][1].sanitize();
1966 lp[i][0].sanitize();
1967 lp[i][1].sanitize();
1969 lsL.sanitize();
1970 hsR.sanitize();
1971 for(int i = 0; i < AM::PeakBands; ++i) {
1972 pL[i].sanitize();
1973 pR[i].sanitize();
1976 // draw meters
1977 SET_IF_CONNECTED(clip_inL)
1978 SET_IF_CONNECTED(clip_inR)
1979 SET_IF_CONNECTED(clip_outL)
1980 SET_IF_CONNECTED(clip_outR)
1981 SET_IF_CONNECTED(meter_inL)
1982 SET_IF_CONNECTED(meter_inR)
1983 SET_IF_CONNECTED(meter_outL)
1984 SET_IF_CONNECTED(meter_outR)
1985 // whatever has to be returned x)
1986 return outputs_mask;
1989 #undef SET_IF_CONNECTED
1991 template<class BaseClass, bool has_lphp>
1992 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
1994 if (!is_active)
1995 return false;
1996 if (index == AM::param_p1_freq && !subindex) {
1997 context->set_line_width(1.5);
1998 return ::get_graph(*this, subindex, data, points);
2000 return false;
2003 template<class BaseClass, bool has_lphp>
2004 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
2006 if (!is_active) {
2007 return false;
2008 } else {
2009 return get_freq_gridline(subindex, pos, vertical, legend, context);
2013 template<class BaseClass, bool has_lphp>
2014 int equalizerNband_audio_module<BaseClass, has_lphp>::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
2016 if (!is_active) {
2017 return false;
2018 } else {
2019 bool changed = false;
2020 for (int i = 0; i < graph_param_count && !changed; i++)
2022 if (*params[AM::first_graph_param + i] != old_params_for_graph[i])
2023 changed = true;
2025 if (changed)
2027 for (int i = 0; i < graph_param_count; i++)
2028 old_params_for_graph[i] = *params[AM::first_graph_param + i];
2030 last_generation++;
2031 subindex_graph = 0;
2032 subindex_dot = INT_MAX;
2033 subindex_gridline = INT_MAX;
2035 else {
2036 subindex_graph = 0;
2037 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
2039 if (generation == last_calculated_generation)
2040 subindex_graph = INT_MAX;
2041 return last_generation;
2043 return false;
2046 static inline float adjusted_lphp_gain(float **params, int param_active, int param_mode, biquad_d2<float> filter, float freq, float srate)
2048 if(*params[param_active] > 0.f) {
2049 float gain = filter.freq_gain(freq, srate);
2050 switch((int)*params[param_mode]) {
2051 case MODE12DB:
2052 return gain;
2053 case MODE24DB:
2054 return gain * gain;
2055 case MODE36DB:
2056 return gain * gain * gain;
2059 return 1;
2062 template<class BaseClass, bool use_hplp>
2063 float equalizerNband_audio_module<BaseClass, use_hplp>::freq_gain(int index, double freq, uint32_t sr)
2065 float ret = 1.f;
2066 if (use_hplp)
2068 ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)sr);
2069 ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)sr);
2071 ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, sr) : 1;
2072 ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, sr) : 1;
2073 for (int i = 0; i < PeakBands; i++)
2074 ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)sr) : 1;
2075 return ret;
2078 template class equalizerNband_audio_module<equalizer5band_metadata, false>;
2079 template class equalizerNband_audio_module<equalizer8band_metadata, true>;
2080 template class equalizerNband_audio_module<equalizer12band_metadata, true>;
2082 /// LFO module by Markus
2083 /// This module provides simple LFO's (sine=0, triangle=1, square=2, saw_up=3, saw_down=4)
2084 /// get_value() returns a value between -1 and 1
2085 ////////////////////////////////////////////////////////////////////////////////
2086 lfo_audio_module::lfo_audio_module()
2088 is_active = false;
2089 phase = 0.f;
2092 void lfo_audio_module::activate()
2094 is_active = true;
2095 phase = 0.f;
2098 void lfo_audio_module::deactivate()
2100 is_active = false;
2103 float lfo_audio_module::get_value()
2105 return get_value_from_phase(phase, offset) * amount;
2108 float lfo_audio_module::get_value_from_phase(float ph, float off)
2110 float val = 0.f;
2111 float phs = ph + off;
2112 if (phs >= 1.0)
2113 phs = fmod(phs, 1.f);
2114 switch (mode) {
2115 default:
2116 case 0:
2117 // sine
2118 val = sin((phs * 360.f) * M_PI / 180);
2119 break;
2120 case 1:
2121 // triangle
2122 if(phs > 0.75)
2123 val = (phs - 0.75) * 4 - 1;
2124 else if(phs > 0.5)
2125 val = (phs - 0.5) * 4 * -1;
2126 else if(phs > 0.25)
2127 val = 1 - (phs - 0.25) * 4;
2128 else
2129 val = phs * 4;
2130 break;
2131 case 2:
2132 // square
2133 val = (phs < 0.5) ? -1 : +1;
2134 break;
2135 case 3:
2136 // saw up
2137 val = phs * 2.f - 1;
2138 break;
2139 case 4:
2140 // saw down
2141 val = 1 - phs * 2.f;
2142 break;
2144 return val;
2147 void lfo_audio_module::advance(uint32_t count)
2149 //this function walks from 0.f to 1.f and starts all over again
2150 phase += count * freq * (1.0 / srate);
2151 if (phase >= 1.0)
2152 phase = fmod(phase, 1.f);
2155 void lfo_audio_module::set_phase(float ph)
2157 //set the phase from outsinde
2158 phase = fabs(ph);
2159 if (phase >= 1.0)
2160 phase = fmod(phase, 1.f);
2163 void lfo_audio_module::set_params(float f, int m, float o, uint32_t sr, float a)
2165 // freq: a value in Hz
2166 // mode: sine=0, triangle=1, square=2, saw_up=3, saw_down=4
2167 // offset: value between 0.f and 1.f to offset the lfo in time
2168 freq = f;
2169 mode = m;
2170 offset = o;
2171 srate = sr;
2172 amount = a;
2175 bool lfo_audio_module::get_graph(float *data, int points, cairo_iface *context)
2177 if (!is_active)
2178 return false;
2179 for (int i = 0; i < points; i++) {
2180 float ph = (float)i / (float)points;
2181 data[i] = get_value_from_phase(ph, offset) * amount;
2183 return true;
2186 bool lfo_audio_module::get_dot(float &x, float &y, int &size, cairo_iface *context)
2188 if (!is_active)
2189 return false;
2190 float phs = phase + offset;
2191 if (phs >= 1.0)
2192 phs = fmod(phs, 1.f);
2193 x = phase;
2194 y = get_value_from_phase(phase, offset) * amount;
2195 return true;
2198 /// Pulsator by Markus Schmidt
2200 /// This module provides a couple
2201 /// of different LFO's for modulating the level of a signal.
2202 ///////////////////////////////////////////////////////////////////////////////////////////////
2204 pulsator_audio_module::pulsator_audio_module()
2206 is_active = false;
2207 srate = 0;
2208 // last_generation = 0;
2209 clip_inL = 0.f;
2210 clip_inR = 0.f;
2211 clip_outL = 0.f;
2212 clip_outR = 0.f;
2213 meter_inL = 0.f;
2214 meter_inR = 0.f;
2215 meter_outL = 0.f;
2216 meter_outR = 0.f;
2219 void pulsator_audio_module::activate()
2221 is_active = true;
2222 lfoL.activate();
2223 lfoR.activate();
2224 params_changed();
2226 void pulsator_audio_module::deactivate()
2228 is_active = false;
2229 lfoL.deactivate();
2230 lfoR.deactivate();
2233 void pulsator_audio_module::params_changed()
2235 lfoL.set_params(*params[param_freq], *params[param_mode], 0.f, srate, *params[param_amount]);
2236 lfoR.set_params(*params[param_freq], *params[param_mode], *params[param_offset], srate, *params[param_amount]);
2237 clear_reset = false;
2238 if (*params[param_reset] >= 0.5) {
2239 clear_reset = true;
2240 lfoL.set_phase(0.f);
2241 lfoR.set_phase(0.f);
2245 void pulsator_audio_module::set_sample_rate(uint32_t sr)
2247 srate = sr;
2250 uint32_t pulsator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2252 bool bypass = *params[param_bypass] > 0.5f;
2253 uint32_t samples = numsamples + offset;
2254 if(bypass) {
2255 // everything bypassed
2256 while(offset < samples) {
2257 outs[0][offset] = ins[0][offset];
2258 outs[1][offset] = ins[1][offset];
2259 ++offset;
2261 // displays, too
2262 clip_inL = 0.f;
2263 clip_inR = 0.f;
2264 clip_outL = 0.f;
2265 clip_outR = 0.f;
2266 meter_inL = 0.f;
2267 meter_inR = 0.f;
2268 meter_outL = 0.f;
2269 meter_outR = 0.f;
2271 // LFO's should go on
2272 lfoL.advance(numsamples);
2273 lfoR.advance(numsamples);
2275 } else {
2277 clip_inL -= std::min(clip_inL, numsamples);
2278 clip_inR -= std::min(clip_inR, numsamples);
2279 clip_outL -= std::min(clip_outL, numsamples);
2280 clip_outR -= std::min(clip_outR, numsamples);
2281 meter_inL = 0.f;
2282 meter_inR = 0.f;
2283 meter_outL = 0.f;
2284 meter_outR = 0.f;
2286 // process
2287 while(offset < samples) {
2288 // cycle through samples
2289 float outL = 0.f;
2290 float outR = 0.f;
2291 float inL = ins[0][offset];
2292 float inR = ins[1][offset];
2293 // in level
2294 inR *= *params[param_level_in];
2295 inL *= *params[param_level_in];
2297 if(*params[param_mono] > 0.5) {
2298 inL = (inL + inR) * 0.5;
2299 inR = inL;
2301 float procL = inL;
2302 float procR = inR;
2304 procL *= (lfoL.get_value() * 0.5 + *params[param_amount] / 2);
2305 procR *= (lfoR.get_value() * 0.5 + *params[param_amount] / 2);
2307 outL = procL + inL * (1 - *params[param_amount]);
2308 outR = procR + inR * (1 - *params[param_amount]);
2310 outL *= *params[param_level_out];
2311 outR *= *params[param_level_out];
2313 // send to output
2314 outs[0][offset] = outL;
2315 outs[1][offset] = outR;
2317 // clip LED's
2318 if(inL > 1.f) {
2319 clip_inL = srate >> 3;
2321 if(inR > 1.f) {
2322 clip_inR = srate >> 3;
2324 if(outL > 1.f) {
2325 clip_outL = srate >> 3;
2327 if(outR > 1.f) {
2328 clip_outR = srate >> 3;
2330 // set up in / out meters
2331 if(inL > meter_inL) {
2332 meter_inL = inL;
2334 if(inR > meter_inR) {
2335 meter_inR = inR;
2337 if(outL > meter_outL) {
2338 meter_outL = outL;
2340 if(outR > meter_outR) {
2341 meter_outR = outR;
2344 // next sample
2345 ++offset;
2347 // advance lfo's
2348 lfoL.advance(1);
2349 lfoR.advance(1);
2350 } // cycle trough samples
2352 // draw meters
2353 if(params[param_clip_inL] != NULL) {
2354 *params[param_clip_inL] = clip_inL;
2356 if(params[param_clip_inR] != NULL) {
2357 *params[param_clip_inR] = clip_inR;
2359 if(params[param_clip_outL] != NULL) {
2360 *params[param_clip_outL] = clip_outL;
2362 if(params[param_clip_outR] != NULL) {
2363 *params[param_clip_outR] = clip_outR;
2366 if(params[param_meter_inL] != NULL) {
2367 *params[param_meter_inL] = meter_inL;
2369 if(params[param_meter_inR] != NULL) {
2370 *params[param_meter_inR] = meter_inR;
2372 if(params[param_meter_outL] != NULL) {
2373 *params[param_meter_outL] = meter_outL;
2375 if(params[param_meter_outR] != NULL) {
2376 *params[param_meter_outR] = meter_outR;
2378 // whatever has to be returned x)
2379 return outputs_mask;
2381 bool pulsator_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
2383 if (!is_active) {
2384 return false;
2385 } else if(index == param_freq) {
2386 if(subindex == 0) {
2387 context->set_source_rgba(0.35, 0.4, 0.2, 1);
2388 return lfoL.get_graph(data, points, context);
2390 if(subindex == 1) {
2391 context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
2392 return lfoR.get_graph(data, points, context);
2395 return false;
2397 bool pulsator_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
2399 if (!is_active) {
2400 return false;
2401 } else if(index == param_freq) {
2402 if(subindex == 0) {
2403 context->set_source_rgba(0.35, 0.4, 0.2, 1);
2404 return lfoL.get_dot(x, y, size, context);
2406 if(subindex == 1) {
2407 context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
2408 return lfoR.get_dot(x, y, size, context);
2410 return false;
2412 return false;
2414 bool pulsator_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
2416 if (index == param_freq && !subindex)
2418 pos = 0;
2419 vertical = false;
2420 return true;
2422 return false;