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 namespace calf_plugins
{
37 /**********************************************************************
38 * EQUALIZER N BAND by Markus Schmidt and Krzysztof Foltman
39 **********************************************************************/
41 template<class BaseClass
, bool has_lphp
>
42 class equalizerNband_audio_module
: public audio_module
<BaseClass
>, public frequency_response_line_graph
{
44 typedef audio_module
<BaseClass
> AM
;
50 using AM::param_count
;
54 enum { graph_param_count
= BaseClass::last_graph_param
- BaseClass::first_graph_param
+ 1, params_per_band
= AM::param_p2_active
- AM::param_p1_active
};
55 float hp_mode_old
, hp_freq_old
;
56 float lp_mode_old
, lp_freq_old
;
57 float ls_level_old
, ls_freq_old
;
58 float hs_level_old
, hs_freq_old
;
61 float p_level_old
[PeakBands
], p_freq_old
[PeakBands
], p_q_old
[PeakBands
];
62 mutable float old_params_for_graph
[graph_param_count
];
64 CalfEqMode hp_mode
, lp_mode
;
65 dsp::biquad_d2 hp
[3][2], lp
[3][2];
66 dsp::biquad_d2 lsL
, lsR
, hsL
, hsR
;
67 dsp::biquad_d2 pL
[PeakBands
], pR
[PeakBands
];
69 mutable int last_peak
;
70 inline void process_hplp(float &left
, float &right
);
72 typedef std::complex<double> cfloat
;
75 mutable volatile int last_generation
, last_calculated_generation
;
76 equalizerNband_audio_module();
80 void params_changed();
81 bool get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const;
82 bool get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const;
83 bool get_layers(int index
, int generation
, unsigned int &layers
) const;
84 float freq_gain(int index
, double freq
) const;
85 void set_sample_rate(uint32_t sr
)
88 _analyzer
.set_sample_rate(sr
);
89 int meter
[] = {AM::param_meter_inL
, AM::param_meter_inR
, AM::param_meter_outL
, AM::param_meter_outR
};
90 int clip
[] = {AM::param_clip_inL
, AM::param_clip_inR
, AM::param_clip_outL
, AM::param_clip_outR
};
91 meters
.init(params
, meter
, clip
, 4, sr
);
93 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
);
96 typedef equalizerNband_audio_module
<equalizer5band_metadata
, false> equalizer5band_audio_module
;
97 typedef equalizerNband_audio_module
<equalizer8band_metadata
, true> equalizer8band_audio_module
;
98 typedef equalizerNband_audio_module
<equalizer12band_metadata
, true> equalizer12band_audio_module
;
100 /**********************************************************************
101 * FILTER MODULE by Krzysztof Foltman
102 **********************************************************************/
104 template<typename FilterClass
, typename Metadata
>
105 class filter_module_with_inertia
: public audio_module
<Metadata
>, public FilterClass
,
106 public frequency_response_line_graph
109 /// These are pointers to the ins, outs, params arrays in the main class
110 typedef filter_module_with_inertia inertia_filter_module
;
111 using audio_module
<Metadata
>::ins
;
112 using audio_module
<Metadata
>::outs
;
113 using audio_module
<Metadata
>::params
;
115 dsp::inertia
<dsp::exponential_ramp
> inertia_cutoff
, inertia_resonance
, inertia_gain
;
116 dsp::once_per_n timer
;
118 mutable volatile int last_generation
, last_calculated_generation
;
120 filter_module_with_inertia(float **ins
, float **outs
, float **params
)
121 : inertia_cutoff(dsp::exponential_ramp(128), 20)
122 , inertia_resonance(dsp::exponential_ramp(128), 20)
123 , inertia_gain(dsp::exponential_ramp(128), 1.0)
126 , last_generation(-1)
127 , last_calculated_generation(-2)
130 void calculate_filter()
132 float freq
= inertia_cutoff
.get_last();
133 // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
134 // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
135 float q
= inertia_resonance
.get_last();
136 int mode
= dsp::fastf2i_drm(*params
[Metadata::par_mode
]);
137 // printf("freq = %f q = %f mode = %d\n", freq, q, mode);
139 int inertia
= dsp::fastf2i_drm(*params
[Metadata::par_inertia
]);
140 if (inertia
!= inertia_cutoff
.ramp
.length()) {
141 inertia_cutoff
.ramp
.set_length(inertia
);
142 inertia_resonance
.ramp
.set_length(inertia
);
143 inertia_gain
.ramp
.set_length(inertia
);
146 FilterClass::calculate_filter(freq
, q
, mode
, inertia_gain
.get_last());
149 virtual void params_changed()
156 int gen
= last_generation
;
157 inertia_cutoff
.step();
158 inertia_resonance
.step();
161 last_calculated_generation
= gen
;
167 FilterClass::filter_activate();
168 timer
= dsp::once_per_n(FilterClass::srate
/ 1000);
173 void set_sample_rate(uint32_t sr
)
175 FilterClass::srate
= sr
;
184 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
185 // printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]);
187 numsamples
+= offset
;
188 while(offset
< numsamples
) {
189 uint32_t numnow
= numsamples
- offset
;
190 // if inertia's inactive, we can calculate the whole buffer at once
191 if (inertia_cutoff
.active() || inertia_resonance
.active() || inertia_gain
.active())
192 numnow
= timer
.get(numnow
);
194 if (outputs_mask
& 1) {
195 ostate
|= FilterClass::process_channel(0, ins
[0] + offset
, outs
[0] + offset
, numnow
, inputs_mask
& 1);
197 if (outputs_mask
& 2) {
198 ostate
|= FilterClass::process_channel(1, ins
[1] + offset
, outs
[1] + offset
, numnow
, inputs_mask
& 2);
201 if (timer
.elapsed()) {
208 float freq_gain(int index
, double freq
) const {
209 return FilterClass::freq_gain(index
, (float)freq
, (float)FilterClass::srate
);
213 /**********************************************************************
214 * FILTER by Krzysztof Foltman
215 **********************************************************************/
217 class filter_audio_module
:
218 public filter_module_with_inertia
<dsp::biquad_filter_module
, filter_metadata
>
220 mutable float old_cutoff
, old_resonance
, old_mode
;
222 filter_audio_module()
223 : filter_module_with_inertia
<dsp::biquad_filter_module
, filter_metadata
>(ins
, outs
, params
)
226 old_mode
= old_resonance
= old_cutoff
= -1;
229 void params_changed()
231 inertia_cutoff
.set_inertia(*params
[par_cutoff
]);
232 inertia_resonance
.set_inertia(*params
[par_resonance
]);
233 inertia_filter_module::params_changed();
238 /**********************************************************************
239 * FILTERKLAVIER by Hans Baier
240 **********************************************************************/
242 class filterclavier_audio_module
:
243 public filter_module_with_inertia
<dsp::biquad_filter_module
, filterclavier_metadata
>
245 using audio_module
<filterclavier_metadata
>::ins
;
246 using audio_module
<filterclavier_metadata
>::outs
;
247 using audio_module
<filterclavier_metadata
>::params
;
249 const float min_gain
;
250 const float max_gain
;
255 filterclavier_audio_module();
256 void params_changed();
258 void set_sample_rate(uint32_t sr
);
262 virtual void note_on(int channel
, int note
, int vel
);
263 virtual void note_off(int channel
, int note
, int vel
);
265 void adjust_gain_according_to_filter_mode(int velocity
);
268 /**********************************************************************
269 * EMPHASIS by Damien Zammit
270 **********************************************************************/
272 class emphasis_audio_module
: public audio_module
<emphasis_metadata
>, public frequency_response_line_graph
{
274 dsp::riaacurve riaacurvL
, riaacurvR
;
275 int mode
, type
, bypass
;
276 typedef std::complex<double> cfloat
;
280 emphasis_audio_module();
283 void params_changed();
284 void set_sample_rate(uint32_t sr
)
287 int meter
[] = {param_meter_inL
, param_meter_inR
, param_meter_outL
, param_meter_outR
};
288 int clip
[] = {param_clip_inL
, param_clip_inR
, param_clip_outL
, param_clip_outR
};
289 meters
.init(params
, meter
, clip
, 4, sr
);
291 virtual float freq_gain(int index
, double freq
) const {
292 return riaacurvL
.freq_gain(freq
, (float)srate
);
294 virtual bool get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const;
295 virtual bool get_gridline(int index
, int subindex
, int phase
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
) const;
296 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
);
299 /**********************************************************************
300 * CROSSOVER MODULES by Markus Schmidt
301 **********************************************************************/
303 template<class XoverBaseClass
>
304 class xover_audio_module
: public audio_module
<XoverBaseClass
>, public frequency_response_line_graph
{
306 typedef audio_module
<XoverBaseClass
> AM
;
312 using AM::param_count
;
315 enum { params_per_band
= AM::param_level2
- AM::param_level1
};
321 unsigned int buffer_size
;
323 static inline float sign(float x
) {
324 if(x
< 0) return -1.f
;
325 if(x
> 0) return 1.f
;
329 dsp::crossover crossover
;
330 xover_audio_module();
331 ~xover_audio_module();
334 void params_changed();
335 void set_sample_rate(uint32_t sr
);
336 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
);
337 bool get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const;
338 bool get_layers(int index
, int generation
, unsigned int &layers
) const;
341 typedef xover_audio_module
<xover2_metadata
> xover2_audio_module
;
342 typedef xover_audio_module
<xover3_metadata
> xover3_audio_module
;
343 typedef xover_audio_module
<xover4_metadata
> xover4_audio_module
;
345 /**********************************************************************
346 * VOCODER by Markus Schmidt & Christian Holschuh
347 **********************************************************************/
349 class vocoder_audio_module
: public audio_module
<vocoder_metadata
>, public frequency_response_line_graph
{
351 int bands
, bands_old
, bypass
, order
, order_old
;
354 static const int maxorder
= 8;
355 dsp::biquad_d2 detector
[2][maxorder
][32], modulator
[2][maxorder
][32];
356 double env_mods
[2][32];
359 double attack
, release
, fcoeff
, log2_
;
360 vocoder_audio_module();
363 void params_changed();
365 int get_solo() const;
366 void set_sample_rate(uint32_t sr
)
369 _analyzer
.set_sample_rate(sr
);
370 int meter
[] = {param_carrier_inL
, param_carrier_inR
, param_mod_inL
, param_mod_inR
, param_outL
, param_outR
};
371 int clip
[] = {param_carrier_clip_inL
, param_carrier_clip_inR
, param_mod_clip_inL
, param_mod_clip_inR
, param_clip_outL
, param_clip_outR
};
372 meters
.init(params
, meter
, clip
, 6, sr
);
374 virtual bool get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const;
375 virtual bool get_layers(int index
, int generation
, unsigned int &layers
) const;
376 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
);