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
31 #include "plugin_tools.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
{
46 typedef audio_module
<BaseClass
> AM
;
52 using AM::param_count
;
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
;
63 float p_level_old
[PeakBands
], p_freq_old
[PeakBands
], p_q_old
[PeakBands
];
64 mutable float old_params_for_graph
[graph_param_count
];
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
];
72 mutable int last_peak
;
73 inline void process_hplp(float &left
, float &right
);
75 typedef std::complex<double> cfloat
;
78 mutable volatile int last_generation
, last_calculated_generation
;
79 equalizerNband_audio_module();
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
)
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 /**********************************************************************
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();
128 dsp::bypass eq_switch
;
130 equalizer30band_audio_module();
131 ~equalizer30band_audio_module();
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
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
;
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)
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()
196 int gen
= last_generation
;
197 inertia_cutoff
.step();
198 inertia_resonance
.step();
201 last_calculated_generation
= gen
;
207 FilterClass::filter_activate();
208 timer
= dsp::once_per_n(FilterClass::srate
/ 1000);
213 void set_sample_rate(uint32_t sr
)
215 FilterClass::srate
= sr
;
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]);
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()) {
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
;
262 filter_audio_module()
263 : filter_module_with_inertia
<dsp::biquad_filter_module
, filter_metadata
>(ins
, outs
, params
)
266 old_mode
= old_resonance
= old_cutoff
= -1;
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();
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
;
295 filterclavier_audio_module();
296 void params_changed();
298 void set_sample_rate(uint32_t sr
);
302 virtual void note_on(int channel
, int note
, int vel
);
303 virtual void note_off(int channel
, int note
, int vel
);
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
{
314 dsp::riaacurve riaacurvL
, riaacurvR
;
316 int mode
, type
, bypass_
;
317 typedef std::complex<double> cfloat
;
321 emphasis_audio_module();
324 void params_changed();
325 void set_sample_rate(uint32_t 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
{
347 typedef audio_module
<XoverBaseClass
> AM
;
353 using AM::param_count
;
356 enum { params_per_band
= AM::param_level2
- AM::param_level1
};
362 unsigned int buffer_size
;
364 static inline float sign(float x
) {
365 if(x
< 0) return -1.f
;
366 if(x
> 0) return 1.f
;
370 dsp::crossover crossover
;
371 xover_audio_module();
372 ~xover_audio_module();
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
{
392 int bands
, bands_old
, order
;
396 static const int maxorder
= 8;
397 dsp::biquad_d2 detector
[2][maxorder
][32], modulator
[2][maxorder
][32];
399 double env_mods
[2][32];
402 double attack
, release
, fcoeff
, log2_
;
403 vocoder_audio_module();
406 void params_changed();
407 int get_solo() const;
408 void set_sample_rate(uint32_t 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
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
;
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;
464 void set_sample_rate(uint32_t 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
];
488 if (*params
[param_q
] != q_old
) {
489 q_old
= *params
[param_q
];
492 if (*params
[param_upper
] != upper_old
) {
493 upper
= *params
[param_upper
];
494 upper_old
= *params
[param_upper
];
498 if (*params
[param_lower
] != lower_old
) {
499 lower
= *params
[param_lower
];
500 lower_old
= *params
[param_lower
];
504 if (*params
[param_gain
] != gain_old
) {
505 gain
= *params
[param_gain
];
506 gain_old
= *params
[param_gain
];
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
) {
517 if (*params
[param_sidechain
] > 0.5)
518 D
= std::max(fabs(ins
[2][offset
]), fabs(ins
[3][offset
])) * *params
[param_gain
];
520 D
= std::max(fabs(ins
[0][offset
]), fabs(ins
[1][offset
])) * *params
[param_gain
];
523 envelope
= std::min(1.f
, (D
> envelope
? attack
: release
) * (envelope
- D
) + D
);
524 if (envelope
!= envelope_old
) {
525 envelope_old
= envelope
;
527 dsp::biquad_filter_module::calculate_filter(get_freq(envelope
), *params
[param_q
], mode
, 1.0);
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
);
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
];
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);
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
];
550 float values
[] = {inL
, inR
, outs
[0][offset
], outs
[1][offset
]};
551 meters
.process(values
);
557 bypass
.crossfade(ins
, outs
, 2, offset
- numsamples
, numsamples
);
558 meters
.fall(numsamples
);
562 float freq_gain(int index
, double freq
) const {
563 return dsp::biquad_filter_module::freq_gain(index
, (float)freq
, (float)srate
);
569 dsp::biquad_filter_module::calculate_filter(get_freq(envelope
), *params
[param_q
], mode
, 1.0);
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
);
583 return std::max(upper
, std::min(lower
, freq
));
584 return std::min(upper
, std::max(lower
, freq
));