Ring Modulator: Initial rudimentary implementation
[calf.git] / src / modules_mod.cpp
blob5689acf547e45fecae1675f208d4119685f9fcef
1 /* Calf DSP plugin pack
2 * Modulation effect 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_mod.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 * FLANGER by Krzysztof Foltman
33 **********************************************************************/
35 void flanger_audio_module::activate() {
36 left.reset();
37 right.reset();
38 last_r_phase = *params[par_stereo] * (1.f / 360.f);
39 left.reset_phase(0.f);
40 right.reset_phase(last_r_phase);
41 is_active = true;
44 void flanger_audio_module::set_sample_rate(uint32_t sr) {
45 srate = sr;
46 left.setup(sr);
47 right.setup(sr);
50 void flanger_audio_module::deactivate() {
51 is_active = false;
54 void flanger_audio_module::params_changed()
56 float dry = *params[par_dryamount];
57 float wet = *params[par_amount];
58 float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
59 float min_delay = *params[par_delay] / 1000.0;
60 float mod_depth = *params[par_depth] / 1000.0;
61 float fb = *params[par_fb];
62 left.set_dry(dry); right.set_dry(dry);
63 left.set_wet(wet); right.set_wet(wet);
64 left.set_rate(rate); right.set_rate(rate);
65 left.set_min_delay(min_delay); right.set_min_delay(min_delay);
66 left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
67 left.set_fb(fb); right.set_fb(fb);
68 float r_phase = *params[par_stereo] * (1.f / 360.f);
69 clear_reset = false;
70 if (*params[par_reset] >= 0.5) {
71 clear_reset = true;
72 left.reset_phase(0.f);
73 right.reset_phase(r_phase);
74 } else {
75 if (fabs(r_phase - last_r_phase) > 0.0001f) {
76 right.phase = left.phase;
77 right.inc_phase(r_phase);
78 last_r_phase = r_phase;
83 void flanger_audio_module::params_reset()
85 if (clear_reset) {
86 *params[par_reset] = 0.f;
87 clear_reset = false;
90 bool flanger_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
92 if (!is_active or !phase or subindex >= 2)
93 return false;
94 set_channel_color(context, subindex);
95 return ::get_graph(*this, subindex, data, points, 32, 0);
97 bool flanger_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
99 if (!is_active or phase)
100 return false;
101 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 32, 0);
103 bool flanger_audio_module::get_layers(int index, int generation, unsigned int &layers) const
105 layers = LG_REALTIME_GRAPH | (generation ? 0 : LG_CACHE_GRID);
106 return true;
108 float flanger_audio_module::freq_gain(int subindex, float freq) const
110 return (subindex ? right : left).freq_gain(freq, srate);
114 /**********************************************************************
115 * PHASER by Krzysztof Foltman
116 **********************************************************************/
119 phaser_audio_module::phaser_audio_module()
120 : left(MaxStages, x1vals[0], y1vals[0])
121 , right(MaxStages, x1vals[1], y1vals[1])
123 is_active = false;
126 void phaser_audio_module::set_sample_rate(uint32_t sr)
128 srate = sr;
129 left.setup(sr);
130 right.setup(sr);
133 void phaser_audio_module::activate()
135 is_active = true;
136 left.reset();
137 right.reset();
138 last_r_phase = *params[par_stereo] * (1.f / 360.f);
139 left.reset_phase(0.f);
140 right.reset_phase(last_r_phase);
143 void phaser_audio_module::deactivate()
145 is_active = false;
148 void phaser_audio_module::params_changed()
150 float dry = *params[par_dryamount];
151 float wet = *params[par_amount];
152 float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
153 float base_frq = *params[par_freq];
154 float mod_depth = *params[par_depth];
155 float fb = *params[par_fb];
156 int stages = (int)*params[par_stages];
157 left.set_dry(dry); right.set_dry(dry);
158 left.set_wet(wet); right.set_wet(wet);
159 left.set_rate(rate); right.set_rate(rate);
160 left.set_base_frq(base_frq); right.set_base_frq(base_frq);
161 left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
162 left.set_fb(fb); right.set_fb(fb);
163 left.set_stages(stages); right.set_stages(stages);
164 float r_phase = *params[par_stereo] * (1.f / 360.f);
165 clear_reset = false;
166 if (*params[par_reset] >= 0.5) {
167 clear_reset = true;
168 left.reset_phase(0.f);
169 right.reset_phase(r_phase);
170 } else {
171 if (fabs(r_phase - last_r_phase) > 0.0001f) {
172 right.phase = left.phase;
173 right.inc_phase(r_phase);
174 last_r_phase = r_phase;
179 void phaser_audio_module::params_reset()
181 if (clear_reset) {
182 *params[par_reset] = 0.f;
183 clear_reset = false;
186 bool phaser_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
188 if (!is_active or phase)
189 return false;
190 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 32, 0);
192 bool phaser_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
194 if (!is_active or subindex >= 2 or !phase)
195 return false;
196 set_channel_color(context, subindex);
197 return ::get_graph(*this, subindex, data, points, 32, 0);
199 bool phaser_audio_module::get_layers(int index, int generation, unsigned int &layers) const
201 layers = LG_REALTIME_GRAPH | (generation ? 0 : LG_CACHE_GRID);
202 return true;
205 float phaser_audio_module::freq_gain(int subindex, float freq) const
207 return (subindex ? right : left).freq_gain(freq, srate);
211 /**********************************************************************
212 * ROTARY SPEAKER by Krzysztof Foltman
213 **********************************************************************/
215 rotary_speaker_audio_module::rotary_speaker_audio_module()
217 mwhl_value = hold_value = 0.f;
218 phase_h = phase_l = 0.f;
219 aspeed_l = 1.f;
220 aspeed_h = 1.f;
221 dspeed = 0.f;
224 void rotary_speaker_audio_module::set_sample_rate(uint32_t sr)
226 srate = sr;
227 setup();
230 void rotary_speaker_audio_module::setup()
232 crossover1l.set_lp_rbj(800.f, 0.7, (float)srate);
233 crossover1r.set_lp_rbj(800.f, 0.7, (float)srate);
234 crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
235 crossover2r.set_hp_rbj(800.f, 0.7, (float)srate);
238 void rotary_speaker_audio_module::activate()
240 phase_h = phase_l = 0.f;
241 maspeed_h = maspeed_l = 0.f;
242 setup();
245 void rotary_speaker_audio_module::deactivate()
249 void rotary_speaker_audio_module::control_change(int /*channel*/, int ctl, int val)
251 if (vibrato_mode == 3 && ctl == 64)
253 hold_value = val / 127.f;
254 set_vibrato();
255 return;
257 if (vibrato_mode == 4 && ctl == 1)
259 mwhl_value = val / 127.f;
260 set_vibrato();
261 return;
265 void rotary_speaker_audio_module::params_changed()
267 set_vibrato();
270 void rotary_speaker_audio_module::set_vibrato()
272 vibrato_mode = fastf2i_drm(*params[par_speed]);
273 // manual vibrato - do not recalculate speeds as they're not used anyway
274 if (vibrato_mode == 5)
275 return;
276 if (!vibrato_mode)
277 dspeed = -1;
278 else {
279 float speed = vibrato_mode - 1;
280 if (vibrato_mode == 3)
281 speed = hold_value;
282 if (vibrato_mode == 4)
283 speed = mwhl_value;
284 dspeed = (speed < 0.5f) ? 0 : 1;
286 update_speed();
289 /// Convert RPM speed to delta-phase
290 uint32_t rotary_speaker_audio_module::rpm2dphase(float rpm)
292 return (uint32_t)((rpm / (60.0 * srate)) * (1 << 30)) << 2;
295 /// Set delta-phase variables based on current calculated (and interpolated) RPM speed
296 void rotary_speaker_audio_module::update_speed()
298 float speed_h = aspeed_h >= 0 ? (48 + (400-48) * aspeed_h) : (48 * (1 + aspeed_h));
299 float speed_l = aspeed_l >= 0 ? 40 + (342-40) * aspeed_l : (40 * (1 + aspeed_l));
300 dphase_h = rpm2dphase(speed_h);
301 dphase_l = rpm2dphase(speed_l);
304 void rotary_speaker_audio_module::update_speed_manual(float delta)
306 float ts = *params[par_treblespeed];
307 float bs = *params[par_bassspeed];
308 incr_towards(maspeed_h, ts, delta * 200, delta * 200);
309 incr_towards(maspeed_l, bs, delta * 200, delta * 200);
310 dphase_h = rpm2dphase(maspeed_h);
311 dphase_l = rpm2dphase(maspeed_l);
314 /// map a ramp [int] to a sinusoid-like function [0, 65536]
315 static inline int pseudo_sine_scl(int counter)
317 // premature optimization is a root of all evil; it can be done with integers only - but later :)
318 double v = counter * (1.0 / (65536.0 * 32768.0));
319 return (int) (32768 + 32768 * (v - v*v*v) * (1.0 / 0.3849));
322 /// Increase or decrease aspeed towards raspeed, with required negative and positive rate
323 inline bool rotary_speaker_audio_module::incr_towards(float &aspeed, float raspeed, float delta_decc, float delta_acc)
325 if (aspeed < raspeed) {
326 aspeed = std::min(raspeed, aspeed + delta_acc);
327 return true;
329 else if (aspeed > raspeed)
331 aspeed = std::max(raspeed, aspeed - delta_decc);
332 return true;
334 return false;
337 uint32_t rotary_speaker_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask)
339 if (true)
341 crossover2l.set_bp_rbj(2000.f, 0.7, (float)srate);
342 crossover2r.copy_coeffs(crossover2l);
343 damper1l.set_bp_rbj(1000.f*pow(4.0, *params[par_test]), 0.7, (float)srate);
344 damper1r.copy_coeffs(damper1l);
346 else
348 crossover2l.set_hp_rbj(800.f, 0.7, (float)srate);
349 crossover2r.copy_coeffs(crossover2l);
351 int shift = (int)(300000 * (*params[par_shift])), pdelta = (int)(300000 * (*params[par_spacing]));
352 int md = (int)(100 * (*params[par_moddepth]));
353 float mix = 0.5 * (1.0 - *params[par_micdistance]);
354 float mix2 = *params[par_reflection];
355 float mix3 = mix2 * mix2;
356 double am_depth = *params[par_am_depth];
357 for (unsigned int i = 0; i < nsamples; i++) {
358 float in_l = ins[0][i + offset], in_r = ins[1][i + offset];
359 double in_mono = atan(0.5f * (in_l + in_r));
361 int xl = pseudo_sine_scl(phase_l), yl = pseudo_sine_scl(phase_l + 0x40000000);
362 int xh = pseudo_sine_scl(phase_h), yh = pseudo_sine_scl(phase_h + 0x40000000);
363 // printf("%d %d %d\n", shift, pdelta, shift + pdelta + 20 * xl);
364 meter_l = xl;
365 meter_h = xh;
366 // 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);
367 // 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);
368 float fm_hi_l = 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);
369 float fm_hi_r = 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);
370 float out_hi_l = lerp(in_mono, (double)damper1l.process(fm_hi_l), lerp(0.5, xh * 1.0 / 65536.0, am_depth));
371 float out_hi_r = lerp(in_mono, (double)damper1r.process(fm_hi_r), lerp(0.5, yh * 1.0 / 65536.0, am_depth));
373 float out_lo_l = lerp(in_mono, (double)delay.get_interp_1616(shift + (md * xl >> 2)), lerp(0.5, yl * 1.0 / 65536.0, am_depth)); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl);
374 float out_lo_r = lerp(in_mono, (double)delay.get_interp_1616(shift + (md * yl >> 2)), lerp(0.5, xl * 1.0 / 65536.0, am_depth)); // + delay.get_interp_1616(shift + md * 65536 + pdelta - md * yl);
376 out_hi_l = crossover2l.process(out_hi_l); // sanitize(out_hi_l);
377 out_hi_r = crossover2r.process(out_hi_r); // sanitize(out_hi_r);
378 out_lo_l = crossover1l.process(out_lo_l); // sanitize(out_lo_l);
379 out_lo_r = crossover1r.process(out_lo_r); // sanitize(out_lo_r);
381 float out_l = out_hi_l + out_lo_l;
382 float out_r = out_hi_r + out_lo_r;
384 float mic_l = out_l + mix * (out_r - out_l);
385 float mic_r = out_r + mix * (out_l - out_r);
387 outs[0][i + offset] = mic_l;
388 outs[1][i + offset] = mic_r;
389 delay.put(in_mono);
390 phase_l += dphase_l;
391 phase_h += dphase_h;
393 crossover1l.sanitize();
394 crossover1r.sanitize();
395 crossover2l.sanitize();
396 crossover2r.sanitize();
397 damper1l.sanitize();
398 damper1r.sanitize();
399 float delta = nsamples * 1.0 / srate;
400 if (vibrato_mode == 5)
401 update_speed_manual(delta);
402 else
404 bool u1 = incr_towards(aspeed_l, dspeed, delta * 0.2, delta * 0.14);
405 bool u2 = incr_towards(aspeed_h, dspeed, delta, delta * 0.5);
406 if (u1 || u2)
407 set_vibrato();
409 if(params[par_meter_l] != NULL) {
410 *params[par_meter_l] = (float)meter_l / 65536.0;
412 if(params[par_meter_h] != NULL) {
413 *params[par_meter_h] = (float)meter_h / 65536.0;
415 return outputs_mask;
418 /**********************************************************************
419 * MULTI CHORUS by Krzysztof Foltman
420 **********************************************************************/
422 multichorus_audio_module::multichorus_audio_module()
424 is_active = false;
425 last_r_phase = -1;
426 freq_old = freq2_old = q_old = -1;
427 redraw_graph = true;
428 redraw_sine = true;
431 void multichorus_audio_module::activate()
433 is_active = true;
434 params_changed();
437 void multichorus_audio_module::deactivate()
439 is_active = false;
442 void multichorus_audio_module::set_sample_rate(uint32_t sr) {
443 srate = sr;
444 last_r_phase = -1;
445 left.setup(sr);
446 right.setup(sr);
449 void multichorus_audio_module::params_changed()
451 // delicious copy-pasta from flanger module - it'd be better to keep it common or something
452 float dry = *params[par_dryamount];
453 float wet = *params[par_amount];
454 float rate = *params[par_rate];
455 float min_delay = *params[par_delay] / 1000.0;
456 float mod_depth = *params[par_depth] / 1000.0;
457 float overlap = *params[par_overlap];
458 left.set_dry(dry); right.set_dry(dry);
459 left.set_wet(wet); right.set_wet(wet);
460 left.set_rate(rate); right.set_rate(rate);
461 left.set_min_delay(min_delay); right.set_min_delay(min_delay);
462 left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
463 int voices = (int)*params[par_voices];
464 left.lfo.set_voices(voices); right.lfo.set_voices(voices);
465 left.lfo.set_overlap(overlap);right.lfo.set_overlap(overlap);
466 float vphase = *params[par_vphase] * (1.f / 360.f);
467 left.lfo.vphase = right.lfo.vphase = vphase * (4096 / std::max(voices - 1, 1));
468 float r_phase = *params[par_stereo] * (1.f / 360.f);
469 if (fabs(r_phase - last_r_phase) > 0.0001f) {
470 right.lfo.phase = left.lfo.phase;
471 right.lfo.phase += chorus_phase(r_phase * 4096);
472 last_r_phase = r_phase;
474 if (*params[par_freq] != freq_old or *params[par_freq2] != freq2_old or *params[par_q] != q_old) {
475 left.post.f1.set_bp_rbj(*params[par_freq], *params[par_q], srate);
476 left.post.f2.set_bp_rbj(*params[par_freq2], *params[par_q], srate);
477 right.post.f1.copy_coeffs(left.post.f1);
478 right.post.f2.copy_coeffs(left.post.f2);
479 freq_old = *params[par_freq];
480 freq2_old = *params[par_freq2];
481 q_old = *params[par_q];
482 redraw_graph = true;
484 redraw_sine = true;
487 uint32_t multichorus_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
489 left.process(outs[0] + offset, ins[0] + offset, numsamples);
490 right.process(outs[1] + offset, ins[1] + offset, numsamples);
491 return outputs_mask; // XXXKF allow some delay after input going blank
494 bool multichorus_audio_module::get_layers(int index, int generation, unsigned int &layers) const
496 layers = 0;
497 // frequency response
498 if (index == par_delay) {
499 layers = (generation ? 0 : LG_CACHE_GRID) | (redraw_graph ? LG_CACHE_GRAPH : 0) | LG_REALTIME_GRAPH;
501 // sine display
502 if (index == par_rate) {
503 layers = LG_REALTIME_DOT | (redraw_sine ? LG_CACHE_GRAPH : 0);
505 // dot display
506 if (index == par_depth)
507 layers = LG_REALTIME_DOT;
508 return true;
511 bool multichorus_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
513 if (!is_active)
514 return false;
516 // the filter graph (cached) in frequency response
517 if (index == par_delay and subindex == 2 and !phase) {
518 context->set_source_rgba(0.15, 0.2, 0.0, 0.8);
519 redraw_graph = false;
520 return ::get_graph(*this, subindex, data, points, 64, 0.5);
522 // the realtime graphs in frequency response
523 if (index == par_delay and subindex < 2 and phase) {
524 set_channel_color(context, subindex);
525 context->set_line_width(1);
526 return ::get_graph(*this, subindex, data, points, 64, 0.5);
529 // the sine curves in modulation display
530 if (index == par_rate && subindex < (int)*params[par_voices] and !phase) {
531 const sine_multi_lfo<float, 8> &lfo = left.lfo;
532 for (int i = 0; i < points; i++) {
533 float _phase = i * 2 * M_PI / points;
534 // original -65536 to 65535 value
535 float orig = subindex * lfo.voice_offset + ((lfo.voice_depth >> (30-13)) * 65536.0 * (0.95 * sin(_phase) + 1)/ 8192.0) - 65536;
536 // scale to -1..1
537 data[i] = orig / 65536.0;
539 return true;
541 redraw_sine = false;
542 return false;
545 bool multichorus_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
547 int voice = subindex >> 1;
548 int nvoices = (int)*params[par_voices];
549 if (!is_active
550 or !phase
551 or (index != par_rate and index != par_depth)
552 or voice >= nvoices)
553 return false;
555 float unit = (1 - *params[par_overlap]);
556 float scw = 1 + unit * (nvoices - 1);
557 const sine_multi_lfo<float, 8> &lfo = (subindex & 1 ? right : left).lfo;
559 // the display with the sine curves
560 if (index == par_rate) {
561 x = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
562 y = 0.95 * sin(x * 2 * M_PI);
563 y = (voice * unit + (y + 1) / 2) / scw * 2 - 1;
565 // the tiny dot display
566 if (index == par_depth) {
567 double ph = (double)(lfo.phase + lfo.vphase * voice) / 4096.0;
568 x = 0.5 + 0.5 * sin(ph * 2 * M_PI);
569 y = subindex & 1 ? -0.5 : 0.5;
570 x = (voice * unit + x) / scw;
572 return true;
575 bool multichorus_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
577 if (index == par_delay and !phase and is_active)
578 return get_freq_gridline(subindex, pos, vertical, legend, context, true, 64, 0.5);
579 return false;
582 float multichorus_audio_module::freq_gain(int subindex, float freq) const
584 if (subindex == 2)
585 return *params[par_amount] * left.post.freq_gain(freq, srate);
586 return (subindex ? right : left).freq_gain(freq, srate);
589 /**********************************************************************
590 * PULSATOR by Markus Schmidt
591 **********************************************************************/
593 pulsator_audio_module::pulsator_audio_module()
595 is_active = false;
596 srate = 0;
597 mode_old = -1;
598 amount_old = -1;
599 offset_old = -1;
602 void pulsator_audio_module::activate()
604 is_active = true;
605 lfoL.activate();
606 lfoR.activate();
607 params_changed();
609 void pulsator_audio_module::deactivate()
611 is_active = false;
612 lfoL.deactivate();
613 lfoR.deactivate();
616 void pulsator_audio_module::params_changed()
618 lfoL.set_params(*params[param_freq], *params[param_mode], 0.f, srate, *params[param_amount]);
619 lfoR.set_params(*params[param_freq], *params[param_mode], *params[param_offset], srate, *params[param_amount]);
620 clear_reset = false;
621 if (*params[param_reset] >= 0.5) {
622 clear_reset = true;
623 lfoL.set_phase(0.f);
624 lfoR.set_phase(0.f);
626 if (*params[param_mode] != mode_old
627 or *params[param_amount] != amount_old
628 or *params[param_offset] != offset_old
629 or clear_reset) {
630 mode_old = *params[param_mode];
631 amount_old = *params[param_amount];
632 offset_old = *params[param_offset];
633 redraw_graph = true;
637 void pulsator_audio_module::set_sample_rate(uint32_t sr)
639 srate = sr;
640 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
641 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
642 meters.init(params, meter, clip, 4, sr);
645 uint32_t pulsator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
647 bool bypass = *params[param_bypass] > 0.5f;
648 uint32_t samples = numsamples + offset;
649 if(bypass) {
650 // everything bypassed
651 while(offset < samples) {
652 outs[0][offset] = ins[0][offset];
653 outs[1][offset] = ins[1][offset];
654 ++offset;
656 // LFO's should go on
657 lfoL.advance(numsamples);
658 lfoR.advance(numsamples);
660 float values[] = {0, 0, 0, 0};
661 meters.process(values);
662 } else {
663 // process
664 while(offset < samples) {
665 // cycle through samples
666 float outL = 0.f;
667 float outR = 0.f;
668 float inL = ins[0][offset];
669 float inR = ins[1][offset];
670 // in level
671 inR *= *params[param_level_in];
672 inL *= *params[param_level_in];
674 if(*params[param_mono] > 0.5) {
675 inL = (inL + inR) * 0.5;
676 inR = inL;
678 float procL = inL;
679 float procR = inR;
681 procL *= (lfoL.get_value() * 0.5 + *params[param_amount] / 2);
682 procR *= (lfoR.get_value() * 0.5 + *params[param_amount] / 2);
684 outL = procL + inL * (1 - *params[param_amount]);
685 outR = procR + inR * (1 - *params[param_amount]);
687 outL *= *params[param_level_out];
688 outR *= *params[param_level_out];
690 // send to output
691 outs[0][offset] = outL;
692 outs[1][offset] = outR;
694 // next sample
695 ++offset;
697 // advance lfo's
698 lfoL.advance(1);
699 lfoR.advance(1);
701 float values[] = {inL, inR, outL, outR};
702 meters.process(values);
704 } // cycle trough samples
706 meters.fall(numsamples);
707 return outputs_mask;
710 bool pulsator_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
712 if (!is_active or phase or subindex > 1) {
713 redraw_graph = false;
714 return false;
716 set_channel_color(context, subindex);
717 return (subindex ? lfoR : lfoL).get_graph(data, points, context, mode);
720 bool pulsator_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
722 if (!is_active or !phase or subindex > 1)
723 return false;
724 set_channel_color(context, subindex);
725 return (subindex ? lfoR : lfoL).get_dot(x, y, size, context);
728 bool pulsator_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
730 if (phase or subindex)
731 return false;
732 pos = 0;
733 vertical = false;
734 return true;
736 bool pulsator_audio_module::get_layers(int index, int generation, unsigned int &layers) const
738 layers = LG_REALTIME_DOT | (generation ? 0 : LG_CACHE_GRID) | ((redraw_graph || !generation) ? LG_CACHE_GRAPH : 0);
739 return true;
743 /**********************************************************************
744 * RING MODULATOR by Markus Schmidt
745 **********************************************************************/
747 ringmodulator_audio_module::ringmodulator_audio_module()
749 is_active = false;
750 srate = 0;
753 void ringmodulator_audio_module::activate()
755 is_active = true;
756 lfo1.activate();
757 lfo2.activate();
758 modL.activate();
759 modR.activate();
760 params_changed();
762 void ringmodulator_audio_module::deactivate()
764 is_active = false;
765 lfo1.deactivate();
766 lfo2.deactivate();
767 modL.deactivate();
768 modR.deactivate();
771 void ringmodulator_audio_module::params_changed()
773 lfo1.set_params(*params[param_lfo1_freq],
774 *params[param_lfo1_mode],
776 srate,
777 *params[param_lfo1_amount]);
779 lfo2.set_params(*params[param_lfo2_freq],
780 *params[param_lfo2_mode],
782 srate,
783 *params[param_lfo2_amount]);
785 modL.set_params(*params[param_mod_freq] * pow(pow(2, 1.0 / 1200.0), *params[param_mod_detune] / 2),
786 *params[param_mod_mode],
788 srate,
789 *params[param_mod_amount]);
791 modR.set_params(*params[param_mod_freq] * pow(pow(2, 1.0 / 1200.0), *params[param_mod_detune] / -2),
792 *params[param_mod_mode],
793 *params[param_mod_phase],
794 srate,
795 *params[param_mod_amount]);
797 clear_reset = false;
799 if (*params[param_lfo1_reset] >= 0.5) {
800 clear_reset = true;
801 lfo1.set_phase(0.f);
803 if (*params[param_lfo2_reset] >= 0.5) {
804 clear_reset = true;
805 lfo2.set_phase(0.f);
808 //redraw_graph = true;
811 void ringmodulator_audio_module::set_sample_rate(uint32_t sr)
813 srate = sr;
814 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR};
815 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR};
816 meters.init(params, meter, clip, 4, sr);
819 uint32_t ringmodulator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
821 bool bypass = *params[param_bypass] > 0.5f;
822 uint32_t samples = numsamples + offset;
823 if(bypass) {
824 // everything bypassed
825 while(offset < samples) {
826 outs[0][offset] = ins[0][offset];
827 outs[1][offset] = ins[1][offset];
828 ++offset;
830 // LFO's should go on
831 lfo1.advance(numsamples);
832 lfo1.advance(numsamples);
833 modL.advance(numsamples);
834 modR.advance(numsamples);
836 float values[] = {0, 0, 0, 0};
837 meters.process(values);
838 } else {
839 // process
840 while(offset < samples) {
841 // cycle through samples
842 float outL = 0.f;
843 float outR = 0.f;
844 float inL = ins[0][offset];
845 float inR = ins[1][offset];
847 // in level
848 inR *= *params[param_level_in];
849 inL *= *params[param_level_in];
851 // modulator
852 float modulL = modL.get_value();
853 float modulR = modR.get_value();
855 float procL = inL * modulL;
856 float procR = inR * modulR;
858 //procL *= (lfo1.get_value() * 0.5 + *params[param_amount] / 2);
859 //procR *= (lfo2.get_value() * 0.5 + *params[param_amount] / 2);
861 outL = procL + inL * (1 - *params[param_mod_amount]);
862 outR = procR + inR * (1 - *params[param_mod_amount]);
864 outL *= *params[param_level_out];
865 outR *= *params[param_level_out];
867 // send to output
868 outs[0][offset] = outL;
869 outs[1][offset] = outR;
871 // next sample
872 ++offset;
874 // advance lfo's
875 lfo1.advance(1);
876 lfo2.advance(1);
877 modL.advance(1);
878 modR.advance(1);
880 float values[] = {inL, inR, outL, outR};
881 meters.process(values);
883 } // cycle trough samples
885 meters.fall(numsamples);
886 return outputs_mask;
889 bool ringmodulator_audio_module::get_graph(int index, int subindex, int phase, float *data, int points, cairo_iface *context, int *mode) const
891 if (!is_active or phase or subindex > 1) {
892 redraw_graph = false;
893 return false;
895 set_channel_color(context, subindex);
896 return (subindex ? lfo2 : lfo1).get_graph(data, points, context, mode);
899 bool ringmodulator_audio_module::get_dot(int index, int subindex, int phase, float &x, float &y, int &size, cairo_iface *context) const
901 if (!is_active or !phase or subindex > 1)
902 return false;
903 set_channel_color(context, subindex);
904 return (subindex ? lfo2 : lfo1).get_dot(x, y, size, context);
907 bool ringmodulator_audio_module::get_gridline(int index, int subindex, int phase, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
909 if (phase or subindex)
910 return false;
911 pos = 0;
912 vertical = false;
913 return true;
915 bool ringmodulator_audio_module::get_layers(int index, int generation, unsigned int &layers) const
917 layers = LG_REALTIME_DOT | (generation ? 0 : LG_CACHE_GRID) | ((redraw_graph || !generation) ? LG_CACHE_GRAPH : 0);
918 return true;