+ Gain reduction module: clearer authorship information
[calf.git] / src / modules_dsp.cpp
blob16694df0229e8719abaa26f85b0a33fd60e6a067
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 /// convert amplitude value to normalized grid-ish value (0dB = 0.5, 30dB = 1.0, -30 dB = 0.0, -60dB = -0.5, -90dB = -1.0)
36 static inline float dB_grid(float amp)
38 return log(amp) * (1.0 / log(256.0)) + 0.4;
41 template<class Fx>
42 static bool get_graph(Fx &fx, int subindex, float *data, int points)
44 for (int i = 0; i < points; i++)
46 typedef std::complex<double> cfloat;
47 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
48 data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate));
50 return true;
53 /// convert normalized grid-ish value back to amplitude value
54 static inline float dB_grid_inv(float pos)
56 return pow(256.0, pos - 0.4);
59 static void set_channel_color(cairo_iface *context, int channel)
61 if (channel & 1)
62 context->set_source_rgba(0.35, 0.4, 0.2, 1);
63 else
64 context->set_source_rgba(0.35, 0.4, 0.2, 0.5);
65 context->set_line_width(1.5);
68 static bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true)
70 if (subindex < 0 )
71 return false;
72 if (use_frequencies)
74 if (subindex < 28)
76 vertical = true;
77 if (subindex == 9) legend = "100 Hz";
78 if (subindex == 18) legend = "1 kHz";
79 if (subindex == 27) legend = "10 kHz";
80 float freq = 100;
81 if (subindex < 9)
82 freq = 10 * (subindex + 1);
83 else if (subindex < 18)
84 freq = 100 * (subindex - 9 + 1);
85 else if (subindex < 27)
86 freq = 1000 * (subindex - 18 + 1);
87 else
88 freq = 10000 * (subindex - 27 + 1);
89 pos = log(freq / 20.0) / log(1000);
90 if (!legend.empty())
91 context->set_source_rgba(0, 0, 0, 0.2);
92 else
93 context->set_source_rgba(0, 0, 0, 0.1);
94 return true;
96 subindex -= 28;
98 if (subindex >= 32)
99 return false;
100 float gain = 16.0 / (1 << subindex);
101 pos = dB_grid(gain);
102 if (pos < -1)
103 return false;
104 if (subindex != 4)
105 context->set_source_rgba(0, 0, 0, subindex & 1 ? 0.1 : 0.2);
106 if (!(subindex & 1))
108 std::stringstream ss;
109 ss << (24 - 6 * subindex) << " dB";
110 legend = ss.str();
112 vertical = false;
113 return true;
116 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
120 return get_freq_gridline(subindex, pos, vertical, legend, context);
123 int frequency_response_line_graph::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
125 subindex_graph = 0;
126 subindex_dot = 0;
127 subindex_gridline = generation ? INT_MAX : 0;
128 return 1;
131 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133 void flanger_audio_module::activate() {
134 left.reset();
135 right.reset();
136 last_r_phase = *params[par_stereo] * (1.f / 360.f);
137 left.reset_phase(0.f);
138 right.reset_phase(last_r_phase);
139 is_active = true;
142 void flanger_audio_module::set_sample_rate(uint32_t sr) {
143 srate = sr;
144 left.setup(sr);
145 right.setup(sr);
148 void flanger_audio_module::deactivate() {
149 is_active = false;
152 bool flanger_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
154 if (!is_active)
155 return false;
156 if (index == par_delay && subindex < 2)
158 set_channel_color(context, subindex);
159 return ::get_graph(*this, subindex, data, points);
161 return false;
164 float flanger_audio_module::freq_gain(int subindex, float freq, float srate)
166 return (subindex ? right : left).freq_gain(freq, srate);
169 ///////////////////////////////////////////////////////////////////////////////////////////////
171 void phaser_audio_module::set_sample_rate(uint32_t sr)
173 srate = sr;
174 left.setup(sr);
175 right.setup(sr);
178 void phaser_audio_module::activate()
180 is_active = true;
181 left.reset();
182 right.reset();
183 last_r_phase = *params[par_stereo] * (1.f / 360.f);
184 left.reset_phase(0.f);
185 right.reset_phase(last_r_phase);
188 void phaser_audio_module::deactivate()
190 is_active = false;
193 bool phaser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
195 if (!is_active)
196 return false;
197 if (subindex < 2)
199 set_channel_color(context, subindex);
200 return ::get_graph(*this, subindex, data, points);
202 return false;
205 float phaser_audio_module::freq_gain(int subindex, float freq, float srate)
207 return (subindex ? right : left).freq_gain(freq, srate);
210 bool phaser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
212 return get_freq_gridline(subindex, pos, vertical, legend, context);
215 ///////////////////////////////////////////////////////////////////////////////////////////////
217 void reverb_audio_module::activate()
219 reverb.reset();
222 void reverb_audio_module::deactivate()
226 void reverb_audio_module::set_sample_rate(uint32_t sr)
228 srate = sr;
229 reverb.setup(sr);
230 amount.set_sample_rate(sr);
233 ///////////////////////////////////////////////////////////////////////////////////////////////
235 bool filter_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
237 if (!is_active)
238 return false;
239 if (index == par_cutoff && !subindex) {
240 context->set_line_width(1.5);
241 return ::get_graph(*this, subindex, data, points);
243 return false;
246 int filter_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
248 if (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
250 old_cutoff = inertia_cutoff.get_last();
251 old_resonance = inertia_resonance.get_last();
252 old_mode = *params[par_mode];
253 last_generation++;
254 subindex_graph = 0;
255 subindex_dot = INT_MAX;
256 subindex_gridline = INT_MAX;
258 else {
259 subindex_graph = 0;
260 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
262 if (generation == last_calculated_generation)
263 subindex_graph = INT_MAX;
264 return last_generation;
268 ///////////////////////////////////////////////////////////////////////////////////////////////
270 bool filterclavier_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
272 if (!is_active || index != par_mode) {
273 return false;
275 if (!subindex) {
276 context->set_line_width(1.5);
277 return ::get_graph(*this, subindex, data, points);
279 return false;
282 ///////////////////////////////////////////////////////////////////////////////////////////////
284 rotary_speaker_audio_module::rotary_speaker_audio_module()
286 mwhl_value = hold_value = 0.f;
287 phase_h = phase_l = 0.f;
288 aspeed_l = 1.f;
289 aspeed_h = 1.f;
290 dspeed = 0.f;
293 void rotary_speaker_audio_module::set_sample_rate(uint32_t sr)
295 srate = sr;
296 setup();
299 void rotary_speaker_audio_module::setup()
301 crossover1l.set_lp_rbj(800.f, 0.7, (float)srate);
302 crossover1r.set_lp_rbj(800.f, 0.7, (float)srate);
303 crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
304 crossover2r.set_hp_rbj(800.f, 0.7, (float)srate);
307 void rotary_speaker_audio_module::activate()
309 phase_h = phase_l = 0.f;
310 maspeed_h = maspeed_l = 0.f;
311 setup();
314 void rotary_speaker_audio_module::deactivate()
318 void rotary_speaker_audio_module::control_change(int ctl, int val)
320 if (vibrato_mode == 3 && ctl == 64)
322 hold_value = val / 127.f;
323 set_vibrato();
324 return;
326 if (vibrato_mode == 4 && ctl == 1)
328 mwhl_value = val / 127.f;
329 set_vibrato();
330 return;
334 ///////////////////////////////////////////////////////////////////////////////////////////////
336 void multichorus_audio_module::activate()
338 is_active = true;
339 params_changed();
342 void multichorus_audio_module::deactivate()
344 is_active = false;
347 void multichorus_audio_module::set_sample_rate(uint32_t sr) {
348 srate = sr;
349 left.setup(sr);
350 right.setup(sr);
353 bool multichorus_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
355 if (!is_active)
356 return false;
357 int nvoices = (int)*params[par_voices];
358 if (index == par_delay && subindex < 3)
360 if (subindex < 2)
361 set_channel_color(context, subindex);
362 else {
363 context->set_source_rgba(0.35, 0.4, 0.2);
364 context->set_line_width(1.0);
366 return ::get_graph(*this, subindex, data, points);
368 if (index == par_rate && subindex < nvoices) {
369 sine_multi_lfo<float, 8> &lfo = left.lfo;
370 for (int i = 0; i < points; i++) {
371 float phase = i * 2 * M_PI / points;
372 // original -65536 to 65535 value
373 float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(phase) + 1)/ 8192.0) - 65536;
374 // scale to -1..1
375 data[i] = orig / 65536.0;
377 return true;
379 return false;
382 bool multichorus_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
384 int voice = subindex >> 1;
385 int nvoices = (int)*params[par_voices];
386 if ((index != par_rate && index != par_depth) || voice >= nvoices)
387 return false;
389 float unit = (1 - *params[par_overlap]);
390 float scw = 1 + unit * (nvoices - 1);
391 set_channel_color(context, subindex);
392 sine_multi_lfo<float, 8> &lfo = (subindex & 1 ? right : left).lfo;
393 if (index == par_rate)
395 x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
396 y = 0.95 * sin(x * 2 * M_PI);
397 y = (voice * unit + (y + 1) / 2) / scw * 2 - 1;
399 else
401 double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
402 x = 0.5 + 0.5 * sin(ph * 2 * M_PI);
403 y = subindex & 1 ? -0.75 : 0.75;
404 x = (voice * unit + x) / scw;
406 return true;
409 bool multichorus_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
411 if (index == par_rate && !subindex)
413 pos = 0;
414 vertical = false;
415 return true;
417 if (index == par_delay)
418 return get_freq_gridline(subindex, pos, vertical, legend, context);
419 return false;
422 float multichorus_audio_module::freq_gain(int subindex, float freq, float srate)
424 if (subindex == 2)
425 return *params[par_amount] * left.post.freq_gain(freq, srate);
426 return (subindex ? right : left).freq_gain(freq, srate);
429 ///////////////////////////////////////////////////////////////////////////////////////////////
431 compressor_audio_module::compressor_audio_module()
433 is_active = false;
434 srate = 0;
435 last_generation = 0;
438 void compressor_audio_module::activate()
440 is_active = true;
441 linSlope = 0.f;
442 peak = 0.f;
443 clip = 0.f;
446 void compressor_audio_module::deactivate()
448 is_active = false;
451 void compressor_audio_module::set_sample_rate(uint32_t sr)
453 srate = sr;
454 awL.set(sr);
455 awR.set(sr);
458 bool compressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
460 if (!is_active)
461 return false;
462 if (subindex > 1) // 1
463 return false;
464 for (int i = 0; i < points; i++)
466 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
467 float output = output_level(input);
468 if (subindex == 0)
469 data[i] = dB_grid(input);
470 else
471 data[i] = dB_grid(output);
473 if (subindex == (*params[param_bypass] > 0.5f ? 1 : 0))
474 context->set_source_rgba(0.35, 0.4, 0.2, 0.3);
475 else {
476 context->set_source_rgba(0.35, 0.4, 0.2, 1);
477 context->set_line_width(2);
479 return true;
482 bool compressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
484 if (!is_active)
485 return false;
486 if (!subindex)
488 bool rms = *params[param_detection] == 0;
489 float det = rms ? sqrt(detected) : detected;
490 x = 0.5 + 0.5 * dB_grid(det);
491 y = dB_grid(*params[param_bypass] > 0.5f ? det : output_level(det));
492 return *params[param_bypass] > 0.5f ? false : true;
494 return false;
497 bool compressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
499 bool tmp;
500 vertical = (subindex & 1) != 0;
501 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
502 if (result && vertical) {
503 if ((subindex & 4) && !legend.empty()) {
504 legend = "";
506 else {
507 size_t pos = legend.find(" dB");
508 if (pos != std::string::npos)
509 legend.erase(pos);
511 pos = 0.5 + 0.5 * pos;
513 return result;
516 // In case of doubt: this function is written by Thor. I just moved it to this file, damaging
517 // the output of "git annotate" in the process.
518 uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
520 bool bypass = *params[param_bypass] > 0.5f;
522 if(bypass) {
523 numsamples += offset;
524 while(offset < numsamples) {
525 outs[0][offset] = ins[0][offset];
526 outs[1][offset] = ins[1][offset];
527 ++offset;
530 if(params[param_compression] != NULL) {
531 *params[param_compression] = 1.f;
534 if(params[param_clip] != NULL) {
535 *params[param_clip] = 0.f;
538 if(params[param_peak] != NULL) {
539 *params[param_peak] = 0.f;
542 return inputs_mask;
545 bool rms = *params[param_detection] == 0;
546 bool average = *params[param_stereo_link] == 0;
547 int aweighting = fastf2i_drm(*params[param_aweighting]);
548 float linThreshold = *params[param_threshold];
549 ratio = *params[param_ratio];
550 float attack = *params[param_attack];
551 float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
552 float release = *params[param_release];
553 float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
554 makeup = *params[param_makeup];
555 knee = *params[param_knee];
557 float linKneeSqrt = sqrt(knee);
558 linKneeStart = linThreshold / linKneeSqrt;
559 adjKneeStart = linKneeStart*linKneeStart;
560 float linKneeStop = linThreshold * linKneeSqrt;
562 threshold = log(linThreshold);
563 kneeStart = log(linKneeStart);
564 kneeStop = log(linKneeStop);
565 compressedKneeStop = (kneeStop - threshold) / ratio + threshold;
567 if (aweighting >= 2)
569 bpL.set_highshelf_rbj(5000, 0.707, 10 << (aweighting - 2), srate);
570 bpR.copy_coeffs(bpL);
571 bpL.sanitize();
572 bpR.sanitize();
575 numsamples += offset;
577 float compression = 1.f;
578 peak = 0.f;
579 clip -= std::min(clip, numsamples);
581 while(offset < numsamples) {
582 float left = ins[0][offset] * *params[param_input];
583 float right = ins[1][offset] * *params[param_input];
585 if(aweighting == 1) {
586 left = awL.process(left);
587 right = awR.process(right);
589 else if(aweighting >= 2) {
590 left = bpL.process(left);
591 right = bpR.process(right);
594 float absample = average ? (fabs(left) + fabs(right)) * 0.5f : std::max(fabs(left), fabs(right));
595 if(rms) absample *= absample;
597 linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
599 float gain = 1.f;
601 if(linSlope > 0.f) {
602 gain = output_gain(linSlope, rms);
605 compression = gain;
606 gain *= makeup;
608 float outL = ins[0][offset] * gain * *params[param_input];
609 float outR = ins[1][offset] * gain * *params[param_input];
611 outs[0][offset] = outL;
612 outs[1][offset] = outR;
614 ++offset;
616 float maxLR = std::max(fabs(outL), fabs(outR));
617 if(maxLR > peak)
618 peak = maxLR;
620 if(peak > 1.f) clip = srate >> 3; /* blink clip LED for 125 ms */
623 detected = linSlope;
625 if(params[param_compression] != NULL) {
626 *params[param_compression] = compression;
629 if(params[param_clip] != NULL) {
630 *params[param_clip] = clip;
633 if(params[param_peak] != NULL) {
634 *params[param_peak] = peak;
637 return inputs_mask;
641 /// Multibandcompressor by Markus Schmidt
643 /// This module splits the signal in four different bands
644 /// and sends them through multiple filters (implemented by
645 /// Krzysztof). They are processed by a compressing routine
646 /// (implemented by Thor) afterwards and summed up to the
647 /// final output again.
648 ///////////////////////////////////////////////////////////////////////////////////////////////
650 multibandcompressor_audio_module::multibandcompressor_audio_module()
652 is_active = false;
653 srate = 0;
654 // zero all displays
655 clip_inL = 0.f;
656 clip_inR = 0.f;
657 clip_outL = 0.f;
658 clip_outR = 0.f;
659 meter_inL = 0.f;
660 meter_inR = 0.f;
661 meter_outL = 0.f;
662 meter_outR = 0.f;
665 void multibandcompressor_audio_module::activate()
667 is_active = true;
668 // set all filters and strips
669 params_changed();
670 // activate all strips
671 for (int j = 0; j < strips; j ++) {
672 strip[j].activate();
673 strip[j].id = j;
677 void multibandcompressor_audio_module::deactivate()
679 is_active = false;
680 // deactivate all strips
681 for (int j = 0; j < strips; j ++) {
682 strip[j].deactivate();
686 void multibandcompressor_audio_module::params_changed()
688 // set the params of all filters
689 if(*params[param_freq0] != freq_old[0] or *params[param_sep0] != sep_old[0] or *params[param_q0] != q_old[0]) {
690 lpL0.set_lp_rbj((float)(*params[param_freq0] * (1 - *params[param_sep0])), *params[param_q0], (float)srate);
691 lpR0.copy_coeffs(lpL0);
692 hpL0.set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate);
693 hpR0.copy_coeffs(hpL0);
694 freq_old[0] = *params[param_freq0];
695 sep_old[0] = *params[param_sep2];
696 q_old[0] = *params[param_q2];
698 if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1]) {
699 lpL1.set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate);
700 lpR1.copy_coeffs(lpL1);
701 hpL1.set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate);
702 hpR1.copy_coeffs(hpL1);
703 freq_old[1] = *params[param_freq1];
704 sep_old[1] = *params[param_sep2];
705 q_old[1] = *params[param_q2];
707 if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2]) {
708 lpL2.set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate);
709 lpR2.copy_coeffs(lpL2);
710 hpL2.set_hp_rbj((float)(*params[param_freq2] * (1 + *params[param_sep2])), *params[param_q2], (float)srate);
711 hpR2.copy_coeffs(hpL2);
712 freq_old[2] = *params[param_freq2];
713 sep_old[2] = *params[param_sep2];
714 q_old[2] = *params[param_q2];
716 // set the params of all strips
717 for (int j = 0; j < strips; j ++) {
718 switch (j) {
719 case 0:
720 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]);
721 break;
722 case 1:
723 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]);
724 break;
725 case 2:
726 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]);
727 break;
728 case 3:
729 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]);
730 break;
735 void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
737 srate = sr;
738 // set srate of all strips
739 for (int j = 0; j < strips; j ++) {
740 strip[j].set_sample_rate(srate);
744 uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
746 bool bypass = *params[param_bypass] > 0.5f;
747 numsamples += offset;
748 if(bypass) {
749 // everything bypassed
750 while(offset < numsamples) {
751 outs[0][offset] = ins[0][offset];
752 outs[1][offset] = ins[1][offset];
753 ++offset;
755 // displays, too
756 clip_inL = 0.f;
757 clip_inR = 0.f;
758 clip_outL = 0.f;
759 clip_outR = 0.f;
760 meter_inL = 0.f;
761 meter_inR = 0.f;
762 meter_outL = 0.f;
763 meter_outR = 0.f;
764 } else {
765 // process all strips
767 // determine mute state of strips
768 mute[0] = *params[param_mute0] > 0.f ? true : false;
769 mute[1] = *params[param_mute1] > 0.f ? true : false;
770 mute[2] = *params[param_mute2] > 0.f ? true : false;
771 mute[3] = *params[param_mute3] > 0.f ? true : false;
773 // let meters fall a bit
774 clip_inL -= std::min(clip_inL, numsamples);
775 clip_inR -= std::min(clip_inR, numsamples);
776 clip_outL -= std::min(clip_outL, numsamples);
777 clip_outR -= std::min(clip_outR, numsamples);
778 meter_inL = 0.f;
779 meter_inR = 0.f;
780 meter_outL = 0.f;
781 meter_outR = 0.f;
782 while(offset < numsamples) {
783 // cycle through samples
784 float inL = ins[0][offset];
785 float inR = ins[1][offset];
786 // in level
787 inR *= *params[param_level_in];
788 inL *= *params[param_level_in];
789 // out vars
790 float outL = 0.f;
791 float outR = 0.f;
792 for (int i = 0; i < strips; i ++) {
793 // cycle trough strips
794 if (!mute[i]) {
795 // strip unmuted
796 float left = inL;
797 float right = inR;
798 // send trough filters
799 switch (i) {
800 case 0:
801 left = lpL0.process(left);
802 right = lpR0.process(right);
803 lpL0.sanitize();
804 lpR0.sanitize();
805 break;
806 case 1:
807 left = lpL1.process(left);
808 right = lpR1.process(right);
809 left = hpL0.process(left);
810 right = hpR0.process(right);
811 lpL1.sanitize();
812 lpR1.sanitize();
813 hpL0.sanitize();
814 hpR0.sanitize();
815 break;
816 case 2:
817 left = lpL2.process(left);
818 right = lpR2.process(right);
819 left = hpL1.process(left);
820 right = hpR1.process(right);
821 lpL2.sanitize();
822 lpR2.sanitize();
823 hpL1.sanitize();
824 hpR1.sanitize();
825 break;
826 case 3:
827 left = hpL2.process(left);
828 right = hpR2.process(right);
829 hpL2.sanitize();
830 hpR2.sanitize();
831 break;
833 // process gain reduction
834 strip[i].process(left, right);
835 // sum up output
836 outL += left;
837 outR += right;
838 } else {
839 // strip muted
844 } // process single strip
846 // even out filters gain reduction
847 // 3dB - levelled manually (based on default sep and q settings)
848 outL *= 1.414213562;
849 outR *= 1.414213562;
851 // out level
852 outL *= *params[param_level_out];
853 outR *= *params[param_level_out];
855 // send to output
856 outs[0][offset] = outL;
857 outs[1][offset] = outR;
859 // clip LED's
860 if(inL > 1.f) {
861 clip_inL = srate >> 3;
863 if(inR > 1.f) {
864 clip_inR = srate >> 3;
866 if(outL > 1.f) {
867 clip_outL = srate >> 3;
869 if(outR > 1.f) {
870 clip_outR = srate >> 3;
872 // set up in / out meters
873 if(inL > meter_inL) {
874 meter_inL = inL;
876 if(inR > meter_inR) {
877 meter_inR = inR;
879 if(outL > meter_outL) {
880 meter_outL = outL;
882 if(outR > meter_outR) {
883 meter_outR = outR;
885 // next sample
886 ++offset;
887 } // cycle trough samples
889 } // process all strips (no bypass)
891 // draw meters
892 if(params[param_clip_inL] != NULL) {
893 *params[param_clip_inL] = clip_inL;
895 if(params[param_clip_inR] != NULL) {
896 *params[param_clip_inR] = clip_inR;
898 if(params[param_clip_outL] != NULL) {
899 *params[param_clip_outL] = clip_outL;
901 if(params[param_clip_outR] != NULL) {
902 *params[param_clip_outR] = clip_outR;
905 if(params[param_meter_inL] != NULL) {
906 *params[param_meter_inL] = meter_inL;
908 if(params[param_meter_inR] != NULL) {
909 *params[param_meter_inR] = meter_inR;
911 if(params[param_meter_outL] != NULL) {
912 *params[param_meter_outL] = meter_outL;
914 if(params[param_meter_outR] != NULL) {
915 *params[param_meter_outR] = meter_outR;
917 // draw strip meters
918 if(bypass > 0.5f) {
919 if(params[param_compression0] != NULL) {
920 *params[param_compression0] = 1.0f;
922 if(params[param_compression1] != NULL) {
923 *params[param_compression1] = 1.0f;
925 if(params[param_compression2] != NULL) {
926 *params[param_compression2] = 1.0f;
928 if(params[param_compression3] != NULL) {
929 *params[param_compression3] = 1.0f;
932 if(params[param_output0] != NULL) {
933 *params[param_output0] = 0.0f;
935 if(params[param_output1] != NULL) {
936 *params[param_output1] = 0.0f;
938 if(params[param_output2] != NULL) {
939 *params[param_output2] = 0.0f;
941 if(params[param_output3] != NULL) {
942 *params[param_output3] = 0.0f;
944 } else {
945 if(params[param_compression0] != NULL) {
946 *params[param_compression0] = strip[0].get_comp_level();
948 if(params[param_compression1] != NULL) {
949 *params[param_compression1] = strip[1].get_comp_level();
951 if(params[param_compression2] != NULL) {
952 *params[param_compression2] = strip[2].get_comp_level();
954 if(params[param_compression3] != NULL) {
955 *params[param_compression3] = strip[3].get_comp_level();
958 if(params[param_output0] != NULL) {
959 *params[param_output0] = strip[0].get_output_level();
961 if(params[param_output1] != NULL) {
962 *params[param_output1] = strip[1].get_output_level();
964 if(params[param_output2] != NULL) {
965 *params[param_output2] = strip[2].get_output_level();
967 if(params[param_output3] != NULL) {
968 *params[param_output3] = strip[3].get_output_level();
971 // whatever has to be returned x)
972 return outputs_mask;
974 bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
976 // let's handle by the corresponding strip
977 switch (index) {
978 case param_compression0:
979 return strip[0].get_graph(subindex, data, points, context);
980 break;
981 case param_compression1:
982 return strip[1].get_graph(subindex, data, points, context);
983 break;
984 case param_compression2:
985 return strip[2].get_graph(subindex, data, points, context);
986 break;
987 case param_compression3:
988 return strip[3].get_graph(subindex, data, points, context);
989 break;
991 return false;
994 bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
996 // let's handle by the corresponding strip
997 switch (index) {
998 case param_compression0:
999 return strip[0].get_dot(subindex, x, y, size, context);
1000 break;
1001 case param_compression1:
1002 return strip[1].get_dot(subindex, x, y, size, context);
1003 break;
1004 case param_compression2:
1005 return strip[2].get_dot(subindex, x, y, size, context);
1006 break;
1007 case param_compression3:
1008 return strip[3].get_dot(subindex, x, y, size, context);
1009 break;
1011 return false;
1014 bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1016 // let's handle by the corresponding strip
1017 switch (index) {
1018 case param_compression0:
1019 return strip[0].get_gridline(subindex, pos, vertical, legend, context);
1020 break;
1021 case param_compression1:
1022 return strip[1].get_gridline(subindex, pos, vertical, legend, context);
1023 break;
1024 case param_compression2:
1025 return strip[2].get_gridline(subindex, pos, vertical, legend, context);
1026 break;
1027 case param_compression3:
1028 return strip[3].get_gridline(subindex, pos, vertical, legend, context);
1029 break;
1031 return false;
1034 int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1036 // let's handle by the corresponding strip
1037 switch (index) {
1038 case param_compression0:
1039 return strip[0].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1040 break;
1041 case param_compression1:
1042 return strip[1].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1043 break;
1044 case param_compression2:
1045 return strip[2].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1046 break;
1047 case param_compression3:
1048 return strip[3].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1049 break;
1051 return 0;
1054 /// Sidecain Compressor by Markus Schmidt
1056 /// This module splits the signal in a sidechain- and a process signal.
1057 /// The sidechain is processed through Krzystofs filters and compresses
1058 /// the process signal via Thor's compression routine afterwards.
1059 ///////////////////////////////////////////////////////////////////////////////////////////////
1061 sidechaincompressor_audio_module::sidechaincompressor_audio_module()
1063 is_active = false;
1064 srate = 0;
1065 last_generation = 0;
1068 void sidechaincompressor_audio_module::activate()
1070 is_active = true;
1071 // set all filters and strips
1072 compressor.activate();
1073 params_changed();
1074 meter_in = 0.f;
1075 meter_out = 0.f;
1076 clip_in = 0.f;
1077 clip_out = 0.f;
1079 void sidechaincompressor_audio_module::deactivate()
1081 is_active = false;
1082 compressor.deactivate();
1085 void sidechaincompressor_audio_module::params_changed()
1087 // set the params of all filters
1088 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1089 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1090 or *params[param_sc_mode] != sc_mode) {
1091 float q = 0.707;
1092 switch ((int)*params[param_sc_mode]) {
1093 default:
1094 case WIDEBAND:
1095 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1096 f1R.copy_coeffs(f1L);
1097 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1098 f2R.copy_coeffs(f2L);
1099 f1_active = 0.f;
1100 f2_active = 0.f;
1101 break;
1102 case DEESSER_WIDE:
1103 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1104 f1R.copy_coeffs(f1L);
1105 f2L.set_hp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1106 f2R.copy_coeffs(f2L);
1107 f1_active = 0.5f;
1108 f2_active = 1.f;
1109 break;
1110 case DEESSER_SPLIT:
1111 f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
1112 f1R.copy_coeffs(f1L);
1113 f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
1114 f2R.copy_coeffs(f2L);
1115 f1_active = 0.f;
1116 f2_active = 1.f;
1117 break;
1118 case DERUMBLER_WIDE:
1119 f1L.set_lp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1120 f1R.copy_coeffs(f1L);
1121 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1122 f2R.copy_coeffs(f2L);
1123 f1_active = 1.f;
1124 f2_active = 0.5f;
1125 break;
1126 case DERUMBLER_SPLIT:
1127 f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
1128 f1R.copy_coeffs(f1L);
1129 f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
1130 f2R.copy_coeffs(f2L);
1131 f1_active = 1.f;
1132 f2_active = 0.f;
1133 break;
1134 case WEIGHTED_1:
1135 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1136 f1R.copy_coeffs(f1L);
1137 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1138 f2R.copy_coeffs(f2L);
1139 f1_active = 0.5f;
1140 f2_active = 0.5f;
1141 break;
1142 case WEIGHTED_2:
1143 f1L.set_lowshelf_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1144 f1R.copy_coeffs(f1L);
1145 f2L.set_peakeq_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1146 f2R.copy_coeffs(f2L);
1147 f1_active = 0.5f;
1148 f2_active = 0.5f;
1149 break;
1150 case WEIGHTED_3:
1151 f1L.set_peakeq_rbj((float)*params[param_f1_freq], q, *params[param_f1_level], (float)srate);
1152 f1R.copy_coeffs(f1L);
1153 f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1154 f2R.copy_coeffs(f2L);
1155 f1_active = 0.5f;
1156 f2_active = 0.5f;
1157 break;
1158 case BANDPASS_1:
1159 f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1160 f1R.copy_coeffs(f1L);
1161 f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
1162 f2R.copy_coeffs(f2L);
1163 f1_active = 1.f;
1164 f2_active = 0.f;
1165 break;
1166 case BANDPASS_2:
1167 f1L.set_hp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
1168 f1R.copy_coeffs(f1L);
1169 f2L.set_lp_rbj((float)*params[param_f2_freq], q, (float)srate, *params[param_f2_level]);
1170 f2R.copy_coeffs(f2L);
1171 f1_active = 1.f;
1172 f2_active = 1.f;
1173 break;
1175 f1_freq_old = *params[param_f1_freq];
1176 f1_level_old = *params[param_f1_level];
1177 f2_freq_old = *params[param_f2_freq];
1178 f2_level_old = *params[param_f2_level];
1179 sc_mode = (CalfScModes)*params[param_sc_mode];
1181 // light LED's
1182 if(params[param_f1_active] != NULL) {
1183 *params[param_f1_active] = f1_active;
1185 if(params[param_f2_active] != NULL) {
1186 *params[param_f2_active] = f2_active;
1188 // and set the compressor module
1189 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);
1192 void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr)
1194 srate = sr;
1195 compressor.set_sample_rate(srate);
1198 uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1200 bool bypass = *params[param_bypass] > 0.5f;
1201 numsamples += offset;
1202 if(bypass) {
1203 // everything bypassed
1204 while(offset < numsamples) {
1205 outs[0][offset] = ins[0][offset];
1206 outs[1][offset] = ins[1][offset];
1207 ++offset;
1209 // displays, too
1210 clip_in = 0.f;
1211 clip_out = 0.f;
1212 meter_in = 0.f;
1213 meter_out = 0.f;
1214 } else {
1215 // process
1217 clip_in -= std::min(clip_in, numsamples);
1218 clip_out -= std::min(clip_out, numsamples);
1220 while(offset < numsamples) {
1221 // cycle through samples
1222 float outL = 0.f;
1223 float outR = 0.f;
1224 float inL = ins[0][offset];
1225 float inR = ins[1][offset];
1226 // in level
1227 inR *= *params[param_level_in];
1228 inL *= *params[param_level_in];
1231 float leftAC = inL;
1232 float rightAC = inR;
1233 float leftSC = inL;
1234 float rightSC = inR;
1235 float leftMC = inL;
1236 float rightMC = inR;
1238 switch ((int)*params[param_sc_mode]) {
1239 default:
1240 case WIDEBAND:
1241 compressor.process(leftAC, rightAC, leftSC, rightSC);
1242 break;
1243 case DEESSER_WIDE:
1244 case DERUMBLER_WIDE:
1245 case WEIGHTED_1:
1246 case WEIGHTED_2:
1247 case WEIGHTED_3:
1248 case BANDPASS_2:
1249 leftSC = f2L.process(f1L.process(leftSC));
1250 rightSC = f2R.process(f1R.process(rightSC));
1251 leftMC = leftSC;
1252 rightMC = rightSC;
1253 compressor.process(leftAC, rightAC, leftSC, rightSC);
1254 break;
1255 case DEESSER_SPLIT:
1256 leftSC = f2L.process(leftSC);
1257 rightSC = f2R.process(rightSC);
1258 leftMC = leftSC;
1259 rightMC = rightSC;
1260 compressor.process(leftSC, rightSC, leftSC, rightSC);
1261 leftAC = f1L.process(leftAC);
1262 rightAC = f1R.process(rightAC);
1263 leftAC += leftSC;
1264 rightAC += rightSC;
1265 break;
1266 case DERUMBLER_SPLIT:
1267 leftSC = f1L.process(leftSC);
1268 rightSC = f1R.process(rightSC);
1269 leftMC = leftSC;
1270 rightMC = rightSC;
1271 compressor.process(leftSC, rightSC, leftSC, rightSC);
1272 leftAC = f2L.process(leftAC);
1273 rightAC = f2R.process(rightAC);
1274 leftAC += leftSC;
1275 rightAC += rightSC;
1276 break;
1277 case BANDPASS_1:
1278 leftSC = f1L.process(leftSC);
1279 rightSC = f1R.process(rightSC);
1280 leftMC = leftSC;
1281 rightMC = rightSC;
1282 compressor.process(leftAC, rightAC, leftSC, rightSC);
1283 break;
1286 if(*params[param_sc_listen] > 0.f) {
1287 outL = leftMC;
1288 outR = rightMC;
1289 } else {
1290 outL = leftAC;
1291 outR = rightAC;
1294 // send to output
1295 outs[0][offset] = outL;
1296 outs[1][offset] = outR;
1298 // clip LED's
1299 if(std::max(fabs(inL), fabs(inR)) > 1.f) {
1300 clip_in = srate >> 3;
1302 if(std::max(fabs(outL), fabs(outR)) > 1.f) {
1303 clip_out = srate >> 3;
1305 // rise up out meter
1306 meter_in = std::max(fabs(inL), fabs(inR));;
1307 meter_out = std::max(fabs(outL), fabs(outR));;
1309 // next sample
1310 ++offset;
1311 } // cycle trough samples
1312 f1L.sanitize();
1313 f1R.sanitize();
1314 f2L.sanitize();
1315 f2R.sanitize();
1318 // draw meters
1319 if(params[param_clip_in] != NULL) {
1320 *params[param_clip_in] = clip_in;
1322 if(params[param_clip_out] != NULL) {
1323 *params[param_clip_out] = clip_out;
1325 if(params[param_meter_in] != NULL) {
1326 *params[param_meter_in] = meter_in;
1328 if(params[param_meter_out] != NULL) {
1329 *params[param_meter_out] = meter_out;
1331 // draw strip meter
1332 if(bypass > 0.5f) {
1333 if(params[param_compression] != NULL) {
1334 *params[param_compression] = 1.0f;
1336 } else {
1337 if(params[param_compression] != NULL) {
1338 *params[param_compression] = compressor.get_comp_level();
1341 // whatever has to be returned x)
1342 return outputs_mask;
1344 bool sidechaincompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
1346 if (!is_active)
1347 return false;
1348 if (index == param_f1_freq && !subindex) {
1349 context->set_line_width(1.5);
1350 return ::get_graph(*this, subindex, data, points);
1351 } else if(index == param_compression) {
1352 return compressor.get_graph(subindex, data, points, context);
1354 return false;
1357 bool sidechaincompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
1359 if (!is_active)
1360 return false;
1361 if (index == param_compression) {
1362 return compressor.get_dot(subindex, x, y, size, context);
1364 return false;
1367 bool sidechaincompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1369 if (!is_active)
1370 return false;
1371 if (index == param_compression) {
1372 return compressor.get_gridline(subindex, pos, vertical, legend, context);
1373 } else {
1374 return get_freq_gridline(subindex, pos, vertical, legend, context);
1376 // return false;
1379 int sidechaincompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1381 if (!is_active)
1382 return false;
1383 if(index == param_compression) {
1384 return compressor.get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
1385 } else {
1386 // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
1387 if (*params[param_f1_freq] != f1_freq_old1
1388 or *params[param_f2_freq] != f2_freq_old1
1389 or *params[param_f1_level] != f1_level_old1
1390 or *params[param_f2_level] != f2_level_old1
1391 or *params[param_sc_mode] !=sc_mode_old1)
1393 f1_freq_old1 = *params[param_f1_freq];
1394 f2_freq_old1 = *params[param_f2_freq];
1395 f1_level_old1 = *params[param_f1_level];
1396 f2_level_old1 = *params[param_f2_level];
1397 sc_mode_old1 = (CalfScModes)*params[param_sc_mode];
1398 last_generation++;
1399 subindex_graph = 0;
1400 subindex_dot = INT_MAX;
1401 subindex_gridline = INT_MAX;
1403 else {
1404 subindex_graph = 0;
1405 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
1407 if (generation == last_calculated_generation)
1408 subindex_graph = INT_MAX;
1409 return last_generation;
1411 return false;
1414 /// Deesser by Markus Schmidt
1416 /// This module splits the signal in a sidechain- and a process signal.
1417 /// The sidechain is processed through Krzystofs filters and compresses
1418 /// the process signal via Thor's compression routine afterwards.
1419 ///////////////////////////////////////////////////////////////////////////////////////////////
1421 deesser_audio_module::deesser_audio_module()
1423 is_active = false;
1424 srate = 0;
1425 last_generation = 0;
1428 void deesser_audio_module::activate()
1430 is_active = true;
1431 // set all filters and strips
1432 compressor.activate();
1433 params_changed();
1434 detected = 0.f;
1435 detected_led = 0.f;
1436 clip_out = 0.f;
1438 void deesser_audio_module::deactivate()
1440 is_active = false;
1441 compressor.deactivate();
1444 void deesser_audio_module::params_changed()
1446 // set the params of all filters
1447 if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
1448 or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
1449 or *params[param_f2_q] != f2_q_old) {
1450 float q = 0.707;
1452 hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
1453 hpR.copy_coeffs(hpL);
1454 lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
1455 lpR.copy_coeffs(lpL);
1456 pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
1457 pR.copy_coeffs(pL);
1458 f1_freq_old = *params[param_f1_freq];
1459 f1_level_old = *params[param_f1_level];
1460 f2_freq_old = *params[param_f2_freq];
1461 f2_level_old = *params[param_f2_level];
1462 f2_q_old = *params[param_f2_q];
1464 // and set the compressor module
1465 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);
1468 void deesser_audio_module::set_sample_rate(uint32_t sr)
1470 srate = sr;
1471 compressor.set_sample_rate(srate);
1474 uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1476 bool bypass = *params[param_bypass] > 0.5f;
1477 numsamples += offset;
1478 if(bypass) {
1479 // everything bypassed
1480 while(offset < numsamples) {
1481 outs[0][offset] = ins[0][offset];
1482 outs[1][offset] = ins[1][offset];
1483 ++offset;
1485 // displays, too
1486 clip_out = 0.f;
1487 detected = 0.f;
1488 detected_led = 0.f;
1489 } else {
1490 // process
1492 detected_led -= std::min(detected_led, numsamples);
1493 clip_led -= std::min(clip_led, numsamples);
1495 while(offset < numsamples) {
1496 // cycle through samples
1497 float outL = 0.f;
1498 float outR = 0.f;
1499 float inL = ins[0][offset];
1500 float inR = ins[1][offset];
1503 float leftAC = inL;
1504 float rightAC = inR;
1505 float leftSC = inL;
1506 float rightSC = inR;
1507 float leftRC = inL;
1508 float rightRC = inR;
1509 float leftMC = inL;
1510 float rightMC = inR;
1512 leftSC = pL.process(hpL.process(leftSC));
1513 rightSC = pR.process(hpR.process(rightSC));
1514 leftMC = leftSC;
1515 rightMC = rightSC;
1517 switch ((int)*params[param_mode]) {
1518 default:
1519 case WIDE:
1520 compressor.process(leftAC, rightAC, leftSC, rightSC);
1521 break;
1522 case SPLIT:
1523 hpL.sanitize();
1524 hpR.sanitize();
1525 leftRC = hpL.process(leftRC);
1526 rightRC = hpR.process(rightRC);
1527 compressor.process(leftRC, rightRC, leftSC, rightSC);
1528 leftAC = lpL.process(leftAC);
1529 rightAC = lpR.process(rightAC);
1530 leftAC += leftRC;
1531 rightAC += rightRC;
1532 break;
1535 if(*params[param_sc_listen] > 0.f) {
1536 outL = leftMC;
1537 outR = rightMC;
1538 } else {
1539 outL = leftAC;
1540 outR = rightAC;
1543 // send to output
1544 outs[0][offset] = outL;
1545 outs[1][offset] = outR;
1547 if(std::max(fabs(leftSC), fabs(rightSC)) > 0.1) {
1548 detected_led = srate >> 3;
1550 if(std::max(fabs(leftAC), fabs(rightAC)) > 1.f) {
1551 clip_led = srate >> 3;
1553 if(clip_led > 0) {
1554 clip_out = 1.f;
1555 } else {
1556 clip_out = std::max(fabs(outL), fabs(outR));
1558 detected = std::max(fabs(leftMC), fabs(rightMC));
1560 // next sample
1561 ++offset;
1562 } // cycle trough samples
1563 hpL.sanitize();
1564 hpR.sanitize();
1565 lpL.sanitize();
1566 lpR.sanitize();
1567 pL.sanitize();
1568 pR.sanitize();
1570 // draw meters
1571 if(params[param_detected_led] != NULL) {
1572 *params[param_detected_led] = detected_led;
1574 if(params[param_clip_out] != NULL) {
1575 *params[param_clip_out] = clip_out;
1577 if(params[param_detected] != NULL) {
1578 *params[param_detected] = detected;
1580 // draw strip meter
1581 if(bypass > 0.5f) {
1582 if(params[param_compression] != NULL) {
1583 *params[param_compression] = 1.0f;
1585 } else {
1586 if(params[param_compression] != NULL) {
1587 *params[param_compression] = compressor.get_comp_level();
1590 // whatever has to be returned x)
1591 return outputs_mask;
1593 bool deesser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
1595 if (!is_active)
1596 return false;
1597 if (index == param_f1_freq && !subindex) {
1598 context->set_line_width(1.5);
1599 return ::get_graph(*this, subindex, data, points);
1601 return false;
1604 bool deesser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1606 return get_freq_gridline(subindex, pos, vertical, legend, context);
1608 // return false;
1611 int deesser_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1613 if (!is_active) {
1614 return false;
1615 } else {
1616 // (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
1617 if (*params[param_f1_freq] != f1_freq_old1
1618 or *params[param_f2_freq] != f2_freq_old1
1619 or *params[param_f1_level] != f1_level_old1
1620 or *params[param_f2_level] != f2_level_old1
1621 or *params[param_f2_q] !=f2_q_old1)
1623 f1_freq_old1 = *params[param_f1_freq];
1624 f2_freq_old1 = *params[param_f2_freq];
1625 f1_level_old1 = *params[param_f1_level];
1626 f2_level_old1 = *params[param_f2_level];
1627 f2_q_old1 = *params[param_f2_q];
1628 last_generation++;
1629 subindex_graph = 0;
1630 subindex_dot = INT_MAX;
1631 subindex_gridline = INT_MAX;
1633 else {
1634 subindex_graph = 0;
1635 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
1637 if (generation == last_calculated_generation)
1638 subindex_graph = INT_MAX;
1639 return last_generation;
1641 return false;
1644 /// Gain reduction module by Thor
1645 /// All functions of this module are originally written
1646 /// by Thor, while some features have been stripped (mainly stereo linking
1647 /// and frequency correction as implemented in Sidechain Compressor above)
1648 /// To save some CPU.
1649 ////////////////////////////////////////////////////////////////////////////////
1650 gain_reduction_audio_module::gain_reduction_audio_module()
1652 is_active = false;
1653 last_generation = 0;
1656 void gain_reduction_audio_module::activate()
1658 is_active = true;
1659 linSlope = 0.f;
1660 meter_out = 0.f;
1661 meter_comp = 1.f;
1662 float l, r;
1663 l = r = 0.f;
1664 float byp = bypass;
1665 bypass = 0.0;
1666 process(l, r);
1667 bypass = byp;
1670 void gain_reduction_audio_module::deactivate()
1672 is_active = false;
1675 void gain_reduction_audio_module::process(float &left, float &right, float det_left, float det_right)
1677 if(!det_left) {
1678 det_left = left;
1680 if(!det_right) {
1681 det_right = right;
1683 float gain = 1.f;
1684 if(bypass < 0.5f) {
1685 // this routine is mainly copied from thor's compressor module
1686 // greatest sounding compressor I've heard!
1687 bool rms = detection == 0;
1688 bool average = stereo_link == 0;
1689 float linThreshold = threshold;
1690 float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
1691 float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
1692 float linKneeSqrt = sqrt(knee);
1693 linKneeStart = linThreshold / linKneeSqrt;
1694 adjKneeStart = linKneeStart*linKneeStart;
1695 float linKneeStop = linThreshold * linKneeSqrt;
1696 thres = log(linThreshold);
1697 kneeStart = log(linKneeStart);
1698 kneeStop = log(linKneeStop);
1699 compressedKneeStop = (kneeStop - thres) / ratio + thres;
1701 float absample = average ? (fabs(det_left) + fabs(det_right)) * 0.5f : std::max(fabs(det_left), fabs(det_right));
1702 if(rms) absample *= absample;
1704 linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
1706 if(linSlope > 0.f) {
1707 gain = output_gain(linSlope, rms);
1710 left *= gain * makeup;
1711 right *= gain * makeup;
1712 meter_out = std::max(fabs(left), fabs(right));;
1713 meter_comp = gain;
1714 detected = rms ? sqrt(linSlope) : linSlope;
1718 float gain_reduction_audio_module::output_level(float slope) {
1719 return slope * output_gain(slope, false) * makeup;
1722 float gain_reduction_audio_module::output_gain(float linSlope, bool rms) {
1723 //this calculation is also thor's work
1724 if(linSlope > (rms ? adjKneeStart : linKneeStart)) {
1725 float slope = log(linSlope);
1726 if(rms) slope *= 0.5f;
1728 float gain = 0.f;
1729 float delta = 0.f;
1730 if(IS_FAKE_INFINITY(ratio)) {
1731 gain = thres;
1732 delta = 0.f;
1733 } else {
1734 gain = (slope - thres) / ratio + thres;
1735 delta = 1.f / ratio;
1738 if(knee > 1.f && slope < kneeStop) {
1739 gain = hermite_interpolation(slope, kneeStart, kneeStop, kneeStart, compressedKneeStop, 1.f, delta);
1742 return exp(gain - slope);
1745 return 1.f;
1748 void gain_reduction_audio_module::set_sample_rate(uint32_t sr)
1750 srate = sr;
1752 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)
1754 // set all params
1755 attack = att;
1756 release = rel;
1757 threshold = thr;
1758 ratio = rat;
1759 knee = kn;
1760 makeup = mak;
1761 detection = det;
1762 stereo_link = stl;
1763 bypass = byp;
1764 mute = mu;
1765 if(mute > 0.f) {
1766 meter_out = 0.f;
1767 meter_comp = 1.f;
1770 float gain_reduction_audio_module::get_output_level() {
1771 // returns output level (max(left, right))
1772 return meter_out;
1774 float gain_reduction_audio_module::get_comp_level() {
1775 // returns amount of compression
1776 return meter_comp;
1779 bool gain_reduction_audio_module::get_graph(int subindex, float *data, int points, cairo_iface *context)
1781 if (!is_active)
1782 return false;
1783 if (subindex > 1) // 1
1784 return false;
1785 for (int i = 0; i < points; i++)
1787 float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
1788 if (subindex == 0)
1789 data[i] = dB_grid(input);
1790 else {
1791 float output = output_level(input);
1792 data[i] = dB_grid(output);
1795 if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
1796 context->set_source_rgba(0.35, 0.4, 0.2, 0.3);
1797 else {
1798 context->set_source_rgba(0.35, 0.4, 0.2, 1);
1799 context->set_line_width(1.5);
1801 return true;
1804 bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int &size, cairo_iface *context)
1806 if (!is_active)
1807 return false;
1808 if (!subindex)
1810 if(bypass > 0.5f or mute > 0.f) {
1811 return false;
1812 } else {
1813 bool rms = detection == 0;
1814 float det = rms ? sqrt(detected) : detected;
1815 x = 0.5 + 0.5 * dB_grid(det);
1816 y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
1817 return true;
1820 return false;
1823 bool gain_reduction_audio_module::get_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
1825 bool tmp;
1826 vertical = (subindex & 1) != 0;
1827 bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
1828 if (result && vertical) {
1829 if ((subindex & 4) && !legend.empty()) {
1830 legend = "";
1832 else {
1833 size_t pos = legend.find(" dB");
1834 if (pos != std::string::npos)
1835 legend.erase(pos);
1837 pos = 0.5 + 0.5 * pos;
1839 return result;
1842 int gain_reduction_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
1844 subindex_graph = 0;
1845 subindex_dot = 0;
1846 subindex_gridline = generation ? INT_MAX : 0;
1848 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)
1850 old_threshold = threshold;
1851 old_ratio = ratio;
1852 old_knee = knee;
1853 old_makeup = makeup;
1854 old_detection = detection;
1855 old_bypass = bypass;
1856 old_mute = mute;
1857 last_generation++;
1860 if (generation == last_generation)
1861 subindex_graph = 2;
1862 return last_generation;
1865 /// Equalizer 12 Band by Markus Schmidt
1867 /// This module is based on Krzysztof's filters. It provides a couple
1868 /// of different chained filters.
1869 ///////////////////////////////////////////////////////////////////////////////////////////////
1871 equalizer12band_audio_module::equalizer12band_audio_module()
1873 is_active = false;
1874 srate = 0;
1875 last_generation = 0;
1876 clip_inL = 0.f;
1877 clip_inR = 0.f;
1878 clip_outL = 0.f;
1879 clip_outR = 0.f;
1880 meter_inL = 0.f;
1881 meter_inR = 0.f;
1882 meter_outL = 0.f;
1883 meter_outR = 0.f;
1886 void equalizer12band_audio_module::activate()
1888 is_active = true;
1889 // set all filters
1890 params_changed();
1892 void equalizer12band_audio_module::deactivate()
1894 is_active = false;
1897 void equalizer12band_audio_module::params_changed()
1899 // set the params of all filters
1900 if(*params[param_hp_freq] != hp_freq_old) {
1901 hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0);
1902 hpL[1].copy_coeffs(hpL[0]);
1903 hpL[2].copy_coeffs(hpL[0]);
1904 hpR[0].copy_coeffs(hpL[0]);
1905 hpR[1].copy_coeffs(hpL[0]);
1906 hpR[2].copy_coeffs(hpL[0]);
1907 hp_freq_old = *params[param_hp_freq];
1909 if(*params[param_lp_freq] != lp_freq_old) {
1910 lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0);
1911 lpL[1].copy_coeffs(lpL[0]);
1912 lpL[2].copy_coeffs(lpL[0]);
1913 lpR[0].copy_coeffs(lpL[0]);
1914 lpR[1].copy_coeffs(lpL[0]);
1915 lpR[2].copy_coeffs(lpL[0]);
1916 lp_freq_old = *params[param_lp_freq];
1918 if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) {
1919 lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate);
1920 lsR.copy_coeffs(lsL);
1921 ls_level_old = *params[param_ls_level];
1922 ls_freq_old = *params[param_ls_freq];
1924 if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) {
1925 hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate);
1926 hsR.copy_coeffs(hsL);
1927 hs_level_old = *params[param_hs_level];
1928 hs_freq_old = *params[param_hs_freq];
1930 if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) {
1931 pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate);
1932 pR[0].copy_coeffs(pL[0]);
1933 p_freq_old[0] = *params[param_p1_freq];
1934 p_level_old[0] = *params[param_p1_level];
1935 p_q_old[0] = *params[param_p1_q];
1937 if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) {
1938 pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate);
1939 pR[1].copy_coeffs(pL[1]);
1940 p_freq_old[1] = *params[param_p2_freq];
1941 p_level_old[1] = *params[param_p2_level];
1942 p_q_old[1] = *params[param_p2_q];
1944 if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) {
1945 pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate);
1946 pR[2].copy_coeffs(pL[2]);
1947 p_freq_old[2] = *params[param_p3_freq];
1948 p_level_old[2] = *params[param_p3_level];
1949 p_q_old[2] = *params[param_p3_q];
1951 if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) {
1952 pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate);
1953 pR[3].copy_coeffs(pL[3]);
1954 p_freq_old[3] = *params[param_p4_freq];
1955 p_level_old[3] = *params[param_p4_level];
1956 p_q_old[3] = *params[param_p4_q];
1958 if(*params[param_p5_freq] != p_freq_old[4] or *params[param_p5_level] != p_level_old[4] or *params[param_p5_q] != p_q_old[4]) {
1959 pL[4].set_peakeq_rbj((float)*params[param_p5_freq], *params[param_p5_q], *params[param_p5_level], (float)srate);
1960 pR[4].copy_coeffs(pL[4]);
1961 p_freq_old[4] = *params[param_p5_freq];
1962 p_level_old[4] = *params[param_p5_level];
1963 p_q_old[4] = *params[param_p5_q];
1965 if(*params[param_p6_freq] != p_freq_old[5] or *params[param_p6_level] != p_level_old[5] or *params[param_p6_q] != p_q_old[5]) {
1966 pL[5].set_peakeq_rbj((float)*params[param_p6_freq], *params[param_p6_q], *params[param_p6_level], (float)srate);
1967 pR[5].copy_coeffs(pL[5]);
1968 p_freq_old[5] = *params[param_p6_freq];
1969 p_level_old[5] = *params[param_p6_level];
1970 p_q_old[5] = *params[param_p6_q];
1972 if(*params[param_p7_freq] != p_freq_old[6] or *params[param_p7_level] != p_level_old[6] or *params[param_p7_q] != p_q_old[6]) {
1973 pL[6].set_peakeq_rbj((float)*params[param_p7_freq], *params[param_p7_q], *params[param_p7_level], (float)srate);
1974 pR[6].copy_coeffs(pL[6]);
1975 p_freq_old[6] = *params[param_p7_freq];
1976 p_level_old[6] = *params[param_p7_level];
1977 p_q_old[6] = *params[param_p7_q];
1979 if(*params[param_p8_freq] != p_freq_old[7] or *params[param_p8_level] != p_level_old[7] or *params[param_p8_q] != p_q_old[7]) {
1980 pL[7].set_peakeq_rbj((float)*params[param_p8_freq], *params[param_p8_q], *params[param_p8_level], (float)srate);
1981 pR[7].copy_coeffs(pL[7]);
1982 p_freq_old[7] = *params[param_p8_freq];
1983 p_level_old[7] = *params[param_p8_level];
1984 p_q_old[7] = *params[param_p8_q];
1988 void equalizer12band_audio_module::set_sample_rate(uint32_t sr)
1990 srate = sr;
1993 uint32_t equalizer12band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1995 bool bypass = *params[param_bypass] > 0.5f;
1996 numsamples += offset;
1997 if(bypass) {
1998 // everything bypassed
1999 while(offset < numsamples) {
2000 outs[0][offset] = ins[0][offset];
2001 outs[1][offset] = ins[1][offset];
2002 ++offset;
2004 // displays, too
2005 clip_inL = 0.f;
2006 clip_inR = 0.f;
2007 clip_outL = 0.f;
2008 clip_outR = 0.f;
2009 meter_inL = 0.f;
2010 meter_inR = 0.f;
2011 meter_outL = 0.f;
2012 meter_outR = 0.f;
2013 } else {
2015 clip_inL -= std::min(clip_inL, numsamples);
2016 clip_inR -= std::min(clip_inR, numsamples);
2017 clip_outL -= std::min(clip_outL, numsamples);
2018 clip_outR -= std::min(clip_outR, numsamples);
2019 meter_inL = 0.f;
2020 meter_inR = 0.f;
2021 meter_outL = 0.f;
2022 meter_outR = 0.f;
2024 // process
2025 while(offset < numsamples) {
2026 // cycle through samples
2027 float outL = 0.f;
2028 float outR = 0.f;
2029 float inL = ins[0][offset];
2030 float inR = ins[1][offset];
2031 // in level
2032 inR *= *params[param_level_in];
2033 inL *= *params[param_level_in];
2035 float procL = inL;
2036 float procR = inR;
2038 // all filters in chain
2039 if(*params[param_hp_active] > 0.f) {
2040 switch((int)*params[param_hp_mode]) {
2041 case MODE12DB:
2042 procL = hpL[0].process(procL);
2043 procR = hpR[0].process(procR);
2044 break;
2045 case MODE24DB:
2046 procL = hpL[1].process(hpL[0].process(procL));
2047 procR = hpR[1].process(hpR[0].process(procR));
2048 break;
2049 case MODE36DB:
2050 procL = hpL[2].process(hpL[1].process(hpL[0].process(procL)));
2051 procR = hpR[2].process(hpR[1].process(hpR[0].process(procR)));
2052 break;
2055 if(*params[param_lp_active] > 0.f) {
2056 switch((int)*params[param_lp_mode]) {
2057 case MODE12DB:
2058 procL = lpL[0].process(procL);
2059 procR = lpR[0].process(procR);
2060 break;
2061 case MODE24DB:
2062 procL = lpL[1].process(lpL[0].process(procL));
2063 procR = lpR[1].process(lpR[0].process(procR));
2064 break;
2065 case MODE36DB:
2066 procL = lpL[2].process(lpL[1].process(lpL[0].process(procL)));
2067 procR = lpR[2].process(lpR[1].process(lpR[0].process(procR)));
2068 break;
2071 if(*params[param_ls_active] > 0.f) {
2072 procL = lsL.process(procL);
2073 procR = lsR.process(procR);
2075 if(*params[param_hs_active] > 0.f) {
2076 procL = hsL.process(procL);
2077 procR = hsR.process(procR);
2079 if(*params[param_p1_active] > 0.f) {
2080 procL = pL[0].process(procL);
2081 procR = pR[0].process(procR);
2083 if(*params[param_p2_active] > 0.f) {
2084 procL = pL[1].process(procL);
2085 procR = pR[1].process(procR);
2087 if(*params[param_p3_active] > 0.f) {
2088 procL = pL[2].process(procL);
2089 procR = pR[2].process(procR);
2091 if(*params[param_p4_active] > 0.f) {
2092 procL = pL[3].process(procL);
2093 procR = pR[3].process(procR);
2095 if(*params[param_p5_active] > 0.f) {
2096 procL = pL[4].process(procL);
2097 procR = pR[4].process(procR);
2099 if(*params[param_p6_active] > 0.f) {
2100 procL = pL[5].process(procL);
2101 procR = pR[5].process(procR);
2103 if(*params[param_p7_active] > 0.f) {
2104 procL = pL[6].process(procL);
2105 procR = pR[6].process(procR);
2107 if(*params[param_p8_active] > 0.f) {
2108 procL = pL[7].process(procL);
2109 procR = pR[7].process(procR);
2112 outL = procL * *params[param_level_out];
2113 outR = procR * *params[param_level_out];
2115 // send to output
2116 outs[0][offset] = outL;
2117 outs[1][offset] = outR;
2119 // clip LED's
2120 if(inL > 1.f) {
2121 clip_inL = srate >> 3;
2123 if(inR > 1.f) {
2124 clip_inR = srate >> 3;
2126 if(outL > 1.f) {
2127 clip_outL = srate >> 3;
2129 if(outR > 1.f) {
2130 clip_outR = srate >> 3;
2132 // set up in / out meters
2133 if(inL > meter_inL) {
2134 meter_inL = inL;
2136 if(inR > meter_inR) {
2137 meter_inR = inR;
2139 if(outL > meter_outL) {
2140 meter_outL = outL;
2142 if(outR > meter_outR) {
2143 meter_outR = outR;
2146 // next sample
2147 ++offset;
2148 } // cycle trough samples
2149 // clean up
2150 for(int i = 0; i < 3; ++i) {
2151 hpL[i].sanitize();
2152 hpR[i].sanitize();
2153 lpL[i].sanitize();
2154 lpR[i].sanitize();
2156 lsL.sanitize();
2157 hsR.sanitize();
2158 for(int i = 0; i < 8; ++i) {
2159 pL[i].sanitize();
2160 pR[i].sanitize();
2163 // draw meters
2164 if(params[param_clip_inL] != NULL) {
2165 *params[param_clip_inL] = clip_inL;
2167 if(params[param_clip_inR] != NULL) {
2168 *params[param_clip_inR] = clip_inR;
2170 if(params[param_clip_outL] != NULL) {
2171 *params[param_clip_outL] = clip_outL;
2173 if(params[param_clip_outR] != NULL) {
2174 *params[param_clip_outR] = clip_outR;
2177 if(params[param_meter_inL] != NULL) {
2178 *params[param_meter_inL] = meter_inL;
2180 if(params[param_meter_inR] != NULL) {
2181 *params[param_meter_inR] = meter_inR;
2183 if(params[param_meter_outL] != NULL) {
2184 *params[param_meter_outL] = meter_outL;
2186 if(params[param_meter_outR] != NULL) {
2187 *params[param_meter_outR] = meter_outR;
2189 // whatever has to be returned x)
2190 return outputs_mask;
2192 bool equalizer12band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
2194 if (!is_active)
2195 return false;
2196 if (index == param_p1_freq && !subindex) {
2197 context->set_line_width(1.5);
2198 return ::get_graph(*this, subindex, data, points);
2200 return false;
2203 bool equalizer12band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
2205 if (!is_active) {
2206 return false;
2207 } else {
2208 return get_freq_gridline(subindex, pos, vertical, legend, context);
2212 int equalizer12band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
2214 if (!is_active) {
2215 return false;
2216 } else {
2217 if (*params[param_hp_freq] != hp_freq_old1
2218 or *params[param_hp_mode] != hp_mode_old1
2219 or *params[param_lp_freq] != lp_freq_old1
2220 or *params[param_lp_mode] != lp_mode_old1
2222 or *params[param_ls_freq] != ls_freq_old1
2223 or *params[param_ls_level] != ls_level_old1
2224 or *params[param_hs_freq] != hs_freq_old1
2225 or *params[param_hs_level] != hs_level_old1
2227 or *params[param_p1_freq] != p_freq_old1[0]
2228 or *params[param_p1_level] != p_level_old1[0]
2229 or *params[param_p1_q] != p_q_old1[0]
2231 or *params[param_p2_freq] != p_freq_old1[1]
2232 or *params[param_p2_level] != p_level_old1[1]
2233 or *params[param_p2_q] != p_q_old1[1]
2235 or *params[param_p3_freq] != p_freq_old1[2]
2236 or *params[param_p3_level] != p_level_old1[2]
2237 or *params[param_p3_q] != p_q_old1[2]
2239 or *params[param_p4_freq] != p_freq_old1[3]
2240 or *params[param_p4_level] != p_level_old1[3]
2241 or *params[param_p4_q] != p_q_old1[3]
2243 or *params[param_p5_freq] != p_freq_old1[4]
2244 or *params[param_p5_level] != p_level_old1[4]
2245 or *params[param_p5_q] != p_q_old1[4]
2247 or *params[param_p6_freq] != p_freq_old1[5]
2248 or *params[param_p6_level] != p_level_old1[5]
2249 or *params[param_p6_q] != p_q_old1[5]
2251 or *params[param_p7_freq] != p_freq_old1[6]
2252 or *params[param_p7_level] != p_level_old1[6]
2253 or *params[param_p7_q] != p_q_old1[6]
2255 or *params[param_p8_freq] != p_freq_old1[7]
2256 or *params[param_p8_level] != p_level_old1[7]
2257 or *params[param_p8_q] != p_q_old1[7])
2260 hp_freq_old1 = *params[param_hp_freq];
2261 hp_mode_old1 = *params[param_hp_mode];
2262 lp_freq_old1 = *params[param_lp_freq];
2263 lp_mode_old1 = *params[param_lp_mode];
2265 ls_freq_old1 = *params[param_ls_freq];
2266 ls_level_old1 = *params[param_ls_level];
2267 hs_freq_old1 = *params[param_hs_freq];
2268 hs_level_old1 = *params[param_hs_level];
2270 p_freq_old1[0] = *params[param_p1_freq];
2271 p_level_old1[0] = *params[param_p1_level];
2272 p_q_old1[0] = *params[param_p1_q];
2274 p_freq_old1[1] = *params[param_p2_freq];
2275 p_level_old1[1] = *params[param_p2_level];
2276 p_q_old1[1] = *params[param_p2_q];
2278 p_freq_old1[2] = *params[param_p3_freq];
2279 p_level_old1[2] = *params[param_p3_level];
2280 p_q_old1[2] = *params[param_p3_q];
2282 p_freq_old1[3] = *params[param_p4_freq];
2283 p_level_old1[3] = *params[param_p4_level];
2284 p_q_old1[3] = *params[param_p4_q];
2286 p_freq_old1[4] = *params[param_p5_freq];
2287 p_level_old1[4] = *params[param_p5_level];
2288 p_q_old1[4] = *params[param_p5_q];
2290 p_freq_old1[5] = *params[param_p6_freq];
2291 p_level_old1[5] = *params[param_p6_level];
2292 p_q_old1[5] = *params[param_p6_q];
2294 p_freq_old1[6] = *params[param_p7_freq];
2295 p_level_old1[6] = *params[param_p7_level];
2296 p_q_old1[6] = *params[param_p7_q];
2298 p_freq_old1[7] = *params[param_p8_freq];
2299 p_level_old1[7] = *params[param_p8_level];
2300 p_q_old1[7] = *params[param_p8_q];
2302 last_generation++;
2303 subindex_graph = 0;
2304 subindex_dot = INT_MAX;
2305 subindex_gridline = INT_MAX;
2307 else {
2308 subindex_graph = 0;
2309 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
2311 if (generation == last_calculated_generation)
2312 subindex_graph = INT_MAX;
2313 return last_generation;
2315 return false;
2318 /// Equalizer 8 Band by Markus Schmidt
2320 /// This module is based on Krzysztof's filters. It provides a couple
2321 /// of different chained filters.
2322 ///////////////////////////////////////////////////////////////////////////////////////////////
2324 equalizer8band_audio_module::equalizer8band_audio_module()
2326 is_active = false;
2327 srate = 0;
2328 last_generation = 0;
2329 clip_inL = 0.f;
2330 clip_inR = 0.f;
2331 clip_outL = 0.f;
2332 clip_outR = 0.f;
2333 meter_inL = 0.f;
2334 meter_inR = 0.f;
2335 meter_outL = 0.f;
2336 meter_outR = 0.f;
2339 void equalizer8band_audio_module::activate()
2341 is_active = true;
2342 // set all filters
2343 params_changed();
2345 void equalizer8band_audio_module::deactivate()
2347 is_active = false;
2350 void equalizer8band_audio_module::params_changed()
2352 // set the params of all filters
2353 if(*params[param_hp_freq] != hp_freq_old) {
2354 hpL[0].set_hp_rbj(*params[param_hp_freq], 0.707, (float)srate, 1.0);
2355 hpL[1].copy_coeffs(hpL[0]);
2356 hpL[2].copy_coeffs(hpL[0]);
2357 hpR[0].copy_coeffs(hpL[0]);
2358 hpR[1].copy_coeffs(hpL[0]);
2359 hpR[2].copy_coeffs(hpL[0]);
2360 hp_freq_old = *params[param_hp_freq];
2362 if(*params[param_lp_freq] != lp_freq_old) {
2363 lpL[0].set_lp_rbj(*params[param_lp_freq], 0.707, (float)srate, 1.0);
2364 lpL[1].copy_coeffs(lpL[0]);
2365 lpL[2].copy_coeffs(lpL[0]);
2366 lpR[0].copy_coeffs(lpL[0]);
2367 lpR[1].copy_coeffs(lpL[0]);
2368 lpR[2].copy_coeffs(lpL[0]);
2369 lp_freq_old = *params[param_lp_freq];
2371 if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) {
2372 lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate);
2373 lsR.copy_coeffs(lsL);
2374 ls_level_old = *params[param_ls_level];
2375 ls_freq_old = *params[param_ls_freq];
2377 if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) {
2378 hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate);
2379 hsR.copy_coeffs(hsL);
2380 hs_level_old = *params[param_hs_level];
2381 hs_freq_old = *params[param_hs_freq];
2383 if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) {
2384 pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate);
2385 pR[0].copy_coeffs(pL[0]);
2386 p_freq_old[0] = *params[param_p1_freq];
2387 p_level_old[0] = *params[param_p1_level];
2388 p_q_old[0] = *params[param_p1_q];
2390 if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) {
2391 pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate);
2392 pR[1].copy_coeffs(pL[1]);
2393 p_freq_old[1] = *params[param_p2_freq];
2394 p_level_old[1] = *params[param_p2_level];
2395 p_q_old[1] = *params[param_p2_q];
2397 if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) {
2398 pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate);
2399 pR[2].copy_coeffs(pL[2]);
2400 p_freq_old[2] = *params[param_p3_freq];
2401 p_level_old[2] = *params[param_p3_level];
2402 p_q_old[2] = *params[param_p3_q];
2404 if(*params[param_p4_freq] != p_freq_old[3] or *params[param_p4_level] != p_level_old[3] or *params[param_p4_q] != p_q_old[3]) {
2405 pL[3].set_peakeq_rbj((float)*params[param_p4_freq], *params[param_p4_q], *params[param_p4_level], (float)srate);
2406 pR[3].copy_coeffs(pL[3]);
2407 p_freq_old[3] = *params[param_p4_freq];
2408 p_level_old[3] = *params[param_p4_level];
2409 p_q_old[3] = *params[param_p4_q];
2413 void equalizer8band_audio_module::set_sample_rate(uint32_t sr)
2415 srate = sr;
2418 uint32_t equalizer8band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2420 bool bypass = *params[param_bypass] > 0.5f;
2421 numsamples += offset;
2422 if(bypass) {
2423 // everything bypassed
2424 while(offset < numsamples) {
2425 outs[0][offset] = ins[0][offset];
2426 outs[1][offset] = ins[1][offset];
2427 ++offset;
2429 // displays, too
2430 clip_inL = 0.f;
2431 clip_inR = 0.f;
2432 clip_outL = 0.f;
2433 clip_outR = 0.f;
2434 meter_inL = 0.f;
2435 meter_inR = 0.f;
2436 meter_outL = 0.f;
2437 meter_outR = 0.f;
2438 } else {
2440 clip_inL -= std::min(clip_inL, numsamples);
2441 clip_inR -= std::min(clip_inR, numsamples);
2442 clip_outL -= std::min(clip_outL, numsamples);
2443 clip_outR -= std::min(clip_outR, numsamples);
2444 meter_inL = 0.f;
2445 meter_inR = 0.f;
2446 meter_outL = 0.f;
2447 meter_outR = 0.f;
2449 // process
2450 while(offset < numsamples) {
2451 // cycle through samples
2452 float outL = 0.f;
2453 float outR = 0.f;
2454 float inL = ins[0][offset];
2455 float inR = ins[1][offset];
2456 // in level
2457 inR *= *params[param_level_in];
2458 inL *= *params[param_level_in];
2460 float procL = inL;
2461 float procR = inR;
2463 // all filters in chain
2464 if(*params[param_hp_active] > 0.f) {
2465 switch((int)*params[param_hp_mode]) {
2466 case MODE12DB:
2467 procL = hpL[0].process(procL);
2468 procR = hpR[0].process(procR);
2469 break;
2470 case MODE24DB:
2471 procL = hpL[1].process(hpL[0].process(procL));
2472 procR = hpR[1].process(hpR[0].process(procR));
2473 break;
2474 case MODE36DB:
2475 procL = hpL[2].process(hpL[1].process(hpL[0].process(procL)));
2476 procR = hpR[2].process(hpR[1].process(hpR[0].process(procR)));
2477 break;
2480 if(*params[param_lp_active] > 0.f) {
2481 switch((int)*params[param_lp_mode]) {
2482 case MODE12DB:
2483 procL = lpL[0].process(procL);
2484 procR = lpR[0].process(procR);
2485 break;
2486 case MODE24DB:
2487 procL = lpL[1].process(lpL[0].process(procL));
2488 procR = lpR[1].process(lpR[0].process(procR));
2489 break;
2490 case MODE36DB:
2491 procL = lpL[2].process(lpL[1].process(lpL[0].process(procL)));
2492 procR = lpR[2].process(lpR[1].process(lpR[0].process(procR)));
2493 break;
2496 if(*params[param_ls_active] > 0.f) {
2497 procL = lsL.process(procL);
2498 procR = lsR.process(procR);
2500 if(*params[param_hs_active] > 0.f) {
2501 procL = hsL.process(procL);
2502 procR = hsR.process(procR);
2504 if(*params[param_p1_active] > 0.f) {
2505 procL = pL[0].process(procL);
2506 procR = pR[0].process(procR);
2508 if(*params[param_p2_active] > 0.f) {
2509 procL = pL[1].process(procL);
2510 procR = pR[1].process(procR);
2512 if(*params[param_p3_active] > 0.f) {
2513 procL = pL[2].process(procL);
2514 procR = pR[2].process(procR);
2516 if(*params[param_p4_active] > 0.f) {
2517 procL = pL[3].process(procL);
2518 procR = pR[3].process(procR);
2521 outL = procL * *params[param_level_out];
2522 outR = procR * *params[param_level_out];
2524 // send to output
2525 outs[0][offset] = outL;
2526 outs[1][offset] = outR;
2528 // clip LED's
2529 if(inL > 1.f) {
2530 clip_inL = srate >> 3;
2532 if(inR > 1.f) {
2533 clip_inR = srate >> 3;
2535 if(outL > 1.f) {
2536 clip_outL = srate >> 3;
2538 if(outR > 1.f) {
2539 clip_outR = srate >> 3;
2541 // set up in / out meters
2542 if(inL > meter_inL) {
2543 meter_inL = inL;
2545 if(inR > meter_inR) {
2546 meter_inR = inR;
2548 if(outL > meter_outL) {
2549 meter_outL = outL;
2551 if(outR > meter_outR) {
2552 meter_outR = outR;
2555 // next sample
2556 ++offset;
2557 } // cycle trough samples
2558 // clean up
2559 for(int i = 0; i < 3; ++i) {
2560 hpL[i].sanitize();
2561 hpR[i].sanitize();
2562 lpL[i].sanitize();
2563 lpR[i].sanitize();
2565 lsL.sanitize();
2566 hsR.sanitize();
2567 for(int i = 0; i < 4; ++i) {
2568 pL[i].sanitize();
2569 pR[i].sanitize();
2572 // draw meters
2573 if(params[param_clip_inL] != NULL) {
2574 *params[param_clip_inL] = clip_inL;
2576 if(params[param_clip_inR] != NULL) {
2577 *params[param_clip_inR] = clip_inR;
2579 if(params[param_clip_outL] != NULL) {
2580 *params[param_clip_outL] = clip_outL;
2582 if(params[param_clip_outR] != NULL) {
2583 *params[param_clip_outR] = clip_outR;
2586 if(params[param_meter_inL] != NULL) {
2587 *params[param_meter_inL] = meter_inL;
2589 if(params[param_meter_inR] != NULL) {
2590 *params[param_meter_inR] = meter_inR;
2592 if(params[param_meter_outL] != NULL) {
2593 *params[param_meter_outL] = meter_outL;
2595 if(params[param_meter_outR] != NULL) {
2596 *params[param_meter_outR] = meter_outR;
2598 // whatever has to be returned x)
2599 return outputs_mask;
2601 bool equalizer8band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
2603 if (!is_active)
2604 return false;
2605 if (index == param_p1_freq && !subindex) {
2606 context->set_line_width(1.5);
2607 return ::get_graph(*this, subindex, data, points);
2609 return false;
2612 bool equalizer8band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
2614 if (!is_active) {
2615 return false;
2616 } else {
2617 return get_freq_gridline(subindex, pos, vertical, legend, context);
2621 int equalizer8band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
2623 if (!is_active) {
2624 return false;
2625 } else {
2626 if (*params[param_hp_freq] != hp_freq_old1
2627 or *params[param_hp_mode] != hp_mode_old1
2628 or *params[param_lp_freq] != lp_freq_old1
2629 or *params[param_lp_mode] != lp_mode_old1
2631 or *params[param_ls_freq] != ls_freq_old1
2632 or *params[param_ls_level] != ls_level_old1
2633 or *params[param_hs_freq] != hs_freq_old1
2634 or *params[param_hs_level] != hs_level_old1
2636 or *params[param_p1_freq] != p_freq_old1[0]
2637 or *params[param_p1_level] != p_level_old1[0]
2638 or *params[param_p1_q] != p_q_old1[0]
2640 or *params[param_p2_freq] != p_freq_old1[1]
2641 or *params[param_p2_level] != p_level_old1[1]
2642 or *params[param_p2_q] != p_q_old1[1]
2644 or *params[param_p3_freq] != p_freq_old1[2]
2645 or *params[param_p3_level] != p_level_old1[2]
2646 or *params[param_p3_q] != p_q_old1[2]
2648 or *params[param_p4_freq] != p_freq_old1[3]
2649 or *params[param_p4_level] != p_level_old1[3]
2650 or *params[param_p4_q] != p_q_old1[3])
2653 hp_freq_old1 = *params[param_hp_freq];
2654 hp_mode_old1 = *params[param_hp_mode];
2655 lp_freq_old1 = *params[param_lp_freq];
2656 lp_mode_old1 = *params[param_lp_mode];
2658 ls_freq_old1 = *params[param_ls_freq];
2659 ls_level_old1 = *params[param_ls_level];
2660 hs_freq_old1 = *params[param_hs_freq];
2661 hs_level_old1 = *params[param_hs_level];
2663 p_freq_old1[0] = *params[param_p1_freq];
2664 p_level_old1[0] = *params[param_p1_level];
2665 p_q_old1[0] = *params[param_p1_q];
2667 p_freq_old1[1] = *params[param_p2_freq];
2668 p_level_old1[1] = *params[param_p2_level];
2669 p_q_old1[1] = *params[param_p2_q];
2671 p_freq_old1[2] = *params[param_p3_freq];
2672 p_level_old1[2] = *params[param_p3_level];
2673 p_q_old1[2] = *params[param_p3_q];
2675 p_freq_old1[3] = *params[param_p4_freq];
2676 p_level_old1[3] = *params[param_p4_level];
2677 p_q_old1[3] = *params[param_p4_q];
2679 last_generation++;
2680 subindex_graph = 0;
2681 subindex_dot = INT_MAX;
2682 subindex_gridline = INT_MAX;
2684 else {
2685 subindex_graph = 0;
2686 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
2688 if (generation == last_calculated_generation)
2689 subindex_graph = INT_MAX;
2690 return last_generation;
2692 return false;
2695 /// Equalizer 5 Band by Markus Schmidt
2697 /// This module is based on Krzysztof's filters. It provides a couple
2698 /// of different chained filters.
2699 ///////////////////////////////////////////////////////////////////////////////////////////////
2701 equalizer5band_audio_module::equalizer5band_audio_module()
2703 is_active = false;
2704 srate = 0;
2705 last_generation = 0;
2706 clip_in = 0.f;
2707 clip_out = 0.f;
2708 meter_in = 0.f;
2709 meter_out = 0.f;
2712 void equalizer5band_audio_module::activate()
2714 is_active = true;
2715 // set all filters
2716 params_changed();
2718 void equalizer5band_audio_module::deactivate()
2720 is_active = false;
2723 void equalizer5band_audio_module::params_changed()
2725 // set the params of all filters
2726 if(*params[param_ls_freq] != ls_freq_old or *params[param_ls_level] != ls_level_old) {
2727 lsL.set_lowshelf_rbj(*params[param_ls_freq], 0.707, *params[param_ls_level], (float)srate);
2728 lsR.copy_coeffs(lsL);
2729 ls_level_old = *params[param_ls_level];
2730 ls_freq_old = *params[param_ls_freq];
2732 if(*params[param_hs_freq] != hs_freq_old or *params[param_hs_level] != hs_level_old) {
2733 hsL.set_highshelf_rbj(*params[param_hs_freq], 0.707, *params[param_hs_level], (float)srate);
2734 hsR.copy_coeffs(hsL);
2735 hs_level_old = *params[param_hs_level];
2736 hs_freq_old = *params[param_hs_freq];
2738 if(*params[param_p1_freq] != p_freq_old[0] or *params[param_p1_level] != p_level_old[0] or *params[param_p1_q] != p_q_old[0]) {
2739 pL[0].set_peakeq_rbj((float)*params[param_p1_freq], *params[param_p1_q], *params[param_p1_level], (float)srate);
2740 pR[0].copy_coeffs(pL[0]);
2741 p_freq_old[0] = *params[param_p1_freq];
2742 p_level_old[0] = *params[param_p1_level];
2743 p_q_old[0] = *params[param_p1_q];
2745 if(*params[param_p2_freq] != p_freq_old[1] or *params[param_p2_level] != p_level_old[1] or *params[param_p2_q] != p_q_old[1]) {
2746 pL[1].set_peakeq_rbj((float)*params[param_p2_freq], *params[param_p2_q], *params[param_p2_level], (float)srate);
2747 pR[1].copy_coeffs(pL[1]);
2748 p_freq_old[1] = *params[param_p2_freq];
2749 p_level_old[1] = *params[param_p2_level];
2750 p_q_old[1] = *params[param_p2_q];
2752 if(*params[param_p3_freq] != p_freq_old[2] or *params[param_p3_level] != p_level_old[2] or *params[param_p3_q] != p_q_old[2]) {
2753 pL[2].set_peakeq_rbj((float)*params[param_p3_freq], *params[param_p3_q], *params[param_p3_level], (float)srate);
2754 pR[2].copy_coeffs(pL[2]);
2755 p_freq_old[2] = *params[param_p3_freq];
2756 p_level_old[2] = *params[param_p3_level];
2757 p_q_old[2] = *params[param_p3_q];
2761 void equalizer5band_audio_module::set_sample_rate(uint32_t sr)
2763 srate = sr;
2766 uint32_t equalizer5band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
2768 bool bypass = *params[param_bypass] > 0.5f;
2769 numsamples += offset;
2770 if(bypass) {
2771 // everything bypassed
2772 while(offset < numsamples) {
2773 outs[0][offset] = ins[0][offset];
2774 outs[1][offset] = ins[1][offset];
2775 ++offset;
2777 // displays, too
2778 clip_in = 0.f;
2779 clip_out = 0.f;
2780 meter_in = 0.f;
2781 meter_out = 0.f;
2782 } else {
2784 clip_in -= std::min(clip_in, numsamples);
2785 clip_out -= std::min(clip_out, numsamples);
2786 meter_in = 0.f;
2787 meter_out = 0.f;
2789 // process
2790 while(offset < numsamples) {
2791 // cycle through samples
2792 float outL = 0.f;
2793 float outR = 0.f;
2794 float inL = ins[0][offset];
2795 float inR = ins[1][offset];
2796 // in level
2797 inR *= *params[param_level_in];
2798 inL *= *params[param_level_in];
2800 float procL = inL;
2801 float procR = inR;
2803 // all filters in chain
2804 if(*params[param_ls_active] > 0.f) {
2805 procL = lsL.process(procL);
2806 procR = lsR.process(procR);
2808 if(*params[param_hs_active] > 0.f) {
2809 procL = hsL.process(procL);
2810 procR = hsR.process(procR);
2812 if(*params[param_p1_active] > 0.f) {
2813 procL = pL[0].process(procL);
2814 procR = pR[0].process(procR);
2816 if(*params[param_p2_active] > 0.f) {
2817 procL = pL[1].process(procL);
2818 procR = pR[1].process(procR);
2820 if(*params[param_p3_active] > 0.f) {
2821 procL = pL[2].process(procL);
2822 procR = pR[2].process(procR);
2825 outL = procL * *params[param_level_out];
2826 outR = procR * *params[param_level_out];
2828 // send to output
2829 outs[0][offset] = outL;
2830 outs[1][offset] = outR;
2832 // clip LED's
2833 float maxIn = std::max(fabs(inL), fabs(inR));
2834 float maxOut = std::max(fabs(outL), fabs(outR));
2836 if(maxIn > 1.f) {
2837 clip_in = srate >> 3;
2839 if(maxOut > 1.f) {
2840 clip_out = srate >> 3;
2842 // set up in / out meters
2843 if(maxIn > meter_in) {
2844 meter_in = maxIn;
2846 if(maxOut > meter_out) {
2847 meter_out = maxOut;
2850 // next sample
2851 ++offset;
2852 } // cycle trough samples
2853 // clean up
2854 lsL.sanitize();
2855 hsR.sanitize();
2856 for(int i = 0; i < 3; ++i) {
2857 pL[i].sanitize();
2858 pR[i].sanitize();
2861 // draw meters
2862 if(params[param_clip_in] != NULL) {
2863 *params[param_clip_in] = clip_in;
2865 if(params[param_clip_out] != NULL) {
2866 *params[param_clip_out] = clip_out;
2869 if(params[param_meter_in] != NULL) {
2870 *params[param_meter_in] = meter_in;
2872 if(params[param_meter_out] != NULL) {
2873 *params[param_meter_out] = meter_out;
2875 // whatever has to be returned x)
2876 return outputs_mask;
2878 bool equalizer5band_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
2880 if (!is_active)
2881 return false;
2882 if (index == param_p1_freq && !subindex) {
2883 context->set_line_width(1.5);
2884 return ::get_graph(*this, subindex, data, points);
2886 return false;
2889 bool equalizer5band_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
2891 if (!is_active) {
2892 return false;
2893 } else {
2894 return get_freq_gridline(subindex, pos, vertical, legend, context);
2898 int equalizer5band_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
2900 if (!is_active) {
2901 return false;
2902 } else {
2903 if (*params[param_ls_freq] != ls_freq_old1
2904 or *params[param_ls_level] != ls_level_old1
2905 or *params[param_hs_freq] != hs_freq_old1
2906 or *params[param_hs_level] != hs_level_old1
2908 or *params[param_p1_freq] != p_freq_old1[0]
2909 or *params[param_p1_level] != p_level_old1[0]
2910 or *params[param_p1_q] != p_q_old1[0]
2912 or *params[param_p2_freq] != p_freq_old1[1]
2913 or *params[param_p2_level] != p_level_old1[1]
2914 or *params[param_p2_q] != p_q_old1[1]
2916 or *params[param_p3_freq] != p_freq_old1[2]
2917 or *params[param_p3_level] != p_level_old1[2]
2918 or *params[param_p3_q] != p_q_old1[2])
2921 ls_freq_old1 = *params[param_ls_freq];
2922 ls_level_old1 = *params[param_ls_level];
2923 hs_freq_old1 = *params[param_hs_freq];
2924 hs_level_old1 = *params[param_hs_level];
2926 p_freq_old1[0] = *params[param_p1_freq];
2927 p_level_old1[0] = *params[param_p1_level];
2928 p_q_old1[0] = *params[param_p1_q];
2930 p_freq_old1[1] = *params[param_p2_freq];
2931 p_level_old1[1] = *params[param_p2_level];
2932 p_q_old1[1] = *params[param_p2_q];
2934 p_freq_old1[2] = *params[param_p3_freq];
2935 p_level_old1[2] = *params[param_p3_level];
2936 p_q_old1[2] = *params[param_p3_q];
2938 last_generation++;
2939 subindex_graph = 0;
2940 subindex_dot = INT_MAX;
2941 subindex_gridline = INT_MAX;
2943 else {
2944 subindex_graph = 0;
2945 subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
2947 if (generation == last_calculated_generation)
2948 subindex_graph = INT_MAX;
2949 return last_generation;
2951 return false;