New Effect: Envelope Filter with sidechain
[calf.git] / src / calf / modules_filter.h
blob3389424b2026229e28f32d5cbf5de534caf94233
1 /* Calf DSP plugin pack
2 * Equalization related plugins
4 * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
21 #ifndef CALF_MODULES_FILTER_H
22 #define CALF_MODULES_FILTER_H
24 #include <assert.h>
25 #include <limits.h>
26 #include "biquad.h"
27 #include "inertia.h"
28 #include "audio_fx.h"
29 #include "giface.h"
30 #include "metadata.h"
31 #include "plugin_tools.h"
32 #include "loudness.h"
33 #include "analyzer.h"
34 #include "bypass.h"
35 #include "orfanidis_eq.h"
37 namespace calf_plugins {
39 /**********************************************************************
40 * EQUALIZER N BAND by Markus Schmidt and Krzysztof Foltman
41 **********************************************************************/
43 template<class BaseClass, bool has_lphp>
44 class equalizerNband_audio_module: public audio_module<BaseClass>, public frequency_response_line_graph {
45 public:
46 typedef audio_module<BaseClass> AM;
47 using AM::ins;
48 using AM::outs;
49 using AM::params;
50 using AM::in_count;
51 using AM::out_count;
52 using AM::param_count;
53 using AM::PeakBands;
54 private:
55 analyzer _analyzer;
56 enum { graph_param_count = BaseClass::last_graph_param - BaseClass::first_graph_param + 1, params_per_band = AM::param_p2_active - AM::param_p1_active };
57 float hp_mode_old, hp_freq_old;
58 float lp_mode_old, lp_freq_old;
59 float ls_level_old, ls_freq_old;
60 float hs_level_old, hs_freq_old;
61 int indiv_old;
62 bool analyzer_old;
63 float p_level_old[PeakBands], p_freq_old[PeakBands], p_q_old[PeakBands];
64 mutable float old_params_for_graph[graph_param_count];
65 vumeters meters;
66 CalfEqMode hp_mode, lp_mode;
67 dsp::biquad_d2 hp[3][2], lp[3][2];
68 dsp::biquad_d2 lsL, lsR, hsL, hsR;
69 dsp::biquad_d2 pL[PeakBands], pR[PeakBands];
70 dsp::bypass bypass;
71 int keep_gliding;
72 mutable int last_peak;
73 inline void process_hplp(float &left, float &right);
74 public:
75 typedef std::complex<double> cfloat;
76 uint32_t srate;
77 bool is_active;
78 mutable volatile int last_generation, last_calculated_generation;
79 equalizerNband_audio_module();
80 void activate();
81 void deactivate();
83 void params_changed();
84 bool get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
85 bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
86 bool get_layers(int index, int generation, unsigned int &layers) const;
87 float freq_gain(int index, double freq) const;
88 void set_sample_rate(uint32_t sr)
90 srate = sr;
91 _analyzer.set_sample_rate(sr);
92 int meter[] = {AM::param_meter_inL, AM::param_meter_inR, AM::param_meter_outL, AM::param_meter_outR};
93 int clip[] = {AM::param_clip_inL, AM::param_clip_inR, AM::param_clip_outL, AM::param_clip_outR};
94 meters.init(params, meter, clip, 4, sr);
96 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
99 typedef equalizerNband_audio_module<equalizer5band_metadata, false> equalizer5band_audio_module;
100 typedef equalizerNband_audio_module<equalizer8band_metadata, true> equalizer8band_audio_module;
101 typedef equalizerNband_audio_module<equalizer12band_metadata, true> equalizer12band_audio_module;
103 /**********************************************************************
104 * EQUALIZER 30 BAND
105 **********************************************************************/
107 class equalizer30band_audio_module: public audio_module<equalizer30band_metadata> {
108 orfanidis_eq::conversions conv;
109 orfanidis_eq::freq_grid fg;
110 std::vector<orfanidis_eq::eq2*> eq_arrL;
111 std::vector<orfanidis_eq::eq2*> eq_arrR;
113 orfanidis_eq::filter_type flt_type;
114 orfanidis_eq::filter_type flt_type_old;
116 dsp::switcher<orfanidis_eq::filter_type> swL;
117 dsp::switcher<orfanidis_eq::filter_type> swR;
119 bool is_freq_grid_init;
120 void set_freq_grid();
122 public:
123 uint32_t srate;
124 bool is_active;
125 dsp::bypass bypass;
126 dsp::bypass eq_switch;
127 vumeters meters;
128 equalizer30band_audio_module();
129 ~equalizer30band_audio_module();
131 void activate();
132 void deactivate();
133 void params_changed();
134 void set_sample_rate(uint32_t sr);
135 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
138 /**********************************************************************
139 * FILTER MODULE by Krzysztof Foltman
140 **********************************************************************/
142 template<typename FilterClass, typename Metadata>
143 class filter_module_with_inertia: public audio_module<Metadata>, public FilterClass,
144 public frequency_response_line_graph
146 public:
147 /// These are pointers to the ins, outs, params arrays in the main class
148 typedef filter_module_with_inertia inertia_filter_module;
149 using audio_module<Metadata>::ins;
150 using audio_module<Metadata>::outs;
151 using audio_module<Metadata>::params;
153 dsp::inertia<dsp::exponential_ramp> inertia_cutoff, inertia_resonance, inertia_gain;
154 dsp::once_per_n timer;
155 bool is_active;
156 mutable volatile int last_generation, last_calculated_generation;
158 filter_module_with_inertia(float **ins, float **outs, float **params)
159 : inertia_cutoff(dsp::exponential_ramp(128), 20)
160 , inertia_resonance(dsp::exponential_ramp(128), 20)
161 , inertia_gain(dsp::exponential_ramp(128), 1.0)
162 , timer(128)
163 , is_active(false)
164 , last_generation(-1)
165 , last_calculated_generation(-2)
168 void calculate_filter()
170 float freq = inertia_cutoff.get_last();
171 // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
172 // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
173 float q = inertia_resonance.get_last();
174 int mode = dsp::fastf2i_drm(*params[Metadata::par_mode]);
175 // printf("freq = %f q = %f mode = %d\n", freq, q, mode);
177 int inertia = dsp::fastf2i_drm(*params[Metadata::par_inertia]);
178 if (inertia != inertia_cutoff.ramp.length()) {
179 inertia_cutoff.ramp.set_length(inertia);
180 inertia_resonance.ramp.set_length(inertia);
181 inertia_gain.ramp.set_length(inertia);
184 FilterClass::calculate_filter(freq, q, mode, inertia_gain.get_last());
187 virtual void params_changed()
189 calculate_filter();
192 void on_timer()
194 int gen = last_generation;
195 inertia_cutoff.step();
196 inertia_resonance.step();
197 inertia_gain.step();
198 calculate_filter();
199 last_calculated_generation = gen;
202 void activate()
204 params_changed();
205 FilterClass::filter_activate();
206 timer = dsp::once_per_n(FilterClass::srate / 1000);
207 timer.start();
208 is_active = true;
211 void set_sample_rate(uint32_t sr)
213 FilterClass::srate = sr;
217 void deactivate()
219 is_active = false;
222 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
223 // printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]);
224 uint32_t ostate = 0;
225 numsamples += offset;
226 while(offset < numsamples) {
227 uint32_t numnow = numsamples - offset;
228 // if inertia's inactive, we can calculate the whole buffer at once
229 if (inertia_cutoff.active() || inertia_resonance.active() || inertia_gain.active())
230 numnow = timer.get(numnow);
232 if (outputs_mask & 1) {
233 ostate |= FilterClass::process_channel(0, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1);
235 if (outputs_mask & 2) {
236 ostate |= FilterClass::process_channel(1, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2);
239 if (timer.elapsed()) {
240 on_timer();
242 offset += numnow;
244 return ostate;
246 float freq_gain(int index, double freq) const {
247 return FilterClass::freq_gain(index, (float)freq, (float)FilterClass::srate);
251 /**********************************************************************
252 * FILTER by Krzysztof Foltman
253 **********************************************************************/
255 class filter_audio_module:
256 public filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>
258 mutable float old_cutoff, old_resonance, old_mode;
259 public:
260 filter_audio_module()
261 : filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>(ins, outs, params)
263 last_generation = 0;
264 old_mode = old_resonance = old_cutoff = -1;
265 redraw_graph = true;
267 void params_changed()
269 inertia_cutoff.set_inertia(*params[par_cutoff]);
270 inertia_resonance.set_inertia(*params[par_resonance]);
271 inertia_filter_module::params_changed();
272 redraw_graph = true;
276 /**********************************************************************
277 * FILTERKLAVIER by Hans Baier
278 **********************************************************************/
280 class filterclavier_audio_module:
281 public filter_module_with_inertia<dsp::biquad_filter_module, filterclavier_metadata>
283 using audio_module<filterclavier_metadata>::ins;
284 using audio_module<filterclavier_metadata>::outs;
285 using audio_module<filterclavier_metadata>::params;
287 const float min_gain;
288 const float max_gain;
290 int last_note;
291 int last_velocity;
292 public:
293 filterclavier_audio_module();
294 void params_changed();
295 void activate();
296 void set_sample_rate(uint32_t sr);
297 void deactivate();
299 /// MIDI control
300 virtual void note_on(int channel, int note, int vel);
301 virtual void note_off(int channel, int note, int vel);
302 private:
303 void adjust_gain_according_to_filter_mode(int velocity);
306 /**********************************************************************
307 * EMPHASIS by Damien Zammit
308 **********************************************************************/
310 class emphasis_audio_module: public audio_module<emphasis_metadata>, public frequency_response_line_graph {
311 public:
312 dsp::riaacurve riaacurvL, riaacurvR;
313 dsp::bypass bypass;
314 int mode, type, bypass_;
315 typedef std::complex<double> cfloat;
316 uint32_t srate;
317 bool is_active;
318 vumeters meters;
319 emphasis_audio_module();
320 void activate();
321 void deactivate();
322 void params_changed();
323 void set_sample_rate(uint32_t sr)
325 srate = sr;
326 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
327 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
328 meters.init(params, meter, clip, 4, sr);
330 virtual float freq_gain(int index, double freq) const {
331 return riaacurvL.freq_gain(freq, (float)srate);
333 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
334 virtual bool get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
335 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
338 /**********************************************************************
339 * CROSSOVER MODULES by Markus Schmidt
340 **********************************************************************/
342 template<class XoverBaseClass>
343 class xover_audio_module: public audio_module<XoverBaseClass>, public frequency_response_line_graph {
344 public:
345 typedef audio_module<XoverBaseClass> AM;
346 using AM::ins;
347 using AM::outs;
348 using AM::params;
349 using AM::in_count;
350 using AM::out_count;
351 using AM::param_count;
352 using AM::bands;
353 using AM::channels;
354 enum { params_per_band = AM::param_level2 - AM::param_level1 };
355 uint32_t srate;
356 bool is_active;
357 float * buffer;
358 float in[channels];
359 unsigned int pos;
360 unsigned int buffer_size;
361 int last_peak;
362 static inline float sign(float x) {
363 if(x < 0) return -1.f;
364 if(x > 0) return 1.f;
365 return 0.f;
367 vumeters meters;
368 dsp::crossover crossover;
369 xover_audio_module();
370 ~xover_audio_module();
371 void activate();
372 void deactivate();
373 void params_changed();
374 void set_sample_rate(uint32_t sr);
375 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
376 bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
377 bool get_layers(int index, int generation, unsigned int &layers) const;
380 typedef xover_audio_module<xover2_metadata> xover2_audio_module;
381 typedef xover_audio_module<xover3_metadata> xover3_audio_module;
382 typedef xover_audio_module<xover4_metadata> xover4_audio_module;
384 /**********************************************************************
385 * VOCODER by Markus Schmidt & Christian Holschuh
386 **********************************************************************/
388 class vocoder_audio_module: public audio_module<vocoder_metadata>, public frequency_response_line_graph {
389 public:
390 int bands, bands_old, order;
391 float order_old;
392 uint32_t srate;
393 bool is_active;
394 static const int maxorder = 8;
395 dsp::biquad_d2 detector[2][maxorder][32], modulator[2][maxorder][32];
396 dsp::bypass bypass;
397 double env_mods[2][32];
398 vumeters meters;
399 analyzer _analyzer;
400 double attack, release, fcoeff, log2_;
401 vocoder_audio_module();
402 void activate();
403 void deactivate();
404 void params_changed();
405 int get_solo() const;
406 void set_sample_rate(uint32_t sr)
408 srate = sr;
409 _analyzer.set_sample_rate(sr);
410 int meter[] = {param_carrier_inL, param_carrier_inR, param_mod_inL, param_mod_inR, param_outL, param_outR};
411 int clip[] = {param_carrier_clip_inL, param_carrier_clip_inR, param_mod_clip_inL, param_mod_clip_inR, param_clip_outL, param_clip_outR};
412 meters.init(params, meter, clip, 6, sr);
414 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
415 virtual bool get_layers(int index, int generation, unsigned int &layers) const;
416 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
419 /**********************************************************************
420 * ENVELOPE FILTER by Markus Schmidt
421 **********************************************************************/
423 class envelopefilter_audio_module: public audio_module<envelopefilter_metadata>, public dsp::biquad_filter_module,
424 public frequency_response_line_graph
426 public:
427 uint32_t srate;
428 bool is_active;
430 dsp::bypass bypass;
431 vumeters meters;
433 float envelope, attack, release, envelope_old, attack_old, release_old, q_old;
434 float gain, gain_old, upper, upper_old, lower, lower_old;
435 float coefa, coefb, coefz;
436 int mode, mode_old;
438 envelopefilter_audio_module()
440 envelope = envelope_old = 0;
441 lower = 10; lower_old = 0;
442 upper = 10; upper_old = 0;
443 gain = 1; gain_old = 0;
444 attack = release = attack_old = release_old = -1;
445 mode = mode_old = q_old = 0;
446 coefa = coefb = 0;
447 coefz = 2;
450 void activate()
452 params_changed();
453 filter_activate();
454 is_active = true;
457 void deactivate()
459 is_active = false;
462 void set_sample_rate(uint32_t sr)
464 srate = sr;
465 dsp::biquad_filter_module::srate = sr;
466 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
467 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
468 meters.init(params, meter, clip, 4, sr);
471 void params_changed()
473 if (*params[param_attack] != attack_old) {
474 attack_old = *params[param_attack];
475 attack = exp(log(0.01)/( attack_old * srate * 0.001));
477 if (*params[param_release] != release_old) {
478 release_old = *params[param_release];
479 release = exp(log(0.01)/( release_old * srate * 0.001));
481 if (*params[param_mode] != mode_old) {
482 mode = dsp::fastf2i_drm(*params[param_mode]);
483 mode_old = *params[param_mode];
484 calc_filter();
486 if (*params[param_q] != q_old) {
487 q_old = *params[param_q];
488 calc_filter();
490 if (*params[param_upper] != upper_old) {
491 upper = *params[param_upper];
492 upper_old = *params[param_upper];
493 calc_coef();
494 calc_filter();
496 if (*params[param_lower] != lower_old) {
497 lower = *params[param_lower];
498 lower_old = *params[param_lower];
499 calc_coef();
500 calc_filter();
502 if (*params[param_gain] != gain_old) {
503 gain = *params[param_gain];
504 gain_old = *params[param_gain];
505 calc_filter();
509 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
511 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
512 uint32_t end = numsamples + offset;
513 while(offset < end) {
514 float D;
515 if (*params[param_sidechain] > 0.5)
516 D = std::max(fabs(ins[2][offset]), fabs(ins[3][offset])) * *params[param_gain];
517 else
518 D = std::max(fabs(ins[0][offset]), fabs(ins[1][offset])) * *params[param_gain];
520 // advance envelope
521 envelope = (D > envelope ? attack : release) * (envelope - D) + D;
522 if (envelope != envelope_old) {
523 envelope_old = envelope;
524 redraw_graph = true;
525 dsp::biquad_filter_module::calculate_filter(get_freq(envelope), *params[param_q], mode, 1.0);
528 if(bypassed) {
529 outs[0][offset] = ins[0][offset];
530 outs[1][offset] = ins[1][offset];
531 float values[] = {0, 0, 0, 0};
532 meters.process(values);
533 } else {
534 const float inL = ins[0][offset] * *params[param_level_in];
535 const float inR = ins[1][offset] * *params[param_level_in];
536 float outL = outs[0][offset];
537 float outR = outs[1][offset];
539 // process filters
540 dsp::biquad_filter_module::process_channel(0, &inL, &outL, 1, inputs_mask & 1);
541 dsp::biquad_filter_module::process_channel(1, &inR, &outR, 1, inputs_mask & 2);
543 // mix and out level
544 outs[0][offset] = (outL * *params[param_mix] + inL * (*params[param_mix] * -1 + 1)) * *params[param_level_out];
545 outs[1][offset] = (outR * *params[param_mix] + inR * (*params[param_mix] * -1 + 1)) * *params[param_level_out];
547 // meters
548 float values[] = {inL, inR, outs[0][offset], outs[1][offset]};
549 meters.process(values);
551 // step on
552 offset += 1;
554 if (bypassed)
555 bypass.crossfade(ins, outs, 2, offset - numsamples, numsamples);
556 meters.fall(numsamples);
557 return outputs_mask;
560 float freq_gain(int index, double freq) const {
561 return dsp::biquad_filter_module::freq_gain(index, (float)freq, (float)srate);
564 void calc_filter ()
566 redraw_graph = true;
567 dsp::biquad_filter_module::calculate_filter(get_freq(envelope), *params[param_q], mode, 1.0);
570 void calc_coef ()
572 coefa = log10(upper) - log10(lower);
573 coefb = log10(lower);
576 float get_freq(float envelope) const {
577 float diff = upper - lower;
578 float freq = pow(10, coefa * envelope + coefb);
579 if (diff < 0)
580 return std::max(upper, std::min(lower, freq));
581 return std::min(upper, std::max(lower, freq));
588 #endif