LineGraph: z axis for lo and hi pass handles
[calf.git] / src / calf / modules_filter.h
blob03951584e5f8ae1f48ead476dcaf549a6076fd7c
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, hp_q_old;
58 float lp_mode_old, lp_freq_old, lp_q_old;
59 float ls_level_old, ls_freq_old, ls_q_old;
60 float hs_level_old, hs_freq_old, hs_q_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 string get_crosshair_label(int x, int y, int sx, int sy, float q, int dB, int name, int note, int cents) const;
90 void set_sample_rate(uint32_t sr)
92 srate = sr;
93 _analyzer.set_sample_rate(sr);
94 int meter[] = {AM::param_meter_inL, AM::param_meter_inR, AM::param_meter_outL, AM::param_meter_outR};
95 int clip[] = {AM::param_clip_inL, AM::param_clip_inR, AM::param_clip_outL, AM::param_clip_outR};
96 meters.init(params, meter, clip, 4, sr);
98 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
101 typedef equalizerNband_audio_module<equalizer5band_metadata, false> equalizer5band_audio_module;
102 typedef equalizerNband_audio_module<equalizer8band_metadata, true> equalizer8band_audio_module;
103 typedef equalizerNband_audio_module<equalizer12band_metadata, true> equalizer12band_audio_module;
105 /**********************************************************************
106 * EQUALIZER 30 BAND
107 **********************************************************************/
109 class equalizer30band_audio_module: public audio_module<equalizer30band_metadata> {
110 orfanidis_eq::conversions conv;
111 orfanidis_eq::freq_grid fg;
112 std::vector<orfanidis_eq::eq2*> eq_arrL;
113 std::vector<orfanidis_eq::eq2*> eq_arrR;
115 orfanidis_eq::filter_type flt_type;
116 orfanidis_eq::filter_type flt_type_old;
118 dsp::switcher<orfanidis_eq::filter_type> swL;
119 dsp::switcher<orfanidis_eq::filter_type> swR;
121 bool is_freq_grid_init;
122 void set_freq_grid();
124 public:
125 uint32_t srate;
126 bool is_active;
127 dsp::bypass bypass;
128 dsp::bypass eq_switch;
129 vumeters meters;
130 equalizer30band_audio_module();
131 ~equalizer30band_audio_module();
133 void activate();
134 void deactivate();
135 void params_changed();
136 void set_sample_rate(uint32_t sr);
137 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
140 /**********************************************************************
141 * FILTER MODULE by Krzysztof Foltman
142 **********************************************************************/
144 template<typename FilterClass, typename Metadata>
145 class filter_module_with_inertia: public audio_module<Metadata>, public FilterClass,
146 public frequency_response_line_graph
148 public:
149 /// These are pointers to the ins, outs, params arrays in the main class
150 typedef filter_module_with_inertia inertia_filter_module;
151 using audio_module<Metadata>::ins;
152 using audio_module<Metadata>::outs;
153 using audio_module<Metadata>::params;
155 dsp::inertia<dsp::exponential_ramp> inertia_cutoff, inertia_resonance, inertia_gain;
156 dsp::once_per_n timer;
157 bool is_active;
158 mutable volatile int last_generation, last_calculated_generation;
160 filter_module_with_inertia(float **ins, float **outs, float **params)
161 : inertia_cutoff(dsp::exponential_ramp(128), 20)
162 , inertia_resonance(dsp::exponential_ramp(128), 20)
163 , inertia_gain(dsp::exponential_ramp(128), 1.0)
164 , timer(128)
165 , is_active(false)
166 , last_generation(-1)
167 , last_calculated_generation(-2)
170 void calculate_filter()
172 float freq = inertia_cutoff.get_last();
173 // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
174 // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
175 float q = inertia_resonance.get_last();
176 int mode = dsp::fastf2i_drm(*params[Metadata::par_mode]);
177 // printf("freq = %f q = %f mode = %d\n", freq, q, mode);
179 int inertia = dsp::fastf2i_drm(*params[Metadata::par_inertia]);
180 if (inertia != inertia_cutoff.ramp.length()) {
181 inertia_cutoff.ramp.set_length(inertia);
182 inertia_resonance.ramp.set_length(inertia);
183 inertia_gain.ramp.set_length(inertia);
186 FilterClass::calculate_filter(freq, q, mode, inertia_gain.get_last());
189 virtual void params_changed()
191 calculate_filter();
194 void on_timer()
196 int gen = last_generation;
197 inertia_cutoff.step();
198 inertia_resonance.step();
199 inertia_gain.step();
200 calculate_filter();
201 last_calculated_generation = gen;
204 void activate()
206 params_changed();
207 FilterClass::filter_activate();
208 timer = dsp::once_per_n(FilterClass::srate / 1000);
209 timer.start();
210 is_active = true;
213 void set_sample_rate(uint32_t sr)
215 FilterClass::srate = sr;
219 void deactivate()
221 is_active = false;
224 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
225 // printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]);
226 uint32_t ostate = 0;
227 numsamples += offset;
228 while(offset < numsamples) {
229 uint32_t numnow = numsamples - offset;
230 // if inertia's inactive, we can calculate the whole buffer at once
231 if (inertia_cutoff.active() || inertia_resonance.active() || inertia_gain.active())
232 numnow = timer.get(numnow);
234 if (outputs_mask & 1) {
235 ostate |= FilterClass::process_channel(0, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1);
237 if (outputs_mask & 2) {
238 ostate |= FilterClass::process_channel(1, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2);
241 if (timer.elapsed()) {
242 on_timer();
244 offset += numnow;
246 return ostate;
248 float freq_gain(int index, double freq) const {
249 return FilterClass::freq_gain(index, (float)freq, (float)FilterClass::srate);
253 /**********************************************************************
254 * FILTER by Krzysztof Foltman
255 **********************************************************************/
257 class filter_audio_module:
258 public filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>
260 mutable float old_cutoff, old_resonance, old_mode;
261 public:
262 filter_audio_module()
263 : filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>(ins, outs, params)
265 last_generation = 0;
266 old_mode = old_resonance = old_cutoff = -1;
267 redraw_graph = true;
269 void params_changed()
271 inertia_cutoff.set_inertia(*params[par_cutoff]);
272 inertia_resonance.set_inertia(*params[par_resonance]);
273 inertia_filter_module::params_changed();
274 redraw_graph = true;
278 /**********************************************************************
279 * FILTERKLAVIER by Hans Baier
280 **********************************************************************/
282 class filterclavier_audio_module:
283 public filter_module_with_inertia<dsp::biquad_filter_module, filterclavier_metadata>
285 using audio_module<filterclavier_metadata>::ins;
286 using audio_module<filterclavier_metadata>::outs;
287 using audio_module<filterclavier_metadata>::params;
289 const float min_gain;
290 const float max_gain;
292 int last_note;
293 int last_velocity;
294 public:
295 filterclavier_audio_module();
296 void params_changed();
297 void activate();
298 void set_sample_rate(uint32_t sr);
299 void deactivate();
301 /// MIDI control
302 virtual void note_on(int channel, int note, int vel);
303 virtual void note_off(int channel, int note, int vel);
304 private:
305 void adjust_gain_according_to_filter_mode(int velocity);
308 /**********************************************************************
309 * EMPHASIS by Damien Zammit
310 **********************************************************************/
312 class emphasis_audio_module: public audio_module<emphasis_metadata>, public frequency_response_line_graph {
313 public:
314 dsp::riaacurve riaacurvL, riaacurvR;
315 dsp::bypass bypass;
316 int mode, type, bypass_;
317 typedef std::complex<double> cfloat;
318 uint32_t srate;
319 bool is_active;
320 vumeters meters;
321 emphasis_audio_module();
322 void activate();
323 void deactivate();
324 void params_changed();
325 void set_sample_rate(uint32_t sr)
327 srate = sr;
328 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
329 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
330 meters.init(params, meter, clip, 4, sr);
332 virtual float freq_gain(int index, double freq) const {
333 return riaacurvL.freq_gain(freq, (float)srate);
335 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
336 virtual bool get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
337 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
340 /**********************************************************************
341 * CROSSOVER MODULES by Markus Schmidt
342 **********************************************************************/
344 template<class XoverBaseClass>
345 class xover_audio_module: public audio_module<XoverBaseClass>, public frequency_response_line_graph {
346 public:
347 typedef audio_module<XoverBaseClass> AM;
348 using AM::ins;
349 using AM::outs;
350 using AM::params;
351 using AM::in_count;
352 using AM::out_count;
353 using AM::param_count;
354 using AM::bands;
355 using AM::channels;
356 enum { params_per_band = AM::param_level2 - AM::param_level1 };
357 uint32_t srate;
358 bool is_active;
359 float * buffer;
360 float in[channels];
361 unsigned int pos;
362 unsigned int buffer_size;
363 int last_peak;
364 static inline float sign(float x) {
365 if(x < 0) return -1.f;
366 if(x > 0) return 1.f;
367 return 0.f;
369 vumeters meters;
370 dsp::crossover crossover;
371 xover_audio_module();
372 ~xover_audio_module();
373 void activate();
374 void deactivate();
375 void params_changed();
376 void set_sample_rate(uint32_t sr);
377 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
378 bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
379 bool get_layers(int index, int generation, unsigned int &layers) const;
382 typedef xover_audio_module<xover2_metadata> xover2_audio_module;
383 typedef xover_audio_module<xover3_metadata> xover3_audio_module;
384 typedef xover_audio_module<xover4_metadata> xover4_audio_module;
386 /**********************************************************************
387 * VOCODER by Markus Schmidt & Christian Holschuh
388 **********************************************************************/
390 class vocoder_audio_module: public audio_module<vocoder_metadata>, public frequency_response_line_graph {
391 public:
392 int bands, bands_old, order;
393 float order_old;
394 uint32_t srate;
395 bool is_active;
396 static const int maxorder = 8;
397 dsp::biquad_d2 detector[2][maxorder][32], modulator[2][maxorder][32];
398 dsp::bypass bypass;
399 double env_mods[2][32];
400 vumeters meters;
401 analyzer _analyzer;
402 double attack, release, fcoeff, log2_;
403 vocoder_audio_module();
404 void activate();
405 void deactivate();
406 void params_changed();
407 int get_solo() const;
408 void set_sample_rate(uint32_t sr)
410 srate = sr;
411 _analyzer.set_sample_rate(sr);
412 int meter[] = {param_carrier_inL, param_carrier_inR, param_mod_inL, param_mod_inR, param_outL, param_outR};
413 int clip[] = {param_carrier_clip_inL, param_carrier_clip_inR, param_mod_clip_inL, param_mod_clip_inR, param_clip_outL, param_clip_outR};
414 meters.init(params, meter, clip, 6, sr);
416 virtual bool get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const;
417 virtual bool get_layers(int index, int generation, unsigned int &layers) const;
418 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
421 /**********************************************************************
422 * ENVELOPE FILTER by Markus Schmidt
423 **********************************************************************/
425 class envelopefilter_audio_module: public audio_module<envelopefilter_metadata>, public dsp::biquad_filter_module,
426 public frequency_response_line_graph
428 public:
429 uint32_t srate;
430 bool is_active;
432 dsp::bypass bypass;
433 vumeters meters;
435 float envelope, attack, release, envelope_old, attack_old, release_old, q_old;
436 float gain, gain_old, upper, upper_old, lower, lower_old;
437 float coefa, coefb, coefz;
438 int mode, mode_old;
440 envelopefilter_audio_module()
442 envelope = envelope_old = 0;
443 lower = 10; lower_old = 0;
444 upper = 10; upper_old = 0;
445 gain = 1; gain_old = 0;
446 attack = release = attack_old = release_old = -1;
447 mode = mode_old = q_old = 0;
448 coefa = coefb = 0;
449 coefz = 2;
452 void activate()
454 params_changed();
455 filter_activate();
456 is_active = true;
459 void deactivate()
461 is_active = false;
464 void set_sample_rate(uint32_t sr)
466 srate = sr;
467 dsp::biquad_filter_module::srate = sr;
468 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
469 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
470 meters.init(params, meter, clip, 4, sr);
473 void params_changed()
475 if (*params[param_attack] != attack_old) {
476 attack_old = *params[param_attack];
477 attack = exp(log(0.01)/( attack_old * srate * 0.001));
479 if (*params[param_release] != release_old) {
480 release_old = *params[param_release];
481 release = exp(log(0.01)/( release_old * srate * 0.001));
483 if (*params[param_mode] != mode_old) {
484 mode = dsp::fastf2i_drm(*params[param_mode]);
485 mode_old = *params[param_mode];
486 calc_filter();
488 if (*params[param_q] != q_old) {
489 q_old = *params[param_q];
490 calc_filter();
492 if (*params[param_upper] != upper_old) {
493 upper = *params[param_upper];
494 upper_old = *params[param_upper];
495 calc_coef();
496 calc_filter();
498 if (*params[param_lower] != lower_old) {
499 lower = *params[param_lower];
500 lower_old = *params[param_lower];
501 calc_coef();
502 calc_filter();
504 if (*params[param_gain] != gain_old) {
505 gain = *params[param_gain];
506 gain_old = *params[param_gain];
507 calc_filter();
511 uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
513 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
514 uint32_t end = numsamples + offset;
515 while(offset < end) {
516 float D;
517 if (*params[param_sidechain] > 0.5)
518 D = std::max(fabs(ins[2][offset]), fabs(ins[3][offset])) * *params[param_gain];
519 else
520 D = std::max(fabs(ins[0][offset]), fabs(ins[1][offset])) * *params[param_gain];
522 // advance envelope
523 envelope = std::min(1.f, (D > envelope ? attack : release) * (envelope - D) + D);
524 if (envelope != envelope_old) {
525 envelope_old = envelope;
526 redraw_graph = true;
527 dsp::biquad_filter_module::calculate_filter(get_freq(envelope), *params[param_q], mode, 1.0);
530 if(bypassed) {
531 outs[0][offset] = ins[0][offset];
532 outs[1][offset] = ins[1][offset];
533 float values[] = {0, 0, 0, 0};
534 meters.process(values);
535 } else {
536 const float inL = ins[0][offset] * *params[param_level_in];
537 const float inR = ins[1][offset] * *params[param_level_in];
538 float outL = outs[0][offset];
539 float outR = outs[1][offset];
541 // process filters
542 dsp::biquad_filter_module::process_channel(0, &inL, &outL, 1, inputs_mask & 1);
543 dsp::biquad_filter_module::process_channel(1, &inR, &outR, 1, inputs_mask & 2);
545 // mix and out level
546 outs[0][offset] = (outL * *params[param_mix] + inL * (*params[param_mix] * -1 + 1)) * *params[param_level_out];
547 outs[1][offset] = (outR * *params[param_mix] + inR * (*params[param_mix] * -1 + 1)) * *params[param_level_out];
549 // meters
550 float values[] = {inL, inR, outs[0][offset], outs[1][offset]};
551 meters.process(values);
553 // step on
554 offset += 1;
556 if (bypassed)
557 bypass.crossfade(ins, outs, 2, offset - numsamples, numsamples);
558 meters.fall(numsamples);
559 return outputs_mask;
562 float freq_gain(int index, double freq) const {
563 return dsp::biquad_filter_module::freq_gain(index, (float)freq, (float)srate);
566 void calc_filter ()
568 redraw_graph = true;
569 dsp::biquad_filter_module::calculate_filter(get_freq(envelope), *params[param_q], mode, 1.0);
572 void calc_coef ()
574 coefa = log10(upper) - log10(lower);
575 coefb = log10(lower);
578 float get_freq(float envelope) const {
579 float diff = upper - lower;
580 float env = pow(envelope, pow(2, *params[param_response] * -2));
581 float freq = pow(10, coefa * env + coefb);
582 if (diff < 0)
583 return std::max(upper, std::min(lower, freq));
584 return std::min(upper, std::max(lower, freq));
591 #endif