Vocoder: analyzer working
[calf.git] / src / modules_filter.cpp
blobc53aa03681107a466c3eb8bf9e7f2a7657698a48
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 = 0;
53 hs_freq_old = ls_freq_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];
117 if(hpfreq != hp_freq_old) {
118 hpfreq = glide(hp_freq_old, hpfreq, keep_gliding);
119 hp[0][0].set_hp_rbj(hpfreq, 0.707, (float)srate, 1.0);
120 copy_lphp(hp);
121 hp_freq_old = hpfreq;
123 if(lpfreq != lp_freq_old) {
124 lpfreq = glide(lp_freq_old, lpfreq, keep_gliding);
125 lp[0][0].set_lp_rbj(lpfreq, 0.707, (float)srate, 1.0);
126 copy_lphp(lp);
127 lp_freq_old = lpfreq;
131 // then shelves
132 float hsfreq = *params[AM::param_hs_freq], hslevel = *params[AM::param_hs_level];
133 float lsfreq = *params[AM::param_ls_freq], lslevel = *params[AM::param_ls_level];
135 if(lsfreq != ls_freq_old or lslevel != ls_level_old) {
136 lsfreq = glide(ls_freq_old, lsfreq, keep_gliding);
137 lsL.set_lowshelf_rbj(lsfreq, 0.707, lslevel, (float)srate);
138 lsR.copy_coeffs(lsL);
139 ls_level_old = lslevel;
140 ls_freq_old = lsfreq;
142 if(hsfreq != hs_freq_old or hslevel != hs_level_old) {
143 hsfreq = glide(hs_freq_old, hsfreq, keep_gliding);
144 hsL.set_highshelf_rbj(hsfreq, 0.707, hslevel, (float)srate);
145 hsR.copy_coeffs(hsL);
146 hs_level_old = hslevel;
147 hs_freq_old = hsfreq;
149 for (int i = 0; i < AM::PeakBands; i++)
151 int offset = i * params_per_band;
152 float freq = *params[AM::param_p1_freq + offset];
153 float level = *params[AM::param_p1_level + offset];
154 float q = *params[AM::param_p1_q + offset];
155 if(freq != p_freq_old[i] or level != p_level_old[i] or q != p_q_old[i]) {
156 freq = glide(p_freq_old[i], freq, keep_gliding);
157 pL[i].set_peakeq_rbj(freq, q, level, (float)srate);
158 pR[i].copy_coeffs(pL[i]);
159 p_freq_old[i] = freq;
160 p_level_old[i] = level;
161 p_q_old[i] = q;
164 if (*params[AM::param_individuals] != indiv_old) {
165 indiv_old = *params[AM::param_individuals];
166 redraw_graph = true;
169 // check if any important parameter for redrawing the graph changed
170 for (int i = 0; i < graph_param_count; i++) {
171 if (*params[AM::first_graph_param + i] != old_params_for_graph[i])
172 redraw_graph = true;
173 old_params_for_graph[i] = *params[AM::first_graph_param + i];
176 _analyzer.set_params(
177 256, 1, 6, 0, 1,
178 *params[AM::param_analyzer_mode] + (*params[AM::param_analyzer_mode] >= 3 ? 5 : 1),
179 0, 0, 15, 2, 0, 0
182 if ((bool)*params[AM::param_analyzer_active] != analyzer_old) {
183 redraw_graph = true;
184 analyzer_old = (bool)*params[AM::param_analyzer_active];
188 template<class BaseClass, bool has_lphp>
189 inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float &left, float &right)
191 if (!has_lphp)
192 return;
193 int active = *params[AM::param_lp_active];
194 if (active > 0.f)
196 if (active > 3) diff_ms(left, right);
197 switch(lp_mode)
199 case MODE12DB:
200 if (active == 1 or active == 2 or active == 4)
201 left = lp[0][0].process(left);
202 if (active == 1 or active == 3 or active == 5)
203 right = lp[0][1].process(right);
204 break;
205 case MODE24DB:
206 if (active == 1 or active == 2 or active == 4)
207 left = lp[1][0].process(lp[0][0].process(left));
208 if (active == 1 or active == 3 or active == 5)
209 right = lp[1][1].process(lp[0][1].process(right));
210 break;
211 case MODE36DB:
212 if (active == 1 or active == 2 or active == 4)
213 left = lp[2][0].process(lp[1][0].process(lp[0][0].process(left)));
214 if (active == 1 or active == 3 or active == 5)
215 right = lp[2][1].process(lp[1][1].process(lp[0][1].process(right)));
216 break;
218 if (active > 3) undiff_ms(left, right);
220 active = *params[AM::param_hp_active];
221 if (active > 0.f)
223 if (active > 3) diff_ms(left, right);
224 switch(hp_mode)
226 case MODE12DB:
227 if (active == 1 or active == 2 or active == 4)
228 left = hp[0][0].process(left);
229 if (active == 1 or active == 3 or active == 5)
230 right = hp[0][1].process(right);
231 break;
232 case MODE24DB:
233 if (active == 1 or active == 2 or active == 4)
234 left = hp[1][0].process(hp[0][0].process(left));
235 if (active == 1 or active == 3 or active == 5)
236 right = hp[1][1].process(hp[0][1].process(right));
237 break;
238 case MODE36DB:
239 if (active == 1 or active == 2 or active == 4)
240 left = hp[2][0].process(hp[1][0].process(hp[0][0].process(left)));
241 if (active == 1 or active == 3 or active == 5)
242 right = hp[2][1].process(hp[1][1].process(hp[0][1].process(right)));
243 break;
245 if (active > 3) undiff_ms(left, right);
249 template<class BaseClass, bool has_lphp>
250 uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
252 bool bypass = *params[AM::param_bypass] > 0.f;
253 if (keep_gliding && !bypass)
255 // ensure that if params have changed, the params_changed method is
256 // called every 8 samples to interpolate filter parameters
257 while(numsamples > 8 && keep_gliding)
259 params_changed();
260 outputs_mask |= process(offset, 8, inputs_mask, outputs_mask);
261 offset += 8;
262 numsamples -= 8;
264 if (keep_gliding)
265 params_changed();
267 numsamples += offset;
268 if(bypass) {
269 // everything bypassed
270 while(offset < numsamples) {
271 outs[0][offset] = ins[0][offset];
272 outs[1][offset] = ins[1][offset];
273 float values[] = {0, 0, 0, 0};
274 meters.process(values);
275 _analyzer.process(0, 0);
276 ++offset;
278 } else {
279 // process
280 while(offset < numsamples) {
281 // cycle through samples
282 float outL = 0.f;
283 float outR = 0.f;
284 float inL = ins[0][offset];
285 float inR = ins[1][offset];
286 // in level
287 inR *= *params[AM::param_level_in];
288 inL *= *params[AM::param_level_in];
290 float procL = inL;
291 float procR = inR;
293 // all filters in chain
294 process_hplp(procL, procR);
296 int active = *params[AM::param_ls_active];
297 if (active > 3) diff_ms(procL, procR);
298 if (active == 1 or active == 2 or active == 4)
299 procL = lsL.process(procL);
300 if (active == 1 or active == 3 or active == 5)
301 procR = lsR.process(procR);
302 if (active > 3) undiff_ms(procL, procR);
304 active = *params[AM::param_hs_active];
305 if (active > 3) diff_ms(procL, procR);
306 if (active == 1 or active == 2 or active == 4)
307 procL = hsL.process(procL);
308 if (active == 1 or active == 3 or active == 5)
309 procR = hsR.process(procR);
310 if (active > 3) undiff_ms(procL, procR);
312 for (int i = 0; i < AM::PeakBands; i++)
314 int offset = i * params_per_band;
315 int active = *params[AM::param_p1_active + offset];
316 if (active > 3) diff_ms(procL, procR);
317 if (active == 1 or active == 2 or active == 4)
318 procL = pL[i].process(procL);
319 if (active == 1 or active == 3 or active == 5)
320 procR = pR[i].process(procR);
321 if (active > 3) undiff_ms(procL, procR);
324 outL = procL * *params[AM::param_level_out];
325 outR = procR * *params[AM::param_level_out];
327 // analyzer
328 _analyzer.process((inL + inR) / 2.f, (outL + outR) / 2.f);
330 // send to output
331 outs[0][offset] = outL;
332 outs[1][offset] = outR;
334 float values[] = {inL, inR, outL, outR};
335 meters.process(values);
337 // next sample
338 ++offset;
339 } // cycle trough samples
340 // clean up
341 for(int i = 0; i < 3; ++i) {
342 hp[i][0].sanitize();
343 hp[i][1].sanitize();
344 lp[i][0].sanitize();
345 lp[i][1].sanitize();
347 lsL.sanitize();
348 hsR.sanitize();
349 for(int i = 0; i < AM::PeakBands; ++i) {
350 pL[i].sanitize();
351 pR[i].sanitize();
354 meters.fall(numsamples);
355 return outputs_mask;
358 static inline float adjusted_lphp_gain(const float *const *params, int param_active, int param_mode, const biquad_d2 &filter, float freq, float srate)
360 if(*params[param_active] > 0.f) {
361 float gain = filter.freq_gain(freq, srate);
362 switch((int)*params[param_mode]) {
363 case MODE12DB:
364 return gain;
365 case MODE24DB:
366 return gain * gain;
367 case MODE36DB:
368 return gain * gain * gain;
371 return 1;
374 template<class BaseClass, bool has_lphp>
375 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
377 if (phase and *params[AM::param_analyzer_active]) {
378 bool r = _analyzer.get_graph(subindex, phase, data, points, context, mode);
379 if (*params[AM::param_analyzer_mode] == 2) {
380 set_channel_color(context, subindex ? 0 : 1, 0.15);
381 } else {
382 context->set_source_rgba(0,0,0,0.1);
384 return r;
385 } else if (phase and !*params[AM::param_analyzer_active]) {
386 redraw_graph = false;
387 return false;
388 } else {
389 int max = PeakBands + 2 + (has_lphp ? 2 : 0);
391 if (!is_active
392 or (subindex and !*params[AM::param_individuals])
393 or (subindex > max and *params[AM::param_individuals])) {
394 redraw_graph = false;
395 return false;
398 // first graph is the overall frequency response graph
399 if (!subindex)
400 return ::get_graph(*this, subindex, data, points, 128 * *params[AM::param_zoom], 0);
402 // get out if max band is reached
403 if (last_peak >= max) {
404 last_peak = 0;
405 redraw_graph = false;
406 return false;
409 // get the next filter to draw a curve for and leave out inactive
410 // filters
411 while (last_peak < PeakBands and !*params[AM::param_p1_active + last_peak * params_per_band])
412 last_peak ++;
413 if (last_peak == PeakBands and !*params[AM::param_ls_active])
414 last_peak ++;
415 if (last_peak == PeakBands + 1 and !*params[AM::param_hs_active])
416 last_peak ++;
417 if (has_lphp and last_peak == PeakBands + 2 and !*params[AM::param_hp_active])
418 last_peak ++;
419 if (has_lphp and last_peak == PeakBands + 3 and !*params[AM::param_lp_active])
420 last_peak ++;
422 // get out if max band is reached
423 if (last_peak >= max) { // and !*params[param_analyzer_active]) {
424 last_peak = 0;
425 redraw_graph = false;
426 return false;
428 //else if *params[param_analyzer_active]) {
429 //bool goon = _analyzer.get_graph(subindex, phase, data, points, context, mode);
430 //if (!goon)
431 //last_peak = 0;
432 //return goon;
435 // draw the individual curve of the actual filter
436 for (int i = 0; i < points; i++) {
437 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
438 if (last_peak < PeakBands) {
439 data[i] = pL[last_peak].freq_gain(freq, (float)srate);
440 } else if (last_peak == PeakBands) {
441 data[i] = lsL.freq_gain(freq, (float)srate);
442 } else if (last_peak == PeakBands + 1) {
443 data[i] = hsL.freq_gain(freq, (float)srate);
444 } else if (last_peak == PeakBands + 2 and has_lphp) {
445 data[i] = adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)srate);
446 } else if (last_peak == PeakBands + 3 and has_lphp) {
447 data[i] = adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)srate);
449 data[i] = dB_grid(data[i], 128 * *params[AM::param_zoom], 0);
452 last_peak ++;
453 *mode = 4;
454 context->set_source_rgba(0,0,0,0.075);
455 return true;
458 template<class BaseClass, bool has_lphp>
459 bool equalizerNband_audio_module<BaseClass, has_lphp>::get_layers(int index, int generation, unsigned int &layers) const
461 redraw_graph = redraw_graph || !generation;
462 layers = *params[AM::param_analyzer_active] ? LG_REALTIME_GRAPH : 0;
463 layers |= (generation ? LG_NONE : LG_CACHE_GRID) | (redraw_graph ? LG_CACHE_GRAPH : LG_NONE);
464 redraw_graph |= (bool)*params[AM::param_analyzer_active];
465 return redraw_graph or !generation;
468 template<class BaseClass, bool has_lphp>
469 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
471 if (!is_active or phase)
472 return false;
473 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 128 * *params[AM::param_zoom], 0);
476 template<class BaseClass, bool has_lphp>
477 float equalizerNband_audio_module<BaseClass, has_lphp>::freq_gain(int index, double freq) const
479 float ret = 1.f;
480 if (has_lphp)
482 ret *= adjusted_lphp_gain(params, AM::param_hp_active, AM::param_hp_mode, hp[0][0], freq, (float)srate);
483 ret *= adjusted_lphp_gain(params, AM::param_lp_active, AM::param_lp_mode, lp[0][0], freq, (float)srate);
485 ret *= (*params[AM::param_ls_active] > 0.f) ? lsL.freq_gain(freq, (float)srate) : 1;
486 ret *= (*params[AM::param_hs_active] > 0.f) ? hsL.freq_gain(freq, (float)srate) : 1;
487 for (int i = 0; i < PeakBands; i++)
488 ret *= (*params[AM::param_p1_active + i * params_per_band] > 0.f) ? pL[i].freq_gain(freq, (float)srate) : 1;
489 return ret;
492 template class equalizerNband_audio_module<equalizer5band_metadata, false>;
493 template class equalizerNband_audio_module<equalizer8band_metadata, true>;
494 template class equalizerNband_audio_module<equalizer12band_metadata, true>;
497 /**********************************************************************
498 * FILTERKLAVIER by Hans Baier
499 **********************************************************************/
501 filterclavier_audio_module::filterclavier_audio_module()
502 : filter_module_with_inertia<biquad_filter_module, filterclavier_metadata>(ins, outs, params)
503 , min_gain(1.0)
504 , max_gain(32.0)
505 , last_note(-1)
506 , last_velocity(-1)
510 void filterclavier_audio_module::params_changed()
512 inertia_filter_module::inertia_cutoff.set_inertia(
513 note_to_hz(last_note + *params[par_transpose], *params[par_detune]));
515 float min_resonance = param_props[par_max_resonance].min;
516 inertia_filter_module::inertia_resonance.set_inertia(
517 (float(last_velocity) / 127.0)
518 // 0.001: see below
519 * (*params[par_max_resonance] - min_resonance + 0.001)
520 + min_resonance);
522 adjust_gain_according_to_filter_mode(last_velocity);
524 inertia_filter_module::calculate_filter();
525 redraw_graph = true;
528 void filterclavier_audio_module::activate()
530 inertia_filter_module::activate();
533 void filterclavier_audio_module::set_sample_rate(uint32_t sr)
535 inertia_filter_module::set_sample_rate(sr);
538 void filterclavier_audio_module::deactivate()
540 inertia_filter_module::deactivate();
544 void filterclavier_audio_module::note_on(int channel, int note, int vel)
546 last_note = note;
547 last_velocity = vel;
548 inertia_filter_module::inertia_cutoff.set_inertia(
549 note_to_hz(note + *params[par_transpose], *params[par_detune]));
551 float min_resonance = param_props[par_max_resonance].min;
552 inertia_filter_module::inertia_resonance.set_inertia(
553 (float(vel) / 127.0)
554 // 0.001: if the difference is equal to zero (which happens
555 // when the max_resonance knom is at minimum position
556 // then the filter gain doesnt seem to snap to zero on most note offs
557 * (*params[par_max_resonance] - min_resonance + 0.001)
558 + min_resonance);
560 adjust_gain_according_to_filter_mode(vel);
562 inertia_filter_module::calculate_filter();
563 redraw_graph = true;
566 void filterclavier_audio_module::note_off(int channel, int note, int vel)
568 if (note == last_note) {
569 inertia_filter_module::inertia_resonance.set_inertia(param_props[par_max_resonance].min);
570 inertia_filter_module::inertia_gain.set_inertia(min_gain);
571 inertia_filter_module::calculate_filter();
572 last_velocity = 0;
573 redraw_graph = true;
577 void filterclavier_audio_module::adjust_gain_according_to_filter_mode(int velocity)
579 int mode = dsp::fastf2i_drm(*params[par_mode]);
581 // for bandpasses: boost gain for velocities > 0
582 if ( (mode_6db_bp <= mode) && (mode <= mode_18db_bp) ) {
583 // gain for velocity 0: 1.0
584 // gain for velocity 127: 32.0
585 float mode_max_gain = max_gain;
586 // max_gain is right for mode_6db_bp
587 if (mode == mode_12db_bp)
588 mode_max_gain /= 6.0;
589 if (mode == mode_18db_bp)
590 mode_max_gain /= 10.5;
592 inertia_filter_module::inertia_gain.set_now(
593 (float(velocity) / 127.0) * (mode_max_gain - min_gain) + min_gain);
594 } else {
595 inertia_filter_module::inertia_gain.set_now(min_gain);
599 /**********************************************************************
600 * EMPHASIS by Damien Zammit
601 **********************************************************************/
603 emphasis_audio_module::emphasis_audio_module()
605 is_active = false;
606 srate = 0;
607 redraw_graph = true;
608 mode = -1;
609 type = -1;
612 void emphasis_audio_module::activate()
614 is_active = true;
615 // set all filters
616 params_changed();
619 void emphasis_audio_module::deactivate()
621 is_active = false;
624 void emphasis_audio_module::params_changed()
626 if (mode != *params[param_mode] or type != *params[param_type] or bypass != *params[param_bypass])
627 redraw_graph = true;
628 mode = *params[param_mode];
629 type = *params[param_type];
630 bypass = *params[param_bypass];
631 riaacurvL.set(srate, mode, type);
632 riaacurvR.set(srate, mode, type);
635 uint32_t emphasis_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
637 uint32_t orig_numsamples = numsamples;
638 bool bypass = *params[param_bypass] > 0.f;
639 if (!bypass)
641 // ensure that if params have changed, the params_changed method is
642 // called every 8 samples to interpolate filter parameters
643 while(numsamples > 8)
645 params_changed();
646 outputs_mask |= process(offset, 8, inputs_mask, outputs_mask);
647 offset += 8;
648 numsamples -= 8;
651 numsamples += offset;
652 if(bypass) {
653 // everything bypassed
654 while(offset < numsamples) {
655 outs[0][offset] = ins[0][offset];
656 outs[1][offset] = ins[1][offset];
657 float values[] = {0, 0, 0, 0};
658 meters.process(values);
659 ++offset;
661 } else {
662 // process
663 while(offset < numsamples) {
664 // cycle through samples
665 float outL = 0.f;
666 float outR = 0.f;
667 float inL = ins[0][offset];
668 float inR = ins[1][offset];
669 // in level
670 inR *= *params[param_level_in];
671 inL *= *params[param_level_in];
673 float procL = inL;
674 float procR = inR;
676 procL = riaacurvL.process(procL);
677 procR = riaacurvR.process(procR);
679 outL = procL * *params[param_level_out];
680 outR = procR * *params[param_level_out];
682 // send to output
683 outs[0][offset] = outL;
684 outs[1][offset] = outR;
686 float values[] = {inL, inR, outL, outR};
687 meters.process(values);
689 // next sample
690 ++offset;
691 } // cycle trough samples
692 // clean up
693 riaacurvL.sanitize();
694 riaacurvR.sanitize();
696 meters.fall(orig_numsamples);
697 return outputs_mask;
699 bool emphasis_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
701 if (phase or subindex)
702 return false;
703 if (bypass)
704 context->set_source_rgba(0.15, 0.2, 0.0, 0.3);
705 return ::get_graph(*this, subindex, data, points, 32, 0);
707 bool emphasis_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
709 if (phase)
710 return false;
711 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 32, 0);
714 /**********************************************************************
715 * CROSSOVER N BAND by Markus Schmidt
716 **********************************************************************/
718 template<class XoverBaseClass>
719 xover_audio_module<XoverBaseClass>::xover_audio_module()
721 is_active = false;
722 srate = 0;
723 redraw_graph = true;
724 crossover.init(AM::channels, AM::bands, 44100);
726 template<class XoverBaseClass>
727 xover_audio_module<XoverBaseClass>::~xover_audio_module()
729 free(buffer);
731 template<class XoverBaseClass>
732 void xover_audio_module<XoverBaseClass>::activate()
734 is_active = true;
735 params_changed();
738 template<class XoverBaseClass>
739 void xover_audio_module<XoverBaseClass>::deactivate()
741 is_active = false;
743 template<class XoverBaseClass>
744 void xover_audio_module<XoverBaseClass>::set_sample_rate(uint32_t sr)
746 srate = sr;
747 // set srate of crossover
748 crossover.set_sample_rate(srate);
749 // rebuild buffer
750 buffer_size = (int)(srate / 10 * AM::channels * AM::bands + AM::channels * AM::bands); // buffer size attack rate multiplied by channels and bands
751 buffer = (float*) calloc(buffer_size, sizeof(float));
752 pos = 0;
753 int amount = AM::bands * AM::channels + AM::channels;
754 int meter[amount];
755 int clip[amount];
756 for(int b = 0; b < AM::bands; b++) {
757 for (int c = 0; c < AM::channels; c++) {
758 meter[b * AM::channels + c] = AM::param_meter_01 + b * params_per_band + c;
759 clip[b * AM::channels + c] = -1;
762 for (int c = 0; c < AM::channels; c++) {
763 meter[c + AM::bands * AM::channels] = AM::param_meter_0 + c;
764 clip[c + AM::bands * AM::channels] = -1;
766 meters.init(params, meter, clip, amount, srate);
768 template<class XoverBaseClass>
769 void xover_audio_module<XoverBaseClass>::params_changed()
771 int mode = *params[AM::param_mode];
772 crossover.set_mode(mode);
773 for (int i = 0; i < AM::bands - 1; i++) {
774 crossover.set_filter(i, *params[AM::param_freq0 + i]);
776 for (int i = 0; i < AM::bands; i++) {
777 int offset = i * params_per_band;
778 crossover.set_level(i, *params[AM::param_level1 + offset]);
779 crossover.set_active(i, *params[AM::param_active1 + offset] > 0.5);
781 redraw_graph = true;
784 template<class XoverBaseClass>
785 uint32_t xover_audio_module<XoverBaseClass>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
787 unsigned int targ = numsamples + offset;
788 float xval;
789 float values[AM::bands * AM::channels + AM::channels];
790 while(offset < targ) {
791 // cycle through samples
793 // level
794 for (int c = 0; c < AM::channels; c++) {
795 in[c] = ins[c][offset] * *params[AM::param_level];
797 crossover.process(in);
799 for (int b = 0; b < AM::bands; b++) {
800 int nbuf = 0;
801 int off = b * params_per_band;
802 // calc position in delay buffer
803 if (*params[AM::param_delay1 + off]) {
804 nbuf = srate * (fabs(*params[AM::param_delay1 + off]) / 1000.f) * AM::bands * AM::channels;
805 nbuf -= nbuf % (AM::bands * AM::channels);
807 for (int c = 0; c < AM::channels; c++) {
808 // define a pointer between 0 and channels * bands
809 int ptr = b * AM::channels + c;
811 // get output from crossover module if active
812 xval = *params[AM::param_active1 + off] > 0.5 ? crossover.get_value(c, b) : 0.f;
814 // fill delay buffer
815 buffer[pos + ptr] = xval;
817 // get value from delay buffer if neccessary
818 if (*params[AM::param_delay1 + off])
819 xval = buffer[(pos - (int)nbuf + ptr + buffer_size) % buffer_size];
821 // set value with phase to output
822 outs[ptr][offset] = *params[AM::param_phase1 + off] > 0.5 ? xval * -1 : xval;
824 // band meters
825 values[b * AM::channels + c] = outs[ptr][offset];
828 // in meters
829 for (int c = 0; c < AM::channels; c++) {
830 values[c + AM::bands * AM::channels] = ins[c][offset];
832 meters.process(values);
833 // next sample
834 ++offset;
835 // delay buffer pos forward
836 pos = (pos + AM::channels * AM::bands) % buffer_size;
838 } // cycle trough samples
839 meters.fall(numsamples);
840 return outputs_mask;
843 template<class XoverBaseClass>
844 bool xover_audio_module<XoverBaseClass>::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
846 return crossover.get_graph(subindex, phase, data, points, context, mode);
848 template<class XoverBaseClass>
849 bool xover_audio_module<XoverBaseClass>::get_layers(int index, int generation, unsigned int &layers) const
851 return crossover.get_layers(index, generation, layers);
854 template class xover_audio_module<xover2_metadata>;
855 template class xover_audio_module<xover3_metadata>;
856 template class xover_audio_module<xover4_metadata>;
859 /**********************************************************************
860 * Vocoder by Markus Schmidt and Christian Holschuh
861 **********************************************************************/
863 vocoder_audio_module::vocoder_audio_module()
865 is_active = false;
866 srate = 0;
867 attack = 0;
868 release = 0;
869 bands = 0;
870 fcoeff = log10(20.f);
873 void vocoder_audio_module::activate()
875 is_active = true;
878 void vocoder_audio_module::deactivate()
880 is_active = false;
883 void vocoder_audio_module::params_changed()
885 attack = exp(log(0.01)/( *params[param_attack] * srate * 0.001));
886 release = exp(log(0.01)/( *params[param_release] * srate * 0.001));
888 bands = 4 * (1 << (int)*params[param_bands_knob]);
889 if (bands != bands_old) {
890 bands_old = bands;
891 for (int i = 0; i < 32; i++) {
892 // set active LED
893 *params[param_active0 + i * 4] = i < bands ? 1 : 0;
894 if(i < bands) {
895 // set all actually used filters
896 detector[0][i].set_bp_rbj(pow(10, fcoeff + (0.5f + (float)i) * 3.f / (float)bands), 1.0, (double)srate);
897 detector[1][i].copy_coeffs(detector[0][i]);
898 modulator[0][i].copy_coeffs(detector[0][i]);
899 modulator[1][i].copy_coeffs(detector[0][i]);
902 redraw_graph = true;
904 //void analyzer::set_params(float resolution, float offset, int accuracy, int hold, int smoothing, int mode, int scale, int post, int speed, int windowing, int view, int freeze)
905 _analyzer.set_params(256, 1, 6, 0, 1, 0, 0, 0, 15, 2, 0, 0);
908 uint32_t vocoder_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
910 uint32_t orig_numsamples = numsamples;
911 bool bypass = *params[param_bypass] > 0.f;
912 numsamples += offset;
913 if(bypass) {
914 // everything bypassed
915 while(offset < numsamples) {
916 outs[0][offset] = ins[0][offset];
917 outs[1][offset] = ins[1][offset];
918 float values[] = {0, 0, 0, 0, 0, 0};
919 meters.process(values);
920 ++offset;
922 } else {
923 // process
924 while(offset < numsamples) {
925 // cycle through samples
926 double outL = 0;
927 double outR = 0;
928 double pL = 0;
929 double pR = 0;
931 // carrier with level
932 double cL = ins[0][offset] * *params[param_carrier_in];
933 double cR = ins[(!*params[param_mono] > 0.5f) ? 1 : 0][offset] * *params[param_carrier_in];
935 // modulator with level
936 double mL = ins[2][offset] * *params[param_mod_in];
937 double mR = ins[(!*params[param_mono] > 0.5f) ? 3 : 2][offset] * *params[param_mod_in];
939 // noise generator
940 double nL = (float)rand() / (float)RAND_MAX;
941 double nR = *params[param_mono] > 0.5f ? nL : (float)rand() / (float)RAND_MAX;
943 for (int i = 0; i < bands; i++) {
945 // filter modulator
946 double mL_ = detector[0][i].process(mL);
947 double mR_ = detector[1][i].process(mR);
949 // filter carrier with noise
950 double cL_ = modulator[0][i].process(cL + nL * *params[param_noise0 + i * 4]);
951 double cR_ = modulator[1][i].process(cL + nR * *params[param_noise0 + i * 4]);
953 // level by envelope
954 cL_ *= envelope[0][i];
955 cR_ *= envelope[1][i];
957 // add band volume setting
958 cL_ *= *params[param_volume0 + i * 4];
959 cR_ *= *params[param_volume0 + i * 4];
961 // add to outputs with proc level
962 pL += cL_ * *params[param_proc];
963 pR += cR_ * *params[param_proc];
965 // advance envelopes
966 envelope[0][i] = (fabs(mL_) > envelope[0][i] ? attack : release) * (envelope[0][i] - fabs(mL_)) + fabs(mL_);
967 envelope[1][i] = (fabs(mR_) > envelope[1][i] ? attack : release) * (envelope[1][i] - fabs(mR_)) + fabs(mR_);
970 outL = pL;
971 outR = pR;
973 // dry carrier
974 outL += cL * *params[param_carrier];
975 outR += cR * *params[param_carrier];
977 // dry modulator
978 outL += mL * *params[param_mod];
979 outR += mR * *params[param_mod];
981 // analyzer
982 switch ((int)*params[param_analyzer]) {
983 case 0:
984 default:
985 break;
986 case 1:
987 _analyzer.process((float)cL, (float)cR);
988 break;
989 case 2:
990 _analyzer.process((float)mL, (float)mR);
991 break;
992 case 3:
993 _analyzer.process((float)pL, (float)pR);
994 break;
995 case 4:
996 _analyzer.process((float)outL, (float)outR);
997 break;
1000 // out level
1001 outL *= *params[param_out];
1002 outR *= *params[param_out];
1004 // send to outputs
1005 outs[0][offset] = outL;
1006 outs[1][offset] = outR;
1008 // meters
1009 float values[] = {(float)cL, (float)cR, (float)mL, (float)mR, (float)outL, (float)outR};
1010 meters.process(values);
1012 // next sample
1013 ++offset;
1014 } // cycle trough samples
1015 // clean up
1016 for (int i = 0; i < 32; i++) {
1017 detector[0][i].sanitize();
1018 detector[1][i].sanitize();
1019 modulator[0][i].sanitize();
1020 modulator[1][i].sanitize();
1023 meters.fall(orig_numsamples);
1024 return outputs_mask;
1026 bool vocoder_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
1028 if (phase and *params[param_analyzer]) {
1029 bool r = _analyzer.get_graph(subindex, phase, data, points, context, mode);
1030 context->set_source_rgba(0,0,0,0.1);
1031 return r;
1032 } else if (phase and (!*params[param_analyzer] or subindex)) {
1033 redraw_graph = false;
1034 return false;
1035 } else {
1036 // quit
1037 if (subindex >= bands) {
1038 redraw_graph = false;
1039 return false;
1040 } else {
1041 for (int i = 0; i < points; i++) {
1042 double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
1043 data[i] = dB_grid(detector[0][subindex].freq_gain(freq, srate), 256, 0.4);
1047 return true;
1049 bool vocoder_audio_module::get_layers(int index, int generation, unsigned int &layers) const
1051 redraw_graph = redraw_graph || !generation;
1052 layers = *params[param_analyzer] ? LG_REALTIME_GRAPH : 0;
1053 layers |= (generation ? LG_NONE : LG_CACHE_GRID) | (redraw_graph ? LG_CACHE_GRAPH : LG_NONE);
1054 redraw_graph |= (bool)*params[param_analyzer];
1055 return redraw_graph or !generation;