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
23 #include <calf/giface.h>
24 #include <calf/modules_filter.h>
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;
40 inline void undiff_ms(float &left
, float &right
) {
41 float tmp
= left
+ right
/ 2;
42 right
= left
- right
/ 2;
46 template<class BaseClass
, bool has_lphp
>
47 equalizerNband_audio_module
<BaseClass
, has_lphp
>::equalizerNband_audio_module()
52 hp_freq_old
= lp_freq_old
= 0;
53 hs_freq_old
= ls_freq_old
= 0;
54 hs_level_old
= ls_level_old
= 0;
59 for (int i
= 0; i
< AM::PeakBands
; i
++)
65 for (int i
= 0; i
< graph_param_count
; i
++)
66 old_params_for_graph
[i
] = -1;
70 template<class BaseClass
, bool has_lphp
>
71 void equalizerNband_audio_module
<BaseClass
, has_lphp
>::activate()
78 template<class BaseClass
, bool has_lphp
>
79 void equalizerNband_audio_module
<BaseClass
, has_lphp
>::deactivate()
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
++)
89 filters
[i
][j
].copy_coeffs(filters
[0][0]);
92 static inline double glide(double value
, double target
, int &keep_gliding
)
98 return std::min(target
, (value
+ 0.1) * 1.003);
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()
107 // set the params of all filters
109 // lp/hp first (if available)
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);
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);
127 lp_freq_old
= lpfreq
;
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
;
164 if (*params
[AM::param_individuals
] != indiv_old
) {
165 indiv_old
= *params
[AM::param_individuals
];
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
])
173 old_params_for_graph
[i
] = *params
[AM::first_graph_param
+ i
];
176 _analyzer
.set_params(
178 *params
[AM::param_analyzer_mode
] + (*params
[AM::param_analyzer_mode
] >= 3 ? 5 : 1),
182 if ((bool)*params
[AM::param_analyzer_active
] != analyzer_old
) {
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
)
193 int active
= *params
[AM::param_lp_active
];
196 if (active
> 3) diff_ms(left
, right
);
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
);
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
));
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
)));
218 if (active
> 3) undiff_ms(left
, right
);
220 active
= *params
[AM::param_hp_active
];
223 if (active
> 3) diff_ms(left
, right
);
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
);
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
));
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
)));
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
)
260 outputs_mask
|= process(offset
, 8, inputs_mask
, outputs_mask
);
267 numsamples
+= offset
;
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);
280 while(offset
< numsamples
) {
281 // cycle through samples
284 float inL
= ins
[0][offset
];
285 float inR
= ins
[1][offset
];
287 inR
*= *params
[AM::param_level_in
];
288 inL
*= *params
[AM::param_level_in
];
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
];
328 _analyzer
.process((inL
+ inR
) / 2.f
, (outL
+ outR
) / 2.f
);
331 outs
[0][offset
] = outL
;
332 outs
[1][offset
] = outR
;
334 float values
[] = {inL
, inR
, outL
, outR
};
335 meters
.process(values
);
339 } // cycle trough samples
341 for(int i
= 0; i
< 3; ++i
) {
349 for(int i
= 0; i
< AM::PeakBands
; ++i
) {
354 meters
.fall(numsamples
);
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
]) {
368 return gain
* gain
* gain
;
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);
382 context
->set_source_rgba(0,0,0,0.1);
385 } else if (phase
and !*params
[AM::param_analyzer_active
]) {
386 redraw_graph
= false;
389 int max
= PeakBands
+ 2 + (has_lphp
? 2 : 0);
392 or (subindex
and !*params
[AM::param_individuals
])
393 or (subindex
> max
and *params
[AM::param_individuals
])) {
394 redraw_graph
= false;
398 // first graph is the overall frequency response graph
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
) {
405 redraw_graph
= false;
409 // get the next filter to draw a curve for and leave out inactive
411 while (last_peak
< PeakBands
and !*params
[AM::param_p1_active
+ last_peak
* params_per_band
])
413 if (last_peak
== PeakBands
and !*params
[AM::param_ls_active
])
415 if (last_peak
== PeakBands
+ 1 and !*params
[AM::param_hs_active
])
417 if (has_lphp
and last_peak
== PeakBands
+ 2 and !*params
[AM::param_hp_active
])
419 if (has_lphp
and last_peak
== PeakBands
+ 3 and !*params
[AM::param_lp_active
])
422 // get out if max band is reached
423 if (last_peak
>= max
) { // and !*params[param_analyzer_active]) {
425 redraw_graph
= false;
428 //else if *params[param_analyzer_active]) {
429 //bool goon = _analyzer.get_graph(subindex, phase, data, points, context, mode);
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);
454 context
->set_source_rgba(0,0,0,0.075);
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
)
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
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;
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
)
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)
519 * (*params
[par_max_resonance
] - min_resonance
+ 0.001)
522 adjust_gain_according_to_filter_mode(last_velocity
);
524 inertia_filter_module::calculate_filter();
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
)
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(
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)
560 adjust_gain_according_to_filter_mode(vel
);
562 inertia_filter_module::calculate_filter();
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();
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
);
595 inertia_filter_module::inertia_gain
.set_now(min_gain
);
599 /**********************************************************************
600 * EMPHASIS by Damien Zammit
601 **********************************************************************/
603 emphasis_audio_module::emphasis_audio_module()
612 void emphasis_audio_module::activate()
619 void emphasis_audio_module::deactivate()
624 void emphasis_audio_module::params_changed()
626 if (mode
!= *params
[param_mode
] or type
!= *params
[param_type
] or bypass
!= *params
[param_bypass
])
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
;
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)
646 outputs_mask
|= process(offset
, 8, inputs_mask
, outputs_mask
);
651 numsamples
+= offset
;
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
);
663 while(offset
< numsamples
) {
664 // cycle through samples
667 float inL
= ins
[0][offset
];
668 float inR
= ins
[1][offset
];
670 inR
*= *params
[param_level_in
];
671 inL
*= *params
[param_level_in
];
676 procL
= riaacurvL
.process(procL
);
677 procR
= riaacurvR
.process(procR
);
679 outL
= procL
* *params
[param_level_out
];
680 outR
= procR
* *params
[param_level_out
];
683 outs
[0][offset
] = outL
;
684 outs
[1][offset
] = outR
;
686 float values
[] = {inL
, inR
, outL
, outR
};
687 meters
.process(values
);
691 } // cycle trough samples
693 riaacurvL
.sanitize();
694 riaacurvR
.sanitize();
696 meters
.fall(orig_numsamples
);
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
)
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
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()
724 crossover
.init(AM::channels
, AM::bands
, 44100);
726 template<class XoverBaseClass
>
727 xover_audio_module
<XoverBaseClass
>::~xover_audio_module()
731 template<class XoverBaseClass
>
732 void xover_audio_module
<XoverBaseClass
>::activate()
738 template<class XoverBaseClass
>
739 void xover_audio_module
<XoverBaseClass
>::deactivate()
743 template<class XoverBaseClass
>
744 void xover_audio_module
<XoverBaseClass
>::set_sample_rate(uint32_t sr
)
747 // set srate of crossover
748 crossover
.set_sample_rate(srate
);
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));
753 int amount
= AM::bands
* AM::channels
+ AM::channels
;
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);
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
;
789 float values
[AM::bands
* AM::channels
+ AM::channels
];
790 while(offset
< targ
) {
791 // cycle through samples
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
++) {
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
;
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
;
825 values
[b
* AM::channels
+ c
] = outs
[ptr
][offset
];
829 for (int c
= 0; c
< AM::channels
; c
++) {
830 values
[c
+ AM::bands
* AM::channels
] = ins
[c
][offset
];
832 meters
.process(values
);
835 // delay buffer pos forward
836 pos
= (pos
+ AM::channels
* AM::bands
) % buffer_size
;
838 } // cycle trough samples
839 meters
.fall(numsamples
);
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()
870 fcoeff
= log10(20.f
);
873 void vocoder_audio_module::activate()
878 void vocoder_audio_module::deactivate()
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
) {
891 for (int i
= 0; i
< 32; i
++) {
893 *params
[param_active0
+ i
* 4] = i
< bands
? 1 : 0;
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
]);
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
;
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
);
924 while(offset
< numsamples
) {
925 // cycle through samples
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
];
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
++) {
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]);
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
];
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_
);
974 outL
+= cL
* *params
[param_carrier
];
975 outR
+= cR
* *params
[param_carrier
];
978 outL
+= mL
* *params
[param_mod
];
979 outR
+= mR
* *params
[param_mod
];
982 switch ((int)*params
[param_analyzer
]) {
987 _analyzer
.process((float)cL
, (float)cR
);
990 _analyzer
.process((float)mL
, (float)mR
);
993 _analyzer
.process((float)pL
, (float)pR
);
996 _analyzer
.process((float)outL
, (float)outR
);
1001 outL
*= *params
[param_out
];
1002 outR
*= *params
[param_out
];
1005 outs
[0][offset
] = outL
;
1006 outs
[1][offset
] = outR
;
1009 float values
[] = {(float)cL
, (float)cR
, (float)mL
, (float)mR
, (float)outL
, (float)outR
};
1010 meters
.process(values
);
1014 } // cycle trough samples
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);
1032 } else if (phase
and (!*params
[param_analyzer
] or subindex
)) {
1033 redraw_graph
= false;
1037 if (subindex
>= bands
) {
1038 redraw_graph
= false;
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);
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
;