LineGraph: z axis for lo and hi pass handles
[calf.git] / src / modules_filter.cpp
blob740e0e63e62669c7f557574ac65bd6dc81417a32
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 02110-1301 USA
21 #include <limits.h>
22 #include <memory.h>
23 #include <calf/giface.h>
24 #include <calf/modules_filter.h>
26 using namespace dsp;
27 using namespace calf_plugins;
29 #define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
31 /**********************************************************************
32 * EQUALIZER N BAND by Markus Schmidt and Krzysztof Foltman
33 **********************************************************************/
35 inline void diff_ms(float &left, float &right) {
36 float tmp = (left + right) / 2;
37 right = left - right;
38 left = tmp;
40 inline void undiff_ms(float &left, float &right) {
41 float tmp = left + right / 2;
42 right = left - right / 2;
43 left = tmp;
46 template<class BaseClass, bool has_lphp>
47 equalizerNband_audio_module<BaseClass, has_lphp>::equalizerNband_audio_module()
49 is_active = false;
50 srate = 0;
51 last_generation = 0;
52 hp_freq_old = lp_freq_old = hp_q_old = 0;
53 hs_freq_old = ls_freq_old = lp_q_old = 0;
54 hs_level_old = ls_level_old = 0;
55 keep_gliding = 0;
56 last_peak = 0;
57 indiv_old = -1;
58 analyzer_old = false;
59 for (int i = 0; i < AM::PeakBands; i++)
61 p_freq_old[i] = 0;
62 p_level_old[i] = 0;
63 p_q_old[i] = 0;
65 for (int i = 0; i < graph_param_count; i++)
66 old_params_for_graph[i] = -1;
67 redraw_graph = true;
70 template<class BaseClass, bool has_lphp>
71 void equalizerNband_audio_module<BaseClass, has_lphp>::activate()
73 is_active = true;
74 // set all filters
75 params_changed();
78 template<class BaseClass, bool has_lphp>
79 void equalizerNband_audio_module<BaseClass, has_lphp>::deactivate()
81 is_active = false;
84 static inline void copy_lphp(biquad_d2 filters[3][2])
86 for (int i = 0; i < 3; i++)
87 for (int j = 0; j < 2; j++)
88 if (i || j)
89 filters[i][j].copy_coeffs(filters[0][0]);
92 static inline double glide(double value, double target, int &keep_gliding)
94 if (target == value)
95 return value;
96 keep_gliding = 1;
97 if (target > value)
98 return std::min(target, (value + 0.1) * 1.003);
99 else
100 return std::max(target, (value / 1.003) - 0.1);
103 template<class BaseClass, bool has_lphp>
104 void equalizerNband_audio_module<BaseClass, has_lphp>::params_changed()
106 keep_gliding = 0;
107 // set the params of all filters
109 // lp/hp first (if available)
110 if (has_lphp)
112 hp_mode = (CalfEqMode)(int)*params[AM::param_hp_mode];
113 lp_mode = (CalfEqMode)(int)*params[AM::param_lp_mode];
115 float hpfreq = *params[AM::param_hp_freq], lpfreq = *params[AM::param_lp_freq];
116 float hpq = *params[AM::param_hp_q], lpq = *params[AM::param_lp_q];
118 if(hpfreq != hp_freq_old or hpq != hp_q_old) {
119 hpfreq = glide(hp_freq_old, hpfreq, keep_gliding);
120 hp[0][0].set_hp_rbj(hpfreq, hpq, (float)srate, 1.0);
121 copy_lphp(hp);
122 hp_freq_old = hpfreq;
124 if(lpfreq != lp_freq_old or lpq != lp_q_old) {
125 lpfreq = glide(lp_freq_old, lpfreq, keep_gliding);
126 lp[0][0].set_lp_rbj(lpfreq, lpq, (float)srate, 1.0);
127 copy_lphp(lp);
128 lp_freq_old = lpfreq;
132 // then shelves
133 float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level], hsq =*params[AM::param_hs_q];
134 float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level], lsq =*params[AM::param_ls_q];
136 if(lsfreq != ls_freq_old or lslevel != ls_level_old or lsq != ls_q_old) {
137 lsfreq = glide(ls_freq_old, lsfreq, keep_gliding);
138 lsL.set_lowshelf_rbj(lsfreq, lsq, lslevel, (float)srate);
139 lsR.copy_coeffs(lsL);
140 ls_level_old = lslevel;
141 ls_freq_old = lsfreq;
142 ls_q_old = lsq;
144 if(hsfreq != hs_freq_old or hslevel != hs_level_old or hsq != hs_q_old) {
145 hsfreq = glide(hs_freq_old, hsfreq, keep_gliding);
146 hsL.set_highshelf_rbj(hsfreq, hsq, hslevel, (float)srate);
147 hsR.copy_coeffs(hsL);
148 hs_level_old = hslevel;
149 hs_freq_old = hsfreq;
150 hs_q_old = hsq;
152 for (int i = 0; i < AM::PeakBands; i++)
154 int offset = i * params_per_band;
155 float freq = *params[AM::param_p1_freq + offset];
156 float level = *params[AM::param_p1_level + offset];
157 float q = *params[AM::param_p1_q + offset];
158 if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) {
159 freq = glide(p_freq_old[i], freq, keep_gliding);
160 pL[i].set_peakeq_rbj(freq, q, level, (float)srate);
161 pR[i].copy_coeffs(pL[i]);
162 p_freq_old[i] = freq;
163 p_level_old[i] = level;
164 p_q_old[i] = q;
167 if (*params[AM::param_individuals] != indiv_old) {
168 indiv_old = *params[AM::param_individuals];
169 redraw_graph = true;
172 // check if any important parameter for redrawing the graph changed
173 for (int i = 0; i < graph_param_count; i++) {
174 if (*params[AM::first_graph_param + i] != old_params_for_graph[i])
175 redraw_graph = true;
176 old_params_for_graph[i] = *params[AM::first_graph_param + i];
179 _analyzer.set_params(
180 256, 1, 6, 0, 1,
181 *params[AM::param_analyzer_mode] + (*params[AM::param_analyzer_mode] >= 3 ? 5 : 1),
182 0, 0, 15, 2, 0, 0
185 if ((bool)*params[AM::param_analyzer_active] != analyzer_old) {
186 redraw_graph = true;
187 analyzer_old = (bool)*params[AM::param_analyzer_active];
191 template<class BaseClass, bool has_lphp>
192 inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float &left, float &right)
194 if (!has_lphp)
195 return;
196 int active = *params[AM::param_lp_active];
197 if (active > 0.f)
199 if (active > 3) diff_ms(left, right);
200 switch(lp_mode)
202 case MODE12DB:
203 if (active == 1 or active == 2 or active == 4)
204 left = lp[0][0].process(left);
205 if (active == 1 or active == 3 or active == 5)
206 right = lp[0][1].process(right);
207 break;
208 case MODE24DB:
209 if (active == 1 or active == 2 or active == 4)
210 left = lp[1][0].process(lp[0][0].process(left));
211 if (active == 1 or active == 3 or active == 5)
212 right = lp[1][1].process(lp[0][1].process(right));
213 break;
214 case MODE36DB:
215 if (active == 1 or active == 2 or active == 4)
216 left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left)));
217 if (active == 1 or active == 3 or active == 5)
218 right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right)));
219 break;
221 if (active > 3) undiff_ms(left, right);
223 active = *params[AM::param_hp_active];
224 if (active > 0.f)
226 if (active > 3) diff_ms(left, right);
227 switch(hp_mode)
229 case MODE12DB:
230 if (active == 1 or active == 2 or active == 4)
231 left = hp[0][0].process(left);
232 if (active == 1 or active == 3 or active == 5)
233 right = hp[0][1].process(right);
234 break;
235 case MODE24DB:
236 if (active == 1 or active == 2 or active == 4)
237 left = hp[1][0].process(hp[0][0].process(left));
238 if (active == 1 or active == 3 or active == 5)
239 right = hp[1][1].process(hp[0][1].process(right));
240 break;
241 case MODE36DB:
242 if (active == 1 or active == 2 or active == 4)
243 left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left)));
244 if (active == 1 or active == 3 or active == 5)
245 right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right)));
246 break;
248 if (active > 3) undiff_ms(left, right);
252 template<class BaseClass, bool has_lphp>
253 uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
255 bool bypassed = bypass.update(*params[AM::param_bypass] > 0.5f, numsamples);
256 if (keep_gliding)
258 // ensure that if params have changed, the params_changed method is
259 // called every 8 samples to interpolate filter parameters
260 while(numsamples > 8 && keep_gliding)
262 params_changed();
263 outputs_mask |= process(offset, 8, inputs_mask, outputs_mask);
264 offset += 8;
265 numsamples -= 8;
267 if (keep_gliding)
268 params_changed();
270 numsamples += offset;
271 if(bypassed) {
272 // everything bypassed
273 while(offset < numsamples) {
274 outs[0][offset] = ins[0][offset];
275 outs[1][offset] = ins[1][offset];
276 float values[] = {0, 0, 0, 0};
277 meters.process(values);
278 _analyzer.process(0, 0);
279 ++offset;
281 } else {
282 // process
283 uint32_t orig_numsamples = numsamples-offset;
284 uint32_t orig_offset = offset;
285 while(offset < numsamples) {
286 // cycle through samples
287 float outL = 0.f;
288 float outR = 0.f;
289 float inL = ins[0][offset];
290 float inR = ins[1][offset];
291 // in level
292 inR *= *params[AM::param_level_in];
293 inL *= *params[AM::param_level_in];
295 float procL = inL;
296 float procR = inR;
298 // all filters in chain
299 process_hplp(procL, procR);
301 int active = *params[AM::param_ls_active];
302 if (active > 3) diff_ms(procL, procR);
303 if (active == 1 or active == 2 or active == 4)
304 procL = lsL.process(procL);
305 if (active == 1 or active == 3 or active == 5)
306 procR = lsR.process(procR);
307 if (active > 3) undiff_ms(procL, procR);
309 active = *params[AM::param_hs_active];
310 if (active > 3) diff_ms(procL, procR);
311 if (active == 1 or active == 2 or active == 4)
312 procL = hsL.process(procL);
313 if (active == 1 or active == 3 or active == 5)
314 procR = hsR.process(procR);
315 if (active > 3) undiff_ms(procL, procR);
317 for (int i = 0; i < AM::PeakBands; i++)
319 int offset = i * params_per_band;
320 int active = *params[AM::param_p1_active + offset];
321 if (active > 3) diff_ms(procL, procR);
322 if (active == 1 or active == 2 or active == 4)
323 procL = pL[i].process(procL);
324 if (active == 1 or active == 3 or active == 5)
325 procR = pR[i].process(procR);
326 if (active > 3) undiff_ms(procL, procR);
329 outL = procL * *params[AM::param_level_out];
330 outR = procR * *params[AM::param_level_out];
332 // analyzer
333 _analyzer.process((inL + inR) / 2.f, (outL + outR) / 2.f);
335 // send to output
336 outs[0][offset] = outL;
337 outs[1][offset] = outR;
339 float values[] = {inL, inR, outL, outR};
340 meters.process(values);
342 // next sample
343 ++offset;
344 } // cycle trough samples
345 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
346 // clean up
347 for(int i = 0; i < 3; ++i) {
348 hp[i][0].sanitize();
349 hp[i][1].sanitize();
350 lp[i][0].sanitize();
351 lp[i][1].sanitize();
353 lsL.sanitize();
354 hsR.sanitize();
355 for(int i = 0; i < AM::PeakBands; ++i) {
356 pL[i].sanitize();
357 pR[i].sanitize();
360 meters.fall(numsamples);
361 return outputs_mask;
364 static inline float adjusted_lphp_gain(const float *const *params, int param_active, int param_mode, const biquad_d2 &filter, float freq, float srate)
366 if(*params[param_active] > 0.f) {
367 float gain = filter.freq_gain(freq, srate);
368 switch((int)*params[param_mode]) {
369 case MODE12DB:
370 return gain;
371 case MODE24DB:
372 return gain * gain;
373 case MODE36DB:
374 return gain * gain * gain;
377 return 1;
380 template<class BaseClass, bool has_lphp>
381 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
383 if (phase and *params[AM::param_analyzer_active]) {
384 bool r = _analyzer.get_graph(subindex, phase, data, points, context, mode);
385 if (*params[AM::param_analyzer_mode] == 2) {
386 set_channel_color(context, subindex ? 0 : 1, 0.15);
387 } else {
388 context->set_source_rgba(0,0,0,0.1);
390 return r;
391 } else if (phase and !*params[AM::param_analyzer_active]) {
392 redraw_graph = false;
393 return false;
394 } else {
395 int max = PeakBands + 2 + (has_lphp ? 2 : 0);
397 if (!is_active
398 or (subindex and !*params[AM::param_individuals])
399 or (subindex > max and *params[AM::param_individuals])) {
400 redraw_graph = false;
401 return false;
404 // first graph is the overall frequency response graph
405 if (!subindex)
406 return ::get_graph(*this, subindex, data, points, 128 * *params[AM::param_zoom], 0);
408 // get out if max band is reached
409 if (last_peak >= max) {
410 last_peak = 0;
411 redraw_graph = false;
412 return false;
415 // get the next filter to draw a curve for and leave out inactive
416 // filters
417 while (last_peak < PeakBands and !*params[AM::param_p1_active + last_peak * params_per_band])
418 last_peak ++;
419 if (last_peak == PeakBands and !*params[AM::param_ls_active])
420 last_peak ++;
421 if (last_peak == PeakBands + 1 and !*params[AM::param_hs_active])
422 last_peak ++;
423 if (has_lphp and last_peak == PeakBands + 2 and !*params[AM::param_hp_active])
424 last_peak ++;
425 if (has_lphp and last_peak == PeakBands + 3 and !*params[AM::param_lp_active])
426 last_peak ++;
428 // get out if max band is reached
429 if (last_peak >= max) { // and !*params[param_analyzer_active]) {
430 last_peak = 0;
431 redraw_graph = false;
432 return false;
434 //else if *params[param_analyzer_active]) {
435 //bool goon = _analyzer.get_graph(subindex, phase, data, points, context, mode);
436 //if (!goon)
437 //last_peak = 0;
438 //return goon;
441 // draw the individual curve of the actual filter
442 for (int i = 0; i < points; i++) {
443 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
444 if (last_peak < PeakBands) {
445 data[i] = pL[last_peak].freq_gain(freq, (float)srate);
446 } else if (last_peak == PeakBands) {
447 data[i] = lsL.freq_gain(freq, (float)srate);
448 } else if (last_peak == PeakBands + 1) {
449 data[i] = hsL.freq_gain(freq, (float)srate);
450 } else if (last_peak == PeakBands + 2 and has_lphp) {
451 data[i] = adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)srate);
452 } else if (last_peak == PeakBands + 3 and has_lphp) {
453 data[i] = adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)srate);
455 data[i] = dB_grid(data[i], 128 * *params[AM::param_zoom], 0);
458 last_peak ++;
459 *mode = 4;
460 context->set_source_rgba(0,0,0,0.075);
461 return true;
464 template<class BaseClass, bool has_lphp>
465 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_layers(int index, int generation, unsigned int &layers) const
467 redraw_graph = redraw_graph || !generation;
468 layers = *params[AM::param_analyzer_active] ? LG_REALTIME_GRAPH : 0;
469 layers |= (generation ? LG_NONE : LG_CACHE_GRID) | (redraw_graph ? LG_CACHE_GRAPH : LG_NONE);
470 redraw_graph |= (bool)*params[AM::param_analyzer_active];
471 return redraw_graph or !generation;
474 template<class BaseClass, bool has_lphp>
475 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
477 if (!is_active or phase)
478 return false;
479 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 128 * *params[AM::param_zoom], 0);
482 template<class BaseClass, bool has_lphp>
483 float equalizerNband_audio_module<BaseClass, has_lphp>::freq_gain(int index, double freq) const
485 float ret = 1.f;
486 if (has_lphp)
488 ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)srate);
489 ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)srate);
491 ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, (float)srate) : 1;
492 ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, (float)srate) : 1;
493 for (int i = 0; i < PeakBands; i++)
494 ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)srate) : 1;
495 return ret;
498 template<class BaseClass, bool has_lphp>
499 inline string equalizerNband_audio_module<BaseClass, has_lphp>::get_crosshair_label(int x, int y, int sx, int sy, float q, int dB, int name, int note, int cents) const
501 return frequency_crosshair_label(x, y, sx, sy, q, dB, name, note, cents, 128 * *params[AM::param_zoom], 0);
504 template class equalizerNband_audio_module<equalizer5band_metadata, false>;
505 template class equalizerNband_audio_module<equalizer8band_metadata, true>;
506 template class equalizerNband_audio_module<equalizer12band_metadata, true>;
508 /**********************************************************************
509 * EQUALIZER 30 BAND
510 **********************************************************************/
512 void equalizer30band_audio_module::set_freq_grid()
514 //Initialize freq indicators
515 unsigned int param_ptr = 0;
516 for(unsigned j = 0; j < fg.get_number_of_bands(); j++)
518 *params[param_freq11 + param_ptr] = fg.get_rounded_freq(j);
519 *params[param_freq21 + param_ptr] = fg.get_rounded_freq(j);
520 param_ptr += 3;
523 is_freq_grid_init = true;
526 equalizer30band_audio_module::equalizer30band_audio_module() :
527 conv(orfanidis_eq::eq_min_max_gain_db),
528 swL(10000), swR(10000)
530 is_active = false;
531 srate = 0;
533 is_freq_grid_init = false;
535 //Construct equalizers
536 using namespace orfanidis_eq;
538 fg.set_30_bands();
540 eq2* ptr30L = new eq2(fg, butterworth);
541 eq2* ptr30R = new eq2(fg, butterworth);
542 eq_arrL.push_back(ptr30L);
543 eq_arrR.push_back(ptr30R);
545 ptr30L = new eq2(fg, chebyshev1);
546 ptr30R = new eq2(fg, chebyshev1);
547 eq_arrL.push_back(ptr30L);
548 eq_arrR.push_back(ptr30R);
550 ptr30L = new eq2(fg, chebyshev2);
551 ptr30R = new eq2(fg, chebyshev2);
552 eq_arrL.push_back(ptr30L);
553 eq_arrR.push_back(ptr30R);
555 flt_type = butterworth;
556 flt_type_old = none;
558 //Set switcher
559 swL.set_previous(butterworth);
560 swL.set(butterworth);
562 swR.set_previous(butterworth);
563 swR.set(butterworth);
566 equalizer30band_audio_module::~equalizer30band_audio_module()
568 for (unsigned int i = 0; i < eq_arrL.size(); i++)
569 delete eq_arrL[i];
571 for (unsigned int i = 0; i < eq_arrR.size(); i++)
572 delete eq_arrR[i];
575 void equalizer30band_audio_module::activate()
577 is_active = true;
579 //Update freq grid
580 if(is_freq_grid_init == false)
581 set_freq_grid();
584 void equalizer30band_audio_module::deactivate()
586 is_active = false;
589 void equalizer30band_audio_module::params_changed()
591 using namespace orfanidis_eq;
593 //Change gain indicators
594 *params[param_gain_scale10] = *params[param_gain10] * *params[param_gainscale1];
595 *params[param_gain_scale20] = *params[param_gain20] * *params[param_gainscale2];
597 for(unsigned int i = 0; i < fg.get_number_of_bands(); i++)
598 *params[param_gain_scale11 + band_params*i] = (*params[param_gain11 + band_params*i])*
599 *params[param_gainscale1];
601 for(unsigned int i = 0; i < fg.get_number_of_bands(); i++)
602 *params[param_gain_scale21 + band_params*i] = (*params[param_gain21 + band_params*i])*
603 *params[param_gainscale2];
605 //Pass gains to eq's
606 for (unsigned int i = 0; i < fg.get_number_of_bands(); i++)
607 eq_arrL[*params[param_filters]]->change_band_gain_db(i,*params[param_gain_scale11 + band_params*i]);
609 for (unsigned int i = 0; i < fg.get_number_of_bands(); i++)
610 eq_arrR[*params[param_filters]]->change_band_gain_db(i,*params[param_gain_scale21 + band_params*i]);
612 //Upadte filter type
613 flt_type = (filter_type)(*params[param_filters] + 1);
616 void equalizer30band_audio_module::set_sample_rate(uint32_t sr)
618 srate = sr;
620 //Change sample rate for eq's
621 for(unsigned int i = 0; i < eq_arrL.size(); i++)
623 eq_arrL[i]->set_sample_rate(srate);
624 eq_arrL[i]->set_sample_rate(srate);
627 int meter[] = {param_level_in_vuL, param_level_in_vuR, param_level_out_vuL, param_level_out_vuR};
628 int clip[] = {param_level_in_clipL, param_level_in_clipR, param_level_out_clipL, param_level_out_clipR};
629 meters.init(params, meter, clip, 4, sr);
632 uint32_t equalizer30band_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
634 uint32_t orig_numsamples = numsamples;
635 uint32_t orig_offset = offset;
636 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
637 numsamples += offset;
638 if(bypassed) {
639 // everything bypassed
640 while(offset < numsamples) {
641 outs[0][offset] = ins[0][offset];
642 outs[1][offset] = ins[1][offset];
643 float values[] = {0, 0, 0, 0};
644 meters.process(values);
645 ++offset;
647 } else {
648 // process
649 while(offset < numsamples) {
651 double inL = ins[0][offset] * *params[param_level_in];
652 double inR = ins[1][offset] * *params[param_level_in];
654 double outL = inL;
655 double outR = inR;
657 unsigned int eq_index = swL.get_state() - 1;
658 eq_arrL[eq_index]->sbs_process(&inL, &outL);
659 eq_arrR[eq_index]->sbs_process(&inR, &outR);
661 //If filter type switched
662 if(flt_type_old != flt_type)
664 swL.set(flt_type);
665 swR.set(flt_type);
666 flt_type_old = flt_type;
669 outL *= swL.get_ramp();
670 outR *= swR.get_ramp();
672 outL = outL* conv.fast_db_2_lin(*params[param_gain_scale10]);
673 outR = outR* conv.fast_db_2_lin(*params[param_gain_scale20]);
675 outL = outL* *params[param_level_out];
676 outR = outR* *params[param_level_out];
678 outs[0][offset] = outL;
679 outs[1][offset] = outR;
681 // meters
682 float values[] = {(float)inL, (float)inR, (float)outL, (float)outR};
683 meters.process(values);
685 // next sample
686 ++offset;
687 } // cycle trough samples
688 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
691 meters.fall(orig_numsamples);
692 return outputs_mask;
695 /**********************************************************************
696 * FILTERKLAVIER by Hans Baier
697 **********************************************************************/
699 filterclavier_audio_module::filterclavier_audio_module()
700 : filter_module_with_inertia<biquad_filter_module, filterclavier_metadata>(ins, outs, params)
701 , min_gain(1.0)
702 , max_gain(32.0)
703 , last_note(-1)
704 , last_velocity(-1)
708 void filterclavier_audio_module::params_changed()
710 inertia_filter_module::inertia_cutoff.set_inertia(
711 note_to_hz(last_note + *params[par_transpose], *params[par_detune]));
713 float min_resonance = param_props[par_max_resonance].min;
714 inertia_filter_module::inertia_resonance.set_inertia(
715 (float(last_velocity) / 127.0)
716 // 0.001: see below
717 * (*params[par_max_resonance] - min_resonance + 0.001)
718 + min_resonance);
720 adjust_gain_according_to_filter_mode(last_velocity);
722 inertia_filter_module::calculate_filter();
723 redraw_graph = true;
726 void filterclavier_audio_module::activate()
728 inertia_filter_module::activate();
731 void filterclavier_audio_module::set_sample_rate(uint32_t sr)
733 inertia_filter_module::set_sample_rate(sr);
736 void filterclavier_audio_module::deactivate()
738 inertia_filter_module::deactivate();
742 void filterclavier_audio_module::note_on(int channel, int note, int vel)
744 last_note = note;
745 last_velocity = vel;
746 inertia_filter_module::inertia_cutoff.set_inertia(
747 note_to_hz(note + *params[par_transpose], *params[par_detune]));
749 float min_resonance = param_props[par_max_resonance].min;
750 inertia_filter_module::inertia_resonance.set_inertia(
751 (float(vel) / 127.0)
752 // 0.001: if the difference is equal to zero (which happens
753 // when the max_resonance knom is at minimum position
754 // then the filter gain doesnt seem to snap to zero on most note offs
755 * (*params[par_max_resonance] - min_resonance + 0.001)
756 + min_resonance);
758 adjust_gain_according_to_filter_mode(vel);
760 inertia_filter_module::calculate_filter();
761 redraw_graph = true;
764 void filterclavier_audio_module::note_off(int channel, int note, int vel)
766 if (note == last_note) {
767 inertia_filter_module::inertia_resonance.set_inertia(param_props[par_max_resonance].min);
768 inertia_filter_module::inertia_gain.set_inertia(min_gain);
769 inertia_filter_module::calculate_filter();
770 last_velocity = 0;
771 redraw_graph = true;
775 void filterclavier_audio_module::adjust_gain_according_to_filter_mode(int velocity)
777 int mode = dsp::fastf2i_drm(*params[par_mode]);
779 // for bandpasses: boost gain for velocities > 0
780 if ( (mode_6db_bp <= mode) && (mode <= mode_18db_bp) ) {
781 // gain for velocity 0: 1.0
782 // gain for velocity 127: 32.0
783 float mode_max_gain = max_gain;
784 // max_gain is right for mode_6db_bp
785 if (mode == mode_12db_bp)
786 mode_max_gain /= 6.0;
787 if (mode == mode_18db_bp)
788 mode_max_gain /= 10.5;
790 inertia_filter_module::inertia_gain.set_now(
791 (float(velocity) / 127.0) * (mode_max_gain - min_gain) + min_gain);
792 } else {
793 inertia_filter_module::inertia_gain.set_now(min_gain);
797 /**********************************************************************
798 * EMPHASIS by Damien Zammit
799 **********************************************************************/
801 emphasis_audio_module::emphasis_audio_module()
803 is_active = false;
804 srate = 0;
805 redraw_graph = true;
806 mode = -1;
807 type = -1;
810 void emphasis_audio_module::activate()
812 is_active = true;
813 // set all filters
814 params_changed();
817 void emphasis_audio_module::deactivate()
819 is_active = false;
822 void emphasis_audio_module::params_changed()
824 if (mode != *params[param_mode] or type != *params[param_type] or bypass_ != *params[param_bypass])
825 redraw_graph = true;
826 mode = *params[param_mode];
827 type = *params[param_type];
828 bypass_ = *params[param_bypass];
829 riaacurvL.set(srate, mode, type);
830 riaacurvR.set(srate, mode, type);
833 uint32_t emphasis_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
835 uint32_t orig_numsamples = numsamples;
836 uint32_t orig_offset = offset;
837 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
838 if (!bypassed)
840 // ensure that if params have changed, the params_changed method is
841 // called every 8 samples to interpolate filter parameters
842 while(numsamples > 8)
844 params_changed();
845 outputs_mask |= process(offset, 8, inputs_mask, outputs_mask);
846 offset += 8;
847 numsamples -= 8;
850 numsamples += offset;
851 if(bypassed) {
852 // everything bypassed
853 while(offset < numsamples) {
854 outs[0][offset] = ins[0][offset];
855 outs[1][offset] = ins[1][offset];
856 float values[] = {0, 0, 0, 0};
857 meters.process(values);
858 ++offset;
860 } else {
861 // process
862 while(offset < numsamples) {
863 // cycle through samples
864 float outL = 0.f;
865 float outR = 0.f;
866 float inL = ins[0][offset];
867 float inR = ins[1][offset];
868 // in level
869 inR *= *params[param_level_in];
870 inL *= *params[param_level_in];
872 float procL = inL;
873 float procR = inR;
875 procL = riaacurvL.process(procL);
876 procR = riaacurvR.process(procR);
878 outL = procL * *params[param_level_out];
879 outR = procR * *params[param_level_out];
881 // send to output
882 outs[0][offset] = outL;
883 outs[1][offset] = outR;
885 float values[] = {inL, inR, outL, outR};
886 meters.process(values);
888 // next sample
889 ++offset;
890 } // cycle trough samples
891 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
892 // clean up
893 riaacurvL.sanitize();
894 riaacurvR.sanitize();
896 meters.fall(orig_numsamples);
897 return outputs_mask;
899 bool emphasis_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
901 if (phase or subindex)
902 return false;
903 if (bypass_)
904 context->set_source_rgba(0.15, 0.2, 0.0, 0.3);
905 return ::get_graph(*this, subindex, data, points, 32, 0);
907 bool emphasis_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
909 if (phase)
910 return false;
911 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 32, 0);
914 /**********************************************************************
915 * CROSSOVER N BAND by Markus Schmidt
916 **********************************************************************/
918 template<class XoverBaseClass>
919 xover_audio_module<XoverBaseClass>::xover_audio_module()
921 is_active = false;
922 srate = 0;
923 redraw_graph = true;
924 crossover.init(AM::channels, AM::bands, 44100);
926 template<class XoverBaseClass>
927 xover_audio_module<XoverBaseClass>::~xover_audio_module()
929 free(buffer);
931 template<class XoverBaseClass>
932 void xover_audio_module<XoverBaseClass>::activate()
934 is_active = true;
935 params_changed();
938 template<class XoverBaseClass>
939 void xover_audio_module<XoverBaseClass>::deactivate()
941 is_active = false;
943 template<class XoverBaseClass>
944 void xover_audio_module<XoverBaseClass>::set_sample_rate(uint32_t sr)
946 srate = sr;
947 // set srate of crossover
948 crossover.set_sample_rate(srate);
949 // rebuild buffer
950 buffer_size = (int)(srate / 10 * AM::channels * AM::bands + AM::channels * AM::bands); // buffer size attack rate multiplied by channels and bands
951 buffer = (float*) calloc(buffer_size, sizeof(float));
952 pos = 0;
953 int amount = AM::bands * AM::channels + AM::channels;
954 int meter[amount];
955 int clip[amount];
956 for(int b = 0; b < AM::bands; b++) {
957 for (int c = 0; c < AM::channels; c++) {
958 meter[b * AM::channels + c] = AM::param_meter_01 + b * params_per_band + c;
959 clip[b * AM::channels + c] = -1;
962 for (int c = 0; c < AM::channels; c++) {
963 meter[c + AM::bands * AM::channels] = AM::param_meter_0 + c;
964 clip[c + AM::bands * AM::channels] = -1;
966 meters.init(params, meter, clip, amount, srate);
968 template<class XoverBaseClass>
969 void xover_audio_module<XoverBaseClass>::params_changed()
971 int mode = *params[AM::param_mode];
972 crossover.set_mode(mode);
973 for (int i = 0; i < AM::bands - 1; i++) {
974 crossover.set_filter(i, *params[AM::param_freq0 + i]);
976 for (int i = 0; i < AM::bands; i++) {
977 int offset = i * params_per_band;
978 crossover.set_level(i, *params[AM::param_level1 + offset]);
979 crossover.set_active(i, *params[AM::param_active1 + offset] > 0.5);
981 redraw_graph = true;
984 template<class XoverBaseClass>
985 uint32_t xover_audio_module<XoverBaseClass>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
987 unsigned int targ = numsamples + offset;
988 float xval;
989 float values[AM::bands * AM::channels + AM::channels];
990 while(offset < targ) {
991 // cycle through samples
993 // level
994 for (int c = 0; c < AM::channels; c++) {
995 in[c] = ins[c][offset] * *params[AM::param_level];
997 crossover.process(in);
999 for (int b = 0; b < AM::bands; b++) {
1000 int nbuf = 0;
1001 int off = b * params_per_band;
1002 // calc position in delay buffer
1003 if (*params[AM::param_delay1 + off]) {
1004 nbuf = srate * (fabs(*params[AM::param_delay1 + off]) / 1000.f) * AM::bands * AM::channels;
1005 nbuf -= nbuf % (AM::bands * AM::channels);
1007 for (int c = 0; c < AM::channels; c++) {
1008 // define a pointer between 0 and channels * bands
1009 int ptr = b * AM::channels + c;
1011 // get output from crossover module if active
1012 xval = *params[AM::param_active1 + off] > 0.5 ? crossover.get_value(c, b) : 0.f;
1014 // fill delay buffer
1015 buffer[pos + ptr] = xval;
1017 // get value from delay buffer if neccessary
1018 if (*params[AM::param_delay1 + off])
1019 xval = buffer[(pos - (int)nbuf + ptr + buffer_size) % buffer_size];
1021 // set value with phase to output
1022 outs[ptr][offset] = *params[AM::param_phase1 + off] > 0.5 ? xval * -1 : xval;
1024 // band meters
1025 values[b * AM::channels + c] = outs[ptr][offset];
1028 // in meters
1029 for (int c = 0; c < AM::channels; c++) {
1030 values[c + AM::bands * AM::channels] = ins[c][offset];
1032 meters.process(values);
1033 // next sample
1034 ++offset;
1035 // delay buffer pos forward
1036 pos = (pos + AM::channels * AM::bands) % buffer_size;
1038 } // cycle trough samples
1039 meters.fall(numsamples);
1040 return outputs_mask;
1043 template<class XoverBaseClass>
1044 bool xover_audio_module<XoverBaseClass>::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1046 return crossover.get_graph(subindex, phase, data, points, context, mode);
1048 template<class XoverBaseClass>
1049 bool xover_audio_module<XoverBaseClass>::get_layers(int index, int generation, unsigned int &layers) const
1051 return crossover.get_layers(index, generation, layers);
1054 template class xover_audio_module<xover2_metadata>;
1055 template class xover_audio_module<xover3_metadata>;
1056 template class xover_audio_module<xover4_metadata>;
1059 /**********************************************************************
1060 * Vocoder by Markus Schmidt and Christian Holschuh
1061 **********************************************************************/
1063 vocoder_audio_module::vocoder_audio_module()
1065 is_active = false;
1066 srate = 0;
1067 attack = 0;
1068 release = 0;
1069 fcoeff = 0;
1070 bands = 0;
1071 bands_old = -1;
1072 order = 0;
1073 order_old = -1;
1074 fcoeff = log10(20.f);
1075 log2_ = log(2);
1076 memset(env_mods, 0, 32 * 2 * sizeof(double));
1079 void vocoder_audio_module::activate()
1081 is_active = true;
1084 void vocoder_audio_module::deactivate()
1086 is_active = false;
1089 void vocoder_audio_module::params_changed()
1091 attack = exp(log(0.01)/( *params[param_attack] * srate * 0.001));
1092 release = exp(log(0.01)/( *params[param_release] * srate * 0.001));
1094 int b = *params[param_bands];
1095 bands = (b + 2) * 4 + (b > 1 ? (b - 2) * 4 : 0);
1096 order = std::min(8.f, *params[param_order]);
1097 float q = pow(10, (fmodf(std::min(8.999f, *params[param_order]), 1.f) * (7.f / pow(1.3, order))) / 20);
1098 if (bands != bands_old or *params[param_order] != order_old) {
1099 bands_old = bands;
1100 order_old = *params[param_order];
1101 for (int i = 0; i < bands; i++) {
1102 // set all actually used filters
1103 detector[0][0][i].set_bp_rbj(pow(10, fcoeff + (0.5f + (float)i) * 3.f / (float)bands), q, (double)srate);
1104 for (int j = 0; j < order; j++) {
1105 if (j)
1106 detector[0][j][i].copy_coeffs(detector[0][0][i]);
1107 detector[1][j][i].copy_coeffs(detector[0][0][i]);
1108 modulator[0][j][i].copy_coeffs(detector[0][0][i]);
1109 modulator[1][j][i].copy_coeffs(detector[0][0][i]);
1112 redraw_graph = true;
1114 _analyzer.set_params(256, 1, 6, 0, 1, 0, 0, 0, 15, 2, 0, 0);
1115 redraw_graph = true;
1118 int vocoder_audio_module::get_solo() const {
1119 for (int i = 0; i < bands; i++)
1120 if (*params[param_solo0 + i * band_params])
1121 return 1;
1122 return 0;
1125 uint32_t vocoder_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
1127 uint32_t orig_numsamples = numsamples;
1128 uint32_t orig_offset = offset;
1129 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
1130 int solo = get_solo();
1131 numsamples += offset;
1132 float led[32] = {0};
1133 if(bypassed) {
1134 // everything bypassed
1135 while(offset < numsamples) {
1136 outs[0][offset] = ins[0][offset];
1137 outs[1][offset] = ins[1][offset];
1138 float values[] = {0, 0, 0, 0, 0, 0};
1139 meters.process(values);
1140 ++offset;
1142 } else {
1143 // process
1144 while(offset < numsamples) {
1145 // cycle through samples
1146 double outL = 0;
1147 double outR = 0;
1148 double pL = 0;
1149 double pR = 0;
1151 // carrier with level
1152 double cL = ins[0][offset] * *params[param_carrier_in];
1153 double cR = ins[1][offset] * *params[param_carrier_in];
1155 // modulator with level
1156 double mL = ins[2][offset] * *params[param_mod_in];
1157 double mR = ins[3][offset] * *params[param_mod_in];
1159 // noise generator
1160 double nL = (float)rand() / (float)RAND_MAX;
1161 double nR = (float)rand() / (float)RAND_MAX;
1163 for (int i = 0; i < bands; i++) {
1164 double mL_ = mL;
1165 double mR_ = mR;
1166 double cL_ = cL + nL * *params[param_noise0 + i * band_params];
1167 double cR_ = cR + nR * *params[param_noise0 + i * band_params];
1169 if ((solo and *params[param_solo0 + i * band_params]) or !solo) {
1170 for (int j = 0; j < order; j++) {
1171 // filter modulator
1172 if (*params[param_link] > 0.5) {
1173 mL_ = detector[0][j][i].process(std::max(mL_, mR_));
1174 mR_ = mL_;
1175 } else {
1176 mL_ = detector[0][j][i].process(mL_);
1177 mR_ = detector[1][j][i].process(mR_);
1179 // filter carrier with noise
1180 cL_ = modulator[0][j][i].process(cL_);
1181 cR_ = modulator[1][j][i].process(cR_);
1183 // level by envelope with levelling
1184 cL_ *= env_mods[0][i] * ((float)order / 2 + 4) * 4;
1185 cR_ *= env_mods[1][i] * ((float)order / 2 + 4) * 4;
1187 // add band volume setting
1188 cL_ *= *params[param_volume0 + i * band_params];
1189 cR_ *= *params[param_volume0 + i * band_params];
1191 // add filtered modulator
1192 cL_ += mL_ * *params[param_mod0 + i * band_params];
1193 cR_ += mR_ * *params[param_mod0 + i * band_params];
1195 // Balance
1196 cL_ *= (*params[param_pan0 + i * band_params] > 0
1197 ? -*params[param_pan0 + i * band_params] + 1 : 1);
1198 cR_ *= (*params[param_pan0 + i * band_params] < 0
1199 ? *params[param_pan0 + i * band_params] + 1 : 1);
1201 // add to outputs with proc level
1202 pL += cL_ * *params[param_proc];
1203 pR += cR_ * *params[param_proc];
1205 // LED
1206 if (*params[param_detectors] > 0.5)
1207 if (env_mods[0][i] + env_mods[1][i] > led[i])
1208 led[i] = env_mods[0][i] + env_mods[1][i];
1210 // advance envelopes
1211 env_mods[0][i] = (fabs(mL_) > env_mods[0][i] ? attack : release) * (env_mods[0][i] - fabs(mL_)) + fabs(mL_);
1212 env_mods[1][i] = (fabs(mR_) > env_mods[1][i] ? attack : release) * (env_mods[1][i] - fabs(mR_)) + fabs(mR_);
1215 outL = pL;
1216 outR = pR;
1218 // dry carrier
1219 outL += cL * *params[param_carrier];
1220 outR += cR * *params[param_carrier];
1222 // dry modulator
1223 outL += mL * *params[param_mod];
1224 outR += mR * *params[param_mod];
1226 // analyzer
1227 switch ((int)*params[param_analyzer]) {
1228 case 0:
1229 default:
1230 break;
1231 case 1:
1232 _analyzer.process((float)cL, (float)cR);
1233 break;
1234 case 2:
1235 _analyzer.process((float)mL, (float)mR);
1236 break;
1237 case 3:
1238 _analyzer.process((float)pL, (float)pR);
1239 break;
1240 case 4:
1241 _analyzer.process((float)outL, (float)outR);
1242 break;
1245 // out level
1246 outL *= *params[param_out];
1247 outR *= *params[param_out];
1249 // send to outputs
1250 outs[0][offset] = outL;
1251 outs[1][offset] = outR;
1253 // meters
1254 float values[] = {(float)cL, (float)cR, (float)mL, (float)mR, (float)outL, (float)outR};
1255 meters.process(values);
1257 // next sample
1258 ++offset;
1259 } // cycle trough samples
1260 bypass.crossfade(ins, outs, 2, orig_offset, orig_numsamples);
1261 // clean up
1262 for (int i = 0; i < bands; i++) {
1263 for (int j = 0; j < order; j++) {
1264 detector[0][j][i].sanitize();
1265 detector[1][j][i].sanitize();
1266 modulator[0][j][i].sanitize();
1267 modulator[1][j][i].sanitize();
1272 // LED
1273 for (int i = 0; i < 32; i++) {
1274 float val = 0;
1275 if (*params[param_detectors] > 0.5)
1276 val = std::max(0.0, 1 + log((led[i] / 2) * order) / log2_ / 10);
1277 *params[param_level0 + i * band_params] = val;
1279 meters.fall(orig_numsamples);
1280 return outputs_mask;
1282 bool vocoder_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1284 if (phase and *params[param_analyzer]) {
1285 if (subindex) {
1286 return false;
1288 bool r = _analyzer.get_graph(subindex, phase, data, points, context, mode);
1289 context->set_source_rgba(0,0,0,0.25);
1290 return r;
1291 } else if (phase) {
1292 return false;
1293 } else {
1294 // quit
1295 if (subindex >= bands) {
1296 redraw_graph = false;
1297 return false;
1299 int solo = get_solo();
1300 if (solo and !*params[param_solo0 + subindex * band_params])
1301 context->set_source_rgba(0,0,0,0.15);
1302 context->set_line_width(0.99);
1303 int drawn = 0;
1304 double fq = pow(10, fcoeff + (0.5f + (float)subindex) * 3.f / (float)bands);
1305 for (int i = 0; i < points; i++) {
1306 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
1307 float level = 1;
1308 for (int j = 0; j < order; j++)
1309 level *= detector[0][0][subindex].freq_gain(freq, srate);
1310 level *= *params[param_volume0 + subindex * band_params];
1311 data[i] = dB_grid(level, 256, 0.4);
1312 if (!drawn and freq > fq) {
1313 drawn = 1;
1314 char str[32];
1315 sprintf(str, "%d", subindex + 1);
1316 draw_cairo_label(context, str, i, context->size_y * (1 - (data[i] + 1) / 2.f), 0, 0, 0.5);
1320 return true;
1322 bool vocoder_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1324 redraw_graph = redraw_graph || !generation;
1325 layers = *params[param_analyzer] ? LG_REALTIME_GRAPH : 0;
1326 layers |= (generation ? LG_NONE : LG_CACHE_GRID) | (redraw_graph ? LG_CACHE_GRAPH : LG_NONE);
1327 redraw_graph |= (bool)*params[param_analyzer];
1328 return redraw_graph or !generation;