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
;
58 float lp_mode_old
, lp_freq_old
;
59 float ls_level_old
, ls_freq_old
;
60 float hs_level_old
, hs_freq_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 void set_sample_rate(uint32_t 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 /**********************************************************************
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();
126 dsp::bypass eq_switch
;
128 equalizer30band_audio_module();
129 ~equalizer30band_audio_module();
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
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
;
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)
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()
194 int gen
= last_generation
;
195 inertia_cutoff
.step();
196 inertia_resonance
.step();
199 last_calculated_generation
= gen
;
205 FilterClass::filter_activate();
206 timer
= dsp::once_per_n(FilterClass::srate
/ 1000);
211 void set_sample_rate(uint32_t sr
)
213 FilterClass::srate
= sr
;
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]);
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()) {
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
;
260 filter_audio_module()
261 : filter_module_with_inertia
<dsp::biquad_filter_module
, filter_metadata
>(ins
, outs
, params
)
264 old_mode
= old_resonance
= old_cutoff
= -1;
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();
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
;
293 filterclavier_audio_module();
294 void params_changed();
296 void set_sample_rate(uint32_t sr
);
300 virtual void note_on(int channel
, int note
, int vel
);
301 virtual void note_off(int channel
, int note
, int vel
);
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
{
312 dsp::riaacurve riaacurvL
, riaacurvR
;
314 int mode
, type
, bypass_
;
315 typedef std::complex<double> cfloat
;
319 emphasis_audio_module();
322 void params_changed();
323 void set_sample_rate(uint32_t 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
{
345 typedef audio_module
<XoverBaseClass
> AM
;
351 using AM::param_count
;
354 enum { params_per_band
= AM::param_level2
- AM::param_level1
};
360 unsigned int buffer_size
;
362 static inline float sign(float x
) {
363 if(x
< 0) return -1.f
;
364 if(x
> 0) return 1.f
;
368 dsp::crossover crossover
;
369 xover_audio_module();
370 ~xover_audio_module();
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
{
390 int bands
, bands_old
, order
;
394 static const int maxorder
= 8;
395 dsp::biquad_d2 detector
[2][maxorder
][32], modulator
[2][maxorder
][32];
397 double env_mods
[2][32];
400 double attack
, release
, fcoeff
, log2_
;
401 vocoder_audio_module();
404 void params_changed();
405 int get_solo() const;
406 void set_sample_rate(uint32_t 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
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
;
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;
462 void set_sample_rate(uint32_t 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
];
486 if (*params
[param_q
] != q_old
) {
487 q_old
= *params
[param_q
];
490 if (*params
[param_upper
] != upper_old
) {
491 upper
= *params
[param_upper
];
492 upper_old
= *params
[param_upper
];
496 if (*params
[param_lower
] != lower_old
) {
497 lower
= *params
[param_lower
];
498 lower_old
= *params
[param_lower
];
502 if (*params
[param_gain
] != gain_old
) {
503 gain
= *params
[param_gain
];
504 gain_old
= *params
[param_gain
];
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
) {
515 if (*params
[param_sidechain
] > 0.5)
516 D
= std::max(fabs(ins
[2][offset
]), fabs(ins
[3][offset
])) * *params
[param_gain
];
518 D
= std::max(fabs(ins
[0][offset
]), fabs(ins
[1][offset
])) * *params
[param_gain
];
521 envelope
= (D
> envelope
? attack
: release
) * (envelope
- D
) + D
;
522 if (envelope
!= envelope_old
) {
523 envelope_old
= envelope
;
525 dsp::biquad_filter_module::calculate_filter(get_freq(envelope
), *params
[param_q
], mode
, 1.0);
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
);
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
];
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);
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
];
548 float values
[] = {inL
, inR
, outs
[0][offset
], outs
[1][offset
]};
549 meters
.process(values
);
555 bypass
.crossfade(ins
, outs
, 2, offset
- numsamples
, numsamples
);
556 meters
.fall(numsamples
);
560 float freq_gain(int index
, double freq
) const {
561 return dsp::biquad_filter_module::freq_gain(index
, (float)freq
, (float)srate
);
567 dsp::biquad_filter_module::calculate_filter(get_freq(envelope
), *params
[param_q
], mode
, 1.0);
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
);
580 return std::max(upper
, std::min(lower
, freq
));
581 return std::min(upper
, std::max(lower
, freq
));