Vocoder: improve performance of detector LEDs
[calf.git] / src / calf / modules_filter.h
blobca06fd244245f17f5f1b04ba7e3f850795dcf127
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"
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 {
43 public:
44 typedef audio_module<BaseClass> AM;
45 using AM::ins;
46 using AM::outs;
47 using AM::params;
48 using AM::in_count;
49 using AM::out_count;
50 using AM::param_count;
51 using AM::PeakBands;
52 private:
53 analyzer _analyzer;
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;
59 int indiv_old;
60 bool analyzer_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];
63 vumeters meters;
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];
68 int keep_gliding;
69 mutable int last_peak;
70 inline void process_hplp(float &left, float &right);
71 public:
72 typedef std::complex<double> cfloat;
73 uint32_t srate;
74 bool is_active;
75 mutable volatile int last_generation, last_calculated_generation;
76 equalizerNband_audio_module();
77 void activate();
78 void deactivate();
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)
87 srate = 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
108 public:
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;
117 bool is_active;
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)
124 , timer(128)
125 , is_active(false)
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()
151 calculate_filter();
154 void on_timer()
156 int gen = last_generation;
157 inertia_cutoff.step();
158 inertia_resonance.step();
159 inertia_gain.step();
160 calculate_filter();
161 last_calculated_generation = gen;
164 void activate()
166 params_changed();
167 FilterClass::filter_activate();
168 timer = dsp::once_per_n(FilterClass::srate / 1000);
169 timer.start();
170 is_active = true;
173 void set_sample_rate(uint32_t sr)
175 FilterClass::srate = sr;
179 void deactivate()
181 is_active = false;
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]);
186 uint32_t ostate = 0;
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()) {
202 on_timer();
204 offset += numnow;
206 return ostate;
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;
221 public:
222 filter_audio_module()
223 : filter_module_with_inertia<dsp::biquad_filter_module, filter_metadata>(ins, outs, params)
225 last_generation = 0;
226 old_mode = old_resonance = old_cutoff = -1;
227 redraw_graph = true;
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();
234 redraw_graph = true;
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;
252 int last_note;
253 int last_velocity;
254 public:
255 filterclavier_audio_module();
256 void params_changed();
257 void activate();
258 void set_sample_rate(uint32_t sr);
259 void deactivate();
261 /// MIDI control
262 virtual void note_on(int channel, int note, int vel);
263 virtual void note_off(int channel, int note, int vel);
264 private:
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 {
273 public:
274 dsp::riaacurve riaacurvL, riaacurvR;
275 int mode, type, bypass;
276 typedef std::complex<double> cfloat;
277 uint32_t srate;
278 bool is_active;
279 vumeters meters;
280 emphasis_audio_module();
281 void activate();
282 void deactivate();
283 void params_changed();
284 void set_sample_rate(uint32_t sr)
286 srate = 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 {
305 public:
306 typedef audio_module<XoverBaseClass> AM;
307 using AM::ins;
308 using AM::outs;
309 using AM::params;
310 using AM::in_count;
311 using AM::out_count;
312 using AM::param_count;
313 using AM::bands;
314 using AM::channels;
315 enum { params_per_band = AM::param_level2 - AM::param_level1 };
316 uint32_t srate;
317 bool is_active;
318 float * buffer;
319 float in[channels];
320 unsigned int pos;
321 unsigned int buffer_size;
322 int last_peak;
323 static inline float sign(float x) {
324 if(x < 0) return -1.f;
325 if(x > 0) return 1.f;
326 return 0.f;
328 vumeters meters;
329 dsp::crossover crossover;
330 xover_audio_module();
331 ~xover_audio_module();
332 void activate();
333 void deactivate();
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 {
350 public:
351 int bands, bands_old, bypass, order, order_old;
352 uint32_t srate;
353 bool is_active;
354 static const int maxorder = 8;
355 dsp::biquad_d2 detector[2][maxorder][32], modulator[2][maxorder][32];
356 double env_mods[2][32];
357 vumeters meters;
358 analyzer _analyzer;
359 double attack, release, fcoeff, log2_;
360 vocoder_audio_module();
361 void activate();
362 void deactivate();
363 void params_changed();
364 void set_leds();
365 int get_solo() const;
366 void set_sample_rate(uint32_t sr)
368 srate = 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);
381 #endif