2 * Example audio modules
4 * Copyright (C) 2001-2007 Krzysztof Foltman
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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_MODULES_H
22 #define __CALF_MODULES_H
29 #include "multichorus.h"
33 #include "primitives.h"
35 namespace calf_plugins
{
39 struct ladspa_plugin_info
;
42 class amp_audio_module
: public null_audio_module
45 enum { in_count
= 2, out_count
= 2, param_count
= 1, support_midi
= false, require_midi
= false, rt_capable
= true };
50 static parameter_properties param_props
[];
51 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
54 float gain
= *params
[0];
56 for (uint32_t i
= offset
; i
< numsamples
; i
++) {
57 outs
[0][i
] = ins
[0][i
] * gain
;
58 outs
[1][i
] = ins
[1][i
] * gain
;
65 class frequency_response_line_graph
: public line_graph_iface
68 bool get_gridline(int index
, int subindex
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
);
69 virtual int get_changed_offsets(int generation
, int &subindex_graph
, int &subindex_dot
, int &subindex_gridline
);
72 class flanger_audio_module
: public audio_module
<flanger_metadata
>, public frequency_response_line_graph
75 dsp::simple_flanger
<float, 2048> left
, right
;
77 float *outs
[out_count
];
78 float *params
[param_count
];
84 flanger_audio_module() {
87 void set_sample_rate(uint32_t sr
);
88 void params_changed() {
89 float dry
= *params
[par_dryamount
];
90 float wet
= *params
[par_amount
];
91 float rate
= *params
[par_rate
]; // 0.01*pow(1000.0f,*params[par_rate]);
92 float min_delay
= *params
[par_delay
] / 1000.0;
93 float mod_depth
= *params
[par_depth
] / 1000.0;
94 float fb
= *params
[par_fb
];
95 left
.set_dry(dry
); right
.set_dry(dry
);
96 left
.set_wet(wet
); right
.set_wet(wet
);
97 left
.set_rate(rate
); right
.set_rate(rate
);
98 left
.set_min_delay(min_delay
); right
.set_min_delay(min_delay
);
99 left
.set_mod_depth(mod_depth
); right
.set_mod_depth(mod_depth
);
100 left
.set_fb(fb
); right
.set_fb(fb
);
101 float r_phase
= *params
[par_stereo
] * (1.f
/ 360.f
);
103 if (*params
[par_reset
] >= 0.5) {
105 left
.reset_phase(0.f
);
106 right
.reset_phase(r_phase
);
108 if (fabs(r_phase
- last_r_phase
) > 0.0001f
) {
109 right
.phase
= left
.phase
;
110 right
.inc_phase(r_phase
);
111 last_r_phase
= r_phase
;
118 *params
[par_reset
] = 0.f
;
124 uint32_t process(uint32_t offset
, uint32_t nsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
125 left
.process(outs
[0] + offset
, ins
[0] + offset
, nsamples
);
126 right
.process(outs
[1] + offset
, ins
[1] + offset
, nsamples
);
127 return outputs_mask
; // XXXKF allow some delay after input going blank
129 bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
130 float freq_gain(int subindex
, float freq
, float srate
);
133 class phaser_audio_module
: public audio_module
<phaser_metadata
>, public frequency_response_line_graph
136 float *ins
[in_count
];
137 float *outs
[out_count
];
138 float *params
[param_count
];
142 dsp::simple_phaser
<12> left
, right
;
145 phaser_audio_module() {
148 void params_changed() {
149 float dry
= *params
[par_dryamount
];
150 float wet
= *params
[par_amount
];
151 float rate
= *params
[par_rate
]; // 0.01*pow(1000.0f,*params[par_rate]);
152 float base_frq
= *params
[par_freq
];
153 float mod_depth
= *params
[par_depth
];
154 float fb
= *params
[par_fb
];
155 int stages
= (int)*params
[par_stages
];
156 left
.set_dry(dry
); right
.set_dry(dry
);
157 left
.set_wet(wet
); right
.set_wet(wet
);
158 left
.set_rate(rate
); right
.set_rate(rate
);
159 left
.set_base_frq(base_frq
); right
.set_base_frq(base_frq
);
160 left
.set_mod_depth(mod_depth
); right
.set_mod_depth(mod_depth
);
161 left
.set_fb(fb
); right
.set_fb(fb
);
162 left
.set_stages(stages
); right
.set_stages(stages
);
163 float r_phase
= *params
[par_stereo
] * (1.f
/ 360.f
);
165 if (*params
[par_reset
] >= 0.5) {
167 left
.reset_phase(0.f
);
168 right
.reset_phase(r_phase
);
170 if (fabs(r_phase
- last_r_phase
) > 0.0001f
) {
171 right
.phase
= left
.phase
;
172 right
.inc_phase(r_phase
);
173 last_r_phase
= r_phase
;
180 *params
[par_reset
] = 0.f
;
185 void set_sample_rate(uint32_t sr
);
187 uint32_t process(uint32_t offset
, uint32_t nsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
188 left
.process(outs
[0] + offset
, ins
[0] + offset
, nsamples
);
189 right
.process(outs
[1] + offset
, ins
[1] + offset
, nsamples
);
190 return outputs_mask
; // XXXKF allow some delay after input going blank
192 bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
193 bool get_gridline(int index
, int subindex
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
);
194 float freq_gain(int subindex
, float freq
, float srate
);
197 class reverb_audio_module
: public audio_module
<reverb_metadata
>
200 dsp::reverb
<float> reverb
;
201 dsp::simple_delay
<16384, stereo_sample
<float> > pre_delay
;
202 dsp::onepole
<float> left_lo
, right_lo
, left_hi
, right_hi
;
204 gain_smoothing amount
, dryamount
;
206 float *ins
[in_count
];
207 float *outs
[out_count
];
208 float *params
[param_count
];
210 void params_changed() {
211 //reverb.set_time(0.5*pow(8.0f, *params[par_decay]));
212 //reverb.set_cutoff(2000*pow(10.0f, *params[par_hfdamp]));
213 reverb
.set_type_and_diffusion(fastf2i_drm(*params
[par_roomsize
]), *params
[par_diffusion
]);
214 reverb
.set_time(*params
[par_decay
]);
215 reverb
.set_cutoff(*params
[par_hfdamp
]);
216 amount
.set_inertia(*params
[par_amount
]);
217 dryamount
.set_inertia(*params
[par_dry
]);
218 left_lo
.set_lp(dsp::clip(*params
[par_treblecut
], 20.f
, (float)(srate
* 0.49f
)), srate
);
219 left_hi
.set_hp(dsp::clip(*params
[par_basscut
], 20.f
, (float)(srate
* 0.49f
)), srate
);
220 right_lo
.copy_coeffs(left_lo
);
221 right_hi
.copy_coeffs(left_hi
);
222 predelay_amt
= (int) (srate
* (*params
[par_predelay
]) * (1.0f
/ 1000.0f
) + 1);
224 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
225 numsamples
+= offset
;
227 for (uint32_t i
= offset
; i
< numsamples
; i
++) {
228 float dry
= dryamount
.get();
229 float wet
= amount
.get();
230 stereo_sample
<float> s(ins
[0][i
], ins
[1][i
]);
231 stereo_sample
<float> s2
= pre_delay
.process(s
, predelay_amt
);
233 float rl
= s2
.left
, rr
= s2
.right
;
234 rl
= left_lo
.process(left_hi
.process(rl
));
235 rr
= right_lo
.process(right_hi
.process(rr
));
236 reverb
.process(rl
, rr
);
237 outs
[0][i
] = dry
*s
.left
+ wet
*rl
;
238 outs
[1][i
] = dry
*s
.right
+ wet
*rr
;
240 reverb
.extra_sanitize();
248 void set_sample_rate(uint32_t sr
);
252 class vintage_delay_audio_module
: public audio_module
<vintage_delay_metadata
>
255 // 1MB of delay memory per channel... uh, RAM is cheap
256 enum { MAX_DELAY
= 262144, ADDR_MASK
= MAX_DELAY
- 1 };
257 float *ins
[in_count
];
258 float *outs
[out_count
];
259 float *params
[param_count
];
260 float buffers
[2][MAX_DELAY
];
261 int bufptr
, deltime_l
, deltime_r
, mixmode
, medium
, old_medium
;
262 gain_smoothing amt_left
, amt_right
, fb_left
, fb_right
;
265 dsp::biquad_d2
<float> biquad_left
[2], biquad_right
[2];
269 vintage_delay_audio_module()
274 void params_changed()
276 float unit
= 60.0 * srate
/ (*params
[par_bpm
] * *params
[par_divide
]);
277 deltime_l
= dsp::fastf2i_drm(unit
* *params
[par_time_l
]);
278 deltime_r
= dsp::fastf2i_drm(unit
* *params
[par_time_r
]);
279 amt_left
.set_inertia(*params
[par_amount
]); amt_right
.set_inertia(*params
[par_amount
]);
280 float fb
= *params
[par_feedback
];
281 dry
= *params
[par_dryamount
];
282 mixmode
= dsp::fastf2i_drm(*params
[par_mixmode
]);
283 medium
= dsp::fastf2i_drm(*params
[par_medium
]);
286 fb_left
.set_inertia(fb
);
287 fb_right
.set_inertia(pow(fb
, *params
[par_time_r
] / *params
[par_time_l
]));
289 fb_left
.set_inertia(fb
);
290 fb_right
.set_inertia(fb
);
292 if (medium
!= old_medium
)
300 void set_sample_rate(uint32_t sr
) {
303 amt_left
.set_sample_rate(sr
); amt_right
.set_sample_rate(sr
);
304 fb_left
.set_sample_rate(sr
); fb_right
.set_sample_rate(sr
);
309 // parameters are heavily influenced by gordonjcp and his tape delay unit
310 // although, don't blame him if it sounds bad - I've messed with them too :)
311 biquad_left
[0].set_lp_rbj(6000, 0.707, srate
);
312 biquad_left
[1].set_bp_rbj(4500, 0.250, srate
);
313 biquad_right
[0].copy_coeffs(biquad_left
[0]);
314 biquad_right
[1].copy_coeffs(biquad_left
[1]);
316 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
317 uint32_t ostate
= 3; // XXXKF optimize!
318 uint32_t end
= offset
+ numsamples
;
319 int v
= mixmode
? 1 : 0;
320 int orig_bufptr
= bufptr
;
321 for(uint32_t i
= offset
; i
< end
; i
++)
323 float in_left
= buffers
[v
][(bufptr
- deltime_l
) & ADDR_MASK
], in_right
= buffers
[1 - v
][(bufptr
- deltime_r
) & ADDR_MASK
], out_left
, out_right
, del_left
, del_right
;
324 dsp::sanitize(in_left
), dsp::sanitize(in_right
);
326 out_left
= dry
* ins
[0][i
] + in_left
* amt_left
.get();
327 out_right
= dry
* ins
[1][i
] + in_right
* amt_right
.get();
328 del_left
= ins
[0][i
] + in_left
* fb_left
.get();
329 del_right
= ins
[1][i
] + in_right
* fb_right
.get();
331 outs
[0][i
] = out_left
; outs
[1][i
] = out_right
; buffers
[0][bufptr
] = del_left
; buffers
[1][bufptr
] = del_right
;
332 bufptr
= (bufptr
+ 1) & (MAX_DELAY
- 1);
335 bufptr
= orig_bufptr
;
338 for(uint32_t i
= offset
; i
< end
; i
++)
340 buffers
[0][bufptr
] = biquad_left
[0].process_lp(biquad_left
[1].process(buffers
[0][bufptr
]));
341 buffers
[1][bufptr
] = biquad_right
[0].process_lp(biquad_right
[1].process(buffers
[1][bufptr
]));
342 bufptr
= (bufptr
+ 1) & (MAX_DELAY
- 1);
344 biquad_left
[0].sanitize();biquad_right
[0].sanitize();
346 for(uint32_t i
= offset
; i
< end
; i
++)
348 buffers
[0][bufptr
] = biquad_left
[1].process(buffers
[0][bufptr
]);
349 buffers
[1][bufptr
] = biquad_right
[1].process(buffers
[1][bufptr
]);
350 bufptr
= (bufptr
+ 1) & (MAX_DELAY
- 1);
353 biquad_left
[1].sanitize();biquad_right
[1].sanitize();
360 class rotary_speaker_audio_module
: public audio_module
<rotary_speaker_metadata
>
363 float *ins
[in_count
];
364 float *outs
[out_count
];
365 float *params
[param_count
];
366 /// Current phases and phase deltas for bass and treble rotors
367 uint32_t phase_l
, dphase_l
, phase_h
, dphase_h
;
368 dsp::simple_delay
<1024, float> delay
;
369 dsp::biquad_d2
<float> crossover1l
, crossover1r
, crossover2l
, crossover2r
;
370 dsp::simple_delay
<8, float> phaseshift
;
373 /// Current CC1 (Modulation) value, normalized to [0, 1]
375 /// Current CC64 (Hold) value, normalized to [0, 1]
377 /// Current rotation speed for bass rotor - automatic mode
379 /// Current rotation speed for treble rotor - automatic mode
381 /// Desired speed (0=slow, 1=fast) - automatic mode
383 /// Current rotation speed for bass rotor - manual mode
385 /// Current rotation speed for treble rotor - manual mode
388 rotary_speaker_audio_module();
389 void set_sample_rate(uint32_t sr
);
394 void params_changed() {
399 vibrato_mode
= fastf2i_drm(*params
[par_speed
]);
400 // manual vibrato - do not recalculate speeds as they're not used anyway
401 if (vibrato_mode
== 5)
406 float speed
= vibrato_mode
- 1;
407 if (vibrato_mode
== 3)
409 if (vibrato_mode
== 4)
411 dspeed
= (speed
< 0.5f
) ? 0 : 1;
415 /// Convert RPM speed to delta-phase
416 inline uint32_t rpm2dphase(float rpm
)
418 return (uint32_t)((rpm
/ (60.0 * srate
)) * (1 << 30)) << 2;
420 /// Set delta-phase variables based on current calculated (and interpolated) RPM speed
423 float speed_h
= aspeed_h
>= 0 ? (48 + (400-48) * aspeed_h
) : (48 * (1 + aspeed_h
));
424 float speed_l
= aspeed_l
>= 0 ? 40 + (342-40) * aspeed_l
: (40 * (1 + aspeed_l
));
425 dphase_h
= rpm2dphase(speed_h
);
426 dphase_l
= rpm2dphase(speed_l
);
428 void update_speed_manual(float delta
)
430 float ts
= *params
[par_treblespeed
];
431 float bs
= *params
[par_bassspeed
];
432 incr_towards(maspeed_h
, ts
, delta
* 200, delta
* 200);
433 incr_towards(maspeed_l
, bs
, delta
* 200, delta
* 200);
434 dphase_h
= rpm2dphase(maspeed_h
);
435 dphase_l
= rpm2dphase(maspeed_l
);
437 /// map a ramp [int] to a sinusoid-like function [0, 65536]
438 static inline int pseudo_sine_scl(int counter
)
440 // premature optimization is a root of all evil; it can be done with integers only - but later :)
441 double v
= counter
* (1.0 / (65536.0 * 32768.0));
442 return (int) (32768 + 32768 * (v
- v
*v
*v
) * (1.0 / 0.3849));
444 /// Increase or decrease aspeed towards raspeed, with required negative and positive rate
445 inline bool incr_towards(float &aspeed
, float raspeed
, float delta_decc
, float delta_acc
)
447 if (aspeed
< raspeed
) {
448 aspeed
= std::min(raspeed
, aspeed
+ delta_acc
);
451 else if (aspeed
> raspeed
)
453 aspeed
= std::max(raspeed
, aspeed
- delta_decc
);
458 uint32_t process(uint32_t offset
, uint32_t nsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
)
460 int shift
= (int)(300000 * (*params
[par_shift
])), pdelta
= (int)(300000 * (*params
[par_spacing
]));
461 int md
= (int)(100 * (*params
[par_moddepth
]));
462 float mix
= 0.5 * (1.0 - *params
[par_micdistance
]);
463 float mix2
= *params
[par_reflection
];
464 float mix3
= mix2
* mix2
;
465 for (unsigned int i
= 0; i
< nsamples
; i
++) {
466 float in_l
= ins
[0][i
+ offset
], in_r
= ins
[1][i
+ offset
];
467 float in_mono
= 0.5f
* (in_l
+ in_r
);
469 int xl
= pseudo_sine_scl(phase_l
), yl
= pseudo_sine_scl(phase_l
+ 0x40000000);
470 int xh
= pseudo_sine_scl(phase_h
), yh
= pseudo_sine_scl(phase_h
+ 0x40000000);
471 // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl);
473 // float out_hi_l = in_mono - delay.get_interp_1616(shift + md * xh) + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yh) - delay.get_interp_1616(shift + md * 65536 + pdelta + pdelta - md * xh);
474 // float out_hi_r = in_mono + delay.get_interp_1616(shift + md * 65536 - md * yh) - delay.get_interp_1616(shift + pdelta + md * xh) + delay.get_interp_1616(shift + pdelta + pdelta + md * yh);
475 float out_hi_l
= in_mono
+ delay
.get_interp_1616(shift
+ md
* xh
) - mix2
* delay
.get_interp_1616(shift
+ md
* 65536 + pdelta
- md
* yh
) + mix3
* delay
.get_interp_1616(shift
+ md
* 65536 + pdelta
+ pdelta
- md
* xh
);
476 float out_hi_r
= in_mono
+ delay
.get_interp_1616(shift
+ md
* 65536 - md
* yh
) - mix2
* delay
.get_interp_1616(shift
+ pdelta
+ md
* xh
) + mix3
* delay
.get_interp_1616(shift
+ pdelta
+ pdelta
+ md
* yh
);
478 float out_lo_l
= in_mono
+ delay
.get_interp_1616(shift
+ md
* xl
); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl);
479 float out_lo_r
= in_mono
+ delay
.get_interp_1616(shift
+ md
* yl
); // - delay.get_interp_1616(shift + pdelta + md * yl);
481 out_hi_l
= crossover2l
.process(out_hi_l
); // sanitize(out_hi_l);
482 out_hi_r
= crossover2r
.process(out_hi_r
); // sanitize(out_hi_r);
483 out_lo_l
= crossover1l
.process(out_lo_l
); // sanitize(out_lo_l);
484 out_lo_r
= crossover1r
.process(out_lo_r
); // sanitize(out_lo_r);
486 float out_l
= out_hi_l
+ out_lo_l
;
487 float out_r
= out_hi_r
+ out_lo_r
;
489 float mic_l
= out_l
+ mix
* (out_r
- out_l
);
490 float mic_r
= out_r
+ mix
* (out_l
- out_r
);
492 outs
[0][i
+ offset
] = mic_l
* 0.5f
;
493 outs
[1][i
+ offset
] = mic_r
* 0.5f
;
498 crossover1l
.sanitize();
499 crossover1r
.sanitize();
500 crossover2l
.sanitize();
501 crossover2r
.sanitize();
502 float delta
= nsamples
* 1.0 / srate
;
503 if (vibrato_mode
== 5)
504 update_speed_manual(delta
);
507 bool u1
= incr_towards(aspeed_l
, dspeed
, delta
* 0.2, delta
* 0.14);
508 bool u2
= incr_towards(aspeed_h
, dspeed
, delta
, delta
* 0.5);
514 virtual void control_change(int ctl
, int val
);
517 /// Compose two filters in series
518 template<class F1
, class F2
>
519 class filter_compose
{
521 typedef std::complex<float> cfloat
;
525 float process(float value
) {
526 return f2
.process(f1
.process(value
));
529 cfloat
h_z(const cfloat
&z
) {
530 return f1
.h_z(z
) * f2
.h_z(z
);
533 /// Return the filter's gain at frequency freq
534 /// @param freq Frequency to look up
535 /// @param sr Filter sample rate (used to convert frequency to angular frequency)
536 float freq_gain(float freq
, float sr
)
538 typedef std::complex<double> cfloat
;
539 freq
*= 2.0 * M_PI
/ sr
;
540 cfloat z
= 1.0 / exp(cfloat(0.0, freq
));
542 return std::abs(h_z(z
));
551 /// Compose two filters in parallel
552 template<class F1
, class F2
>
555 typedef std::complex<double> cfloat
;
559 float process(float value
) {
560 return f2
.process(value
) + f1
.process(value
);
563 inline cfloat
h_z(const cfloat
&z
) {
564 return f1
.h_z(z
) + f2
.h_z(z
);
567 /// Return the filter's gain at frequency freq
568 /// @param freq Frequency to look up
569 /// @param sr Filter sample rate (used to convert frequency to angular frequency)
570 float freq_gain(float freq
, float sr
)
572 typedef std::complex<double> cfloat
;
573 freq
*= 2.0 * M_PI
/ sr
;
574 cfloat z
= 1.0 / exp(cfloat(0.0, freq
));
576 return std::abs(h_z(z
));
585 template<typename FilterClass
, typename Metadata
>
586 class filter_module_with_inertia
: public FilterClass
589 typedef filter_module_with_inertia inertia_filter_module
;
591 float *ins
[Metadata::in_count
];
592 float *outs
[Metadata::out_count
];
593 float *params
[Metadata::param_count
];
595 inertia
<exponential_ramp
> inertia_cutoff
, inertia_resonance
, inertia_gain
;
599 filter_module_with_inertia()
600 : inertia_cutoff(exponential_ramp(128), 20)
601 , inertia_resonance(exponential_ramp(128), 20)
602 , inertia_gain(exponential_ramp(128), 1.0)
608 void calculate_filter()
610 float freq
= inertia_cutoff
.get_last();
611 // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
612 // XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
613 float q
= inertia_resonance
.get_last();
614 int mode
= dsp::fastf2i_drm(*params
[Metadata::par_mode
]);
615 // printf("freq = %f q = %f mode = %d\n", freq, q, mode);
617 int inertia
= dsp::fastf2i_drm(*params
[Metadata::par_inertia
]);
618 if (inertia
!= inertia_cutoff
.ramp
.length()) {
619 inertia_cutoff
.ramp
.set_length(inertia
);
620 inertia_resonance
.ramp
.set_length(inertia
);
621 inertia_gain
.ramp
.set_length(inertia
);
624 FilterClass::calculate_filter(freq
, q
, mode
, inertia_gain
.get_last());
627 virtual void params_changed()
634 inertia_cutoff
.step();
635 inertia_resonance
.step();
643 FilterClass::filter_activate();
644 timer
= once_per_n(FilterClass::srate
/ 1000);
649 void set_sample_rate(uint32_t sr
)
651 FilterClass::srate
= sr
;
660 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
661 // printf("sr=%d cutoff=%f res=%f mode=%f\n", FilterClass::srate, *params[Metadata::par_cutoff], *params[Metadata::par_resonance], *params[Metadata::par_mode]);
663 numsamples
+= offset
;
664 while(offset
< numsamples
) {
665 uint32_t numnow
= numsamples
- offset
;
666 // if inertia's inactive, we can calculate the whole buffer at once
667 if (inertia_cutoff
.active() || inertia_resonance
.active() || inertia_gain
.active())
668 numnow
= timer
.get(numnow
);
670 if (outputs_mask
& 1) {
671 ostate
|= FilterClass::process_channel(0, ins
[0] + offset
, outs
[0] + offset
, numnow
, inputs_mask
& 1);
673 if (outputs_mask
& 2) {
674 ostate
|= FilterClass::process_channel(1, ins
[1] + offset
, outs
[1] + offset
, numnow
, inputs_mask
& 2);
677 if (timer
.elapsed()) {
686 /// biquad filter module
687 class filter_audio_module
:
688 public audio_module
<filter_metadata
>,
689 public filter_module_with_inertia
<biquad_filter_module
, filter_metadata
>,
690 public frequency_response_line_graph
693 float old_cutoff
, old_resonance
, old_mode
;
695 filter_audio_module()
699 void params_changed()
701 inertia_cutoff
.set_inertia(*params
[par_cutoff
]);
702 inertia_resonance
.set_inertia(*params
[par_resonance
]);
703 inertia_filter_module::params_changed();
708 inertia_filter_module::activate();
711 void set_sample_rate(uint32_t sr
)
713 inertia_filter_module::set_sample_rate(sr
);
719 inertia_filter_module::deactivate();
722 bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
723 int get_changed_offsets(int generation
, int &subindex_graph
, int &subindex_dot
, int &subindex_gridline
);
726 /// A multitap stereo chorus thing - processing
727 class multichorus_audio_module
: public audio_module
<multichorus_metadata
>, public frequency_response_line_graph
730 float *ins
[in_count
];
731 float *outs
[out_count
];
732 float *params
[param_count
];
734 dsp::multichorus
<float, sine_multi_lfo
<float, 8>, filter_sum
<dsp::biquad_d2
<>, dsp::biquad_d2
<> >, 4096> left
, right
;
740 multichorus_audio_module()
745 void params_changed()
747 // delicious copy-pasta from flanger module - it'd be better to keep it common or something
748 float dry
= *params
[par_dryamount
];
749 float wet
= *params
[par_amount
];
750 float rate
= *params
[par_rate
];
751 float min_delay
= *params
[par_delay
] / 1000.0;
752 float mod_depth
= *params
[par_depth
] / 1000.0;
753 left
.set_dry(dry
); right
.set_dry(dry
);
754 left
.set_wet(wet
); right
.set_wet(wet
);
755 left
.set_rate(rate
); right
.set_rate(rate
);
756 left
.set_min_delay(min_delay
); right
.set_min_delay(min_delay
);
757 left
.set_mod_depth(mod_depth
); right
.set_mod_depth(mod_depth
);
758 int voices
= (int)*params
[par_voices
];
759 left
.lfo
.set_voices(voices
); right
.lfo
.set_voices(voices
);
760 float vphase
= *params
[par_vphase
] * (1.f
/ 360.f
);
761 left
.lfo
.vphase
= right
.lfo
.vphase
= vphase
* (4096 / std::max(voices
- 1, 1));
762 float r_phase
= *params
[par_stereo
] * (1.f
/ 360.f
);
763 if (fabs(r_phase
- last_r_phase
) > 0.0001f
) {
764 right
.lfo
.phase
= left
.lfo
.phase
;
765 right
.lfo
.phase
+= chorus_phase(r_phase
* 4096);
766 last_r_phase
= r_phase
;
768 left
.post
.f1
.set_bp_rbj(*params
[par_freq
], *params
[par_q
], srate
);
769 left
.post
.f2
.set_bp_rbj(*params
[par_freq2
], *params
[par_q
], srate
);
770 right
.post
.f1
.copy_coeffs(left
.post
.f1
);
771 right
.post
.f2
.copy_coeffs(left
.post
.f2
);
773 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
774 left
.process(outs
[0] + offset
, ins
[0] + offset
, numsamples
);
775 right
.process(outs
[1] + offset
, ins
[1] + offset
, numsamples
);
776 return outputs_mask
; // XXXKF allow some delay after input going blank
780 void set_sample_rate(uint32_t sr
);
781 bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
782 float freq_gain(int subindex
, float freq
, float srate
);
783 bool get_dot(int index
, int subindex
, float &x
, float &y
, int &size
, cairo_iface
*context
);
784 bool get_gridline(int index
, int subindex
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
);
787 class compressor_audio_module
: public audio_module
<compressor_metadata
>, public line_graph_iface
{
789 float linSlope
, peak
, detected
, kneeSqrt
, kneeStart
, linKneeStart
, kneeStop
, threshold
, ratio
, knee
, makeup
, compressedKneeStop
, adjKneeStart
;
790 float old_threshold
, old_ratio
, old_knee
, old_makeup
;
795 float *ins
[in_count
];
796 float *outs
[out_count
];
797 float *params
[param_count
];
800 compressor_audio_module();
803 uint32_t process(uint32_t offset
, uint32_t numsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
);
805 inline float output_level(float slope
) {
806 return slope
* output_gain(slope
, false) * makeup
;
809 inline float output_gain(float linSlope
, bool rms
) {
810 if(linSlope
> (rms
? adjKneeStart
: linKneeStart
)) {
811 float slope
= log(linSlope
);
812 if(rms
) slope
*= 0.5f
;
816 if(IS_FAKE_INFINITY(ratio
)) {
820 gain
= (slope
- threshold
) / ratio
+ threshold
;
824 if(knee
> 1.f
&& slope
< kneeStop
) {
825 gain
= hermite_interpolation(slope
, kneeStart
, kneeStop
, kneeStart
, compressedKneeStop
, 1.f
, delta
);
828 return exp(gain
- slope
);
834 void set_sample_rate(uint32_t sr
);
836 virtual bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
837 virtual bool get_dot(int index
, int subindex
, float &x
, float &y
, int &size
, cairo_iface
*context
);
838 virtual bool get_gridline(int index
, int subindex
, float &pos
, bool &vertical
, std::string
&legend
, cairo_iface
*context
);
840 virtual int get_changed_offsets(int generation
, int &subindex_graph
, int &subindex_dot
, int &subindex_gridline
)
844 subindex_gridline
= generation
? INT_MAX
: 0;
846 if (fabs(threshold
-old_threshold
) + fabs(ratio
- old_ratio
) + fabs(knee
- old_knee
) + fabs( makeup
- old_makeup
) > 0.1f
)
848 old_threshold
= threshold
;
855 if (generation
== last_generation
)
857 return last_generation
;
861 /// Filterclavier --- MIDI controlled filter by Hans Baier
862 class filterclavier_audio_module
:
863 public audio_module
<filterclavier_metadata
>,
864 public filter_module_with_inertia
<biquad_filter_module
, filterclavier_metadata
>,
865 public frequency_response_line_graph
867 const float min_gain
;
868 const float max_gain
;
874 filterclavier_audio_module()
881 void params_changed()
883 inertia_filter_module::inertia_cutoff
.set_inertia(
884 note_to_hz(last_note
+ *params
[par_transpose
], *params
[par_detune
]));
886 float min_resonance
= param_props
[par_max_resonance
].min
;
887 inertia_filter_module::inertia_resonance
.set_inertia(
888 (float(last_velocity
) / 127.0)
890 * (*params
[par_max_resonance
] - min_resonance
+ 0.001)
893 adjust_gain_according_to_filter_mode(last_velocity
);
895 inertia_filter_module::calculate_filter();
900 inertia_filter_module::activate();
903 void set_sample_rate(uint32_t sr
)
905 inertia_filter_module::set_sample_rate(sr
);
911 inertia_filter_module::deactivate();
915 virtual void note_on(int note
, int vel
)
919 inertia_filter_module::inertia_cutoff
.set_inertia(
920 note_to_hz(note
+ *params
[par_transpose
], *params
[par_detune
]));
922 float min_resonance
= param_props
[par_max_resonance
].min
;
923 inertia_filter_module::inertia_resonance
.set_inertia(
925 // 0.001: if the difference is equal to zero (which happens
926 // when the max_resonance knom is at minimum position
927 // then the filter gain doesnt seem to snap to zero on most note offs
928 * (*params
[par_max_resonance
] - min_resonance
+ 0.001)
931 adjust_gain_according_to_filter_mode(vel
);
933 inertia_filter_module::calculate_filter();
936 virtual void note_off(int note
, int vel
)
938 if (note
== last_note
) {
939 inertia_filter_module::inertia_resonance
.set_inertia(param_props
[par_max_resonance
].min
);
940 inertia_filter_module::inertia_gain
.set_inertia(min_gain
);
941 inertia_filter_module::calculate_filter();
946 bool get_graph(int index
, int subindex
, float *data
, int points
, cairo_iface
*context
);
949 void adjust_gain_according_to_filter_mode(int velocity
) {
950 int mode
= dsp::fastf2i_drm(*params
[par_mode
]);
952 // for bandpasses: boost gain for velocities > 0
953 if ( (mode_6db_bp
<= mode
) && (mode
<= mode_18db_bp
) ) {
954 // gain for velocity 0: 1.0
955 // gain for velocity 127: 32.0
956 float mode_max_gain
= max_gain
;
957 // max_gain is right for mode_6db_bp
958 if (mode
== mode_12db_bp
)
959 mode_max_gain
/= 6.0;
960 if (mode
== mode_18db_bp
)
961 mode_max_gain
/= 10.5;
963 inertia_filter_module::inertia_gain
.set_now(
964 (float(velocity
) / 127.0) * (mode_max_gain
- min_gain
) + min_gain
);
966 inertia_filter_module::inertia_gain
.set_now(min_gain
);
971 extern std::string
get_builtin_modules_rdf();
975 #include "modules_synths.h"