Merge branch 'master' of https://github.com/calf-studio-gear/calf
[calf.git] / src / modules_delay.cpp
blob3d3a611f2beacbe19e0c16c22ddf0023292901c0
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
22 #include <limits.h>
23 #include <memory.h>
24 #include <math.h>
25 #include <calf/giface.h>
26 #include <calf/modules_delay.h>
27 #include <calf/modules_dev.h>
28 #include <sys/time.h>
30 using namespace dsp;
31 using namespace calf_plugins;
33 #define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
35 /**********************************************************************
36 * REVERB by Krzysztof Foltman
37 **********************************************************************/
39 void reverb_audio_module::activate()
41 reverb.reset();
44 void reverb_audio_module::deactivate()
48 void reverb_audio_module::set_sample_rate(uint32_t sr)
50 srate = sr;
51 reverb.setup(sr);
52 amount.set_sample_rate(sr);
53 int meter[] = {par_meter_wet, par_meter_out};
54 int clip[] = {-1, par_clip};
55 meters.init(params, meter, clip, 2, srate);
58 void reverb_audio_module::params_changed()
60 reverb.set_type_and_diffusion(fastf2i_drm(*params[par_roomsize]), *params[par_diffusion]);
61 reverb.set_time(*params[par_decay]);
62 reverb.set_cutoff(*params[par_hfdamp]);
63 amount.set_inertia(*params[par_amount]);
64 dryamount.set_inertia(*params[par_dry]);
65 left_lo.set_lp(dsp::clip(*params[par_treblecut], 20.f, (float)(srate * 0.49f)), srate);
66 left_hi.set_hp(dsp::clip(*params[par_basscut], 20.f, (float)(srate * 0.49f)), srate);
67 right_lo.copy_coeffs(left_lo);
68 right_hi.copy_coeffs(left_hi);
69 predelay_amt = (int) (srate * (*params[par_predelay]) * (1.0f / 1000.0f) + 1);
72 uint32_t reverb_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
74 numsamples += offset;
75 clip -= std::min(clip, numsamples);
76 for (uint32_t i = offset; i < numsamples; i++) {
77 float dry = dryamount.get();
78 float wet = amount.get();
79 stereo_sample<float> s(ins[0][i], ins[1][i]);
80 stereo_sample<float> s2 = pre_delay.process(s, predelay_amt);
82 float rl = s2.left, rr = s2.right;
83 rl = left_lo.process(left_hi.process(rl));
84 rr = right_lo.process(right_hi.process(rr));
85 reverb.process(rl, rr);
86 outs[0][i] = dry*s.left + wet*rl;
87 outs[1][i] = dry*s.right + wet*rr;
88 meter_wet = std::max(fabs(wet*rl), fabs(wet*rr));
89 meter_out = std::max(fabs(outs[0][i]), fabs(outs[1][i]));
90 if(outs[0][i] > 1.f or outs[1][i] > 1.f) {
91 clip = srate >> 3;
94 meters.fall(numsamples);
95 reverb.extra_sanitize();
96 left_lo.sanitize();
97 left_hi.sanitize();
98 right_lo.sanitize();
99 right_hi.sanitize();
100 float values[] = {meter_wet, meter_out};
101 meters.process(values);
102 return outputs_mask;
105 /**********************************************************************
106 * VINTAGE DELAY by Krzysztof Foltman
107 **********************************************************************/
109 vintage_delay_audio_module::vintage_delay_audio_module()
111 old_medium = -1;
112 for (int i = 0; i < MAX_DELAY; i++) {
113 buffers[0][i] = 0.f;
114 buffers[1][i] = 0.f;
116 _tap_avg = 0;
117 _tap_last = 0;
120 void vintage_delay_audio_module::params_changed()
122 if (*params[par_sync] > 0.5f)
123 *params[par_bpm] = *params[par_bpm_host];
124 float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]);
125 deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]);
126 deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]);
127 int deltime_fb = deltime_l + deltime_r;
128 float fb = *params[par_feedback];
129 dry.set_inertia(*params[par_dryamount]);
130 mixmode = dsp::fastf2i_drm(*params[par_mixmode]);
131 medium = dsp::fastf2i_drm(*params[par_medium]);
132 switch(mixmode)
134 case MIXMODE_STEREO:
135 fb_left.set_inertia(fb);
136 fb_right.set_inertia(pow(fb, *params[par_time_r] / *params[par_time_l]));
137 amt_left.set_inertia(*params[par_amount]);
138 amt_right.set_inertia(*params[par_amount]);
139 break;
140 case MIXMODE_PINGPONG:
141 fb_left.set_inertia(fb);
142 fb_right.set_inertia(fb);
143 amt_left.set_inertia(*params[par_amount]);
144 amt_right.set_inertia(*params[par_amount]);
145 break;
146 case MIXMODE_LR:
147 fb_left.set_inertia(fb);
148 fb_right.set_inertia(fb);
149 amt_left.set_inertia(*params[par_amount]); // L is straight 'amount'
150 amt_right.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_r / deltime_fb)); // R is amount with feedback based dampening as if it ran through R/FB*100% of delay line's dampening
151 // deltime_l <<< deltime_r -> pow() = fb -> full delay line worth of dampening
152 // deltime_l >>> deltime_r -> pow() = 1 -> no dampening
153 break;
154 case MIXMODE_RL:
155 fb_left.set_inertia(fb);
156 fb_right.set_inertia(fb);
157 amt_left.set_inertia(*params[par_amount] * pow(fb, 1.0 * deltime_l / deltime_fb));
158 amt_right.set_inertia(*params[par_amount]);
159 break;
161 chmix.set_inertia((1 - *params[par_width]) * 0.5);
162 if (medium != old_medium)
163 calc_filters();
166 void vintage_delay_audio_module::activate()
168 bufptr = 0;
169 age = 0;
172 void vintage_delay_audio_module::deactivate()
176 void vintage_delay_audio_module::set_sample_rate(uint32_t sr)
178 srate = sr;
179 old_medium = -1;
180 amt_left.set_sample_rate(sr); amt_right.set_sample_rate(sr);
181 fb_left.set_sample_rate(sr); fb_right.set_sample_rate(sr);
184 void vintage_delay_audio_module::calc_filters()
186 // parameters are heavily influenced by gordonjcp and his tape delay unit
187 // although, don't blame him if it sounds bad - I've messed with them too :)
188 biquad_left[0].set_lp_rbj(6000, 0.707, srate);
189 biquad_left[1].set_bp_rbj(4500, 0.250, srate);
190 biquad_right[0].copy_coeffs(biquad_left[0]);
191 biquad_right[1].copy_coeffs(biquad_left[1]);
194 /// Single delay line with feedback at the same tap
195 static inline void delayline_impl(int age, int deltime, float dry_value, const float &delayed_value, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb)
197 // if the buffer hasn't been cleared yet (after activation), pretend we've read zeros
198 if (age <= deltime) {
199 out = 0;
200 del = dry_value;
201 amt.step();
202 fb.step();
204 else
206 float delayed = delayed_value; // avoid dereferencing the pointer in 'then' branch of the if()
207 dsp::sanitize(delayed);
208 out = delayed * amt.get();
209 del = dry_value + delayed * fb.get();
213 /// Single delay line with tap output
214 static inline void delayline2_impl(int age, int deltime, float dry_value, const float &delayed_value, const float &delayed_value_for_fb, float &out, float &del, gain_smoothing &amt, gain_smoothing &fb)
216 if (age <= deltime) {
217 out = 0;
218 del = dry_value;
219 amt.step();
220 fb.step();
222 else
224 out = delayed_value * amt.get();
225 del = dry_value + delayed_value_for_fb * fb.get();
226 dsp::sanitize(out);
227 dsp::sanitize(del);
231 static inline void delay_mix(float dry_left, float dry_right, float &out_left, float &out_right, float dry, float chmix)
233 float tmp_left = lerp(out_left, out_right, chmix);
234 float tmp_right = lerp(out_right, out_left, chmix);
235 out_left = dry_left * dry + tmp_left;
236 out_right = dry_right * dry + tmp_right;
239 uint32_t vintage_delay_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
241 uint32_t ostate = 3; // XXXKF optimize!
242 uint32_t end = offset + numsamples;
243 int orig_bufptr = bufptr;
244 float out_left, out_right, del_left, del_right;
246 switch(mixmode)
248 case MIXMODE_STEREO:
249 case MIXMODE_PINGPONG:
251 int v = mixmode == MIXMODE_PINGPONG ? 1 : 0;
252 for(uint32_t i = offset; i < end; i++)
254 delayline_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l) & ADDR_MASK], out_left, del_left, amt_left, fb_left);
255 delayline_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK], out_right, del_right, amt_right, fb_right);
256 delay_mix(ins[0][i], ins[1][i], out_left, out_right, dry.get(), chmix.get());
258 age++;
259 outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
260 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
263 break;
265 case MIXMODE_LR:
266 case MIXMODE_RL:
268 int v = mixmode == MIXMODE_RL ? 1 : 0;
269 int deltime_fb = deltime_l + deltime_r;
270 int deltime_l_corr = mixmode == MIXMODE_RL ? deltime_fb : deltime_l;
271 int deltime_r_corr = mixmode == MIXMODE_LR ? deltime_fb : deltime_r;
273 for(uint32_t i = offset; i < end; i++)
275 delayline2_impl(age, deltime_l, ins[0][i], buffers[v][(bufptr - deltime_l_corr) & ADDR_MASK], buffers[v][(bufptr - deltime_fb) & ADDR_MASK], out_left, del_left, amt_left, fb_left);
276 delayline2_impl(age, deltime_r, ins[1][i], buffers[1 - v][(bufptr - deltime_r_corr) & ADDR_MASK], buffers[1-v][(bufptr - deltime_fb) & ADDR_MASK], out_right, del_right, amt_right, fb_right);
277 delay_mix(ins[0][i], ins[1][i], out_left, out_right, dry.get(), chmix.get());
279 age++;
280 outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
281 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
285 if (age >= MAX_DELAY)
286 age = MAX_DELAY;
287 if (medium > 0) {
288 bufptr = orig_bufptr;
289 if (medium == 2)
291 for(uint32_t i = offset; i < end; i++)
293 buffers[0][bufptr] = biquad_left[0].process_lp(biquad_left[1].process(buffers[0][bufptr]));
294 buffers[1][bufptr] = biquad_right[0].process_lp(biquad_right[1].process(buffers[1][bufptr]));
295 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
297 biquad_left[0].sanitize();biquad_right[0].sanitize();
298 } else {
299 for(uint32_t i = offset; i < end; i++)
301 buffers[0][bufptr] = biquad_left[1].process(buffers[0][bufptr]);
302 buffers[1][bufptr] = biquad_right[1].process(buffers[1][bufptr]);
303 bufptr = (bufptr + 1) & (MAX_DELAY - 1);
306 biquad_left[1].sanitize();biquad_right[1].sanitize();
310 return ostate;
313 /**********************************************************************
314 * COMPENSATION DELAY LINE by Vladimir Sadovnikov
315 **********************************************************************/
317 comp_delay_audio_module::comp_delay_audio_module()
319 buffer = NULL;
320 buf_size = 0;
321 delay = 0;
322 write_ptr = 0;
325 comp_delay_audio_module::~comp_delay_audio_module()
327 if (buffer != NULL)
328 delete [] buffer;
331 void comp_delay_audio_module::params_changed()
333 delay = (uint32_t)
336 (*params[par_distance_m] * 100.0) +
337 (*params[par_distance_cm] * 1.0) +
338 (*params[par_distance_mm] * 0.1)
339 ) * COMP_DELAY_SOUND_FRONT_DELAY(std::max(50, (int) *params[param_temp])) * srate
343 void comp_delay_audio_module::activate()
345 write_ptr = 0;
348 void comp_delay_audio_module::deactivate()
352 void comp_delay_audio_module::set_sample_rate(uint32_t sr)
354 srate = sr;
355 float *old_buf = buffer;
357 uint32_t min_buf_size = (uint32_t)(srate * COMP_DELAY_MAX_DELAY * 2);
358 uint32_t new_buf_size = 2;
359 while (new_buf_size < min_buf_size)
360 new_buf_size <<= 1;
362 float *new_buf = new float[new_buf_size];
363 for (size_t i=0; i<new_buf_size; i++)
364 new_buf[i] = 0.0f;
366 // Assign new pointer and size
367 buffer = new_buf;
368 buf_size = new_buf_size;
370 // Delete old buffer
371 if (old_buf != NULL)
372 delete [] old_buf;
375 uint32_t comp_delay_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
377 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
378 bool stereo = ins[1];
379 uint32_t w_ptr = write_ptr;
380 uint32_t b_mask = buf_size - 2;
381 uint32_t end = offset + numsamples;
382 uint32_t off = offset;
384 if (bypassed) {
385 while(offset < end) {
386 outs[0][offset] = ins[0][offset];
387 buffer[w_ptr] = ins[0][offset];
388 if (stereo)
389 outs[1][offset] = ins[1][offset];
390 buffer[w_ptr + 1] = ins[1][offset];
391 w_ptr = (w_ptr + 2) & b_mask;
392 ++offset;
394 } else {
395 uint32_t r_ptr = (write_ptr + buf_size - delay) & b_mask; // Unsigned math, that's why we add buf_size
396 float dry = *params[par_dry];
397 float wet = *params[par_wet];
398 float L = 0, R = 0;
400 for (uint32_t i=offset; i<end; i++)
402 L = ins[0][i];
403 buffer[w_ptr] = L;
404 outs[0][i] = dry * L + wet * buffer[r_ptr];
405 if (stereo)
406 R = ins[1][i];
407 buffer[w_ptr + 1] = R;
408 outs[1][i] = dry * R + wet * buffer[r_ptr + 1];
410 w_ptr = (w_ptr + 2) & b_mask;
411 r_ptr = (r_ptr + 2) & b_mask;
414 if (!bypassed)
415 bypass.crossfade(ins, outs, stereo ? 2 : 1, off, numsamples);
416 write_ptr = w_ptr;
417 return outputs_mask;
420 /**********************************************************************
421 * HAAS enhancer by Vladimir Sadovnikov
422 **********************************************************************/
424 haas_enhancer_audio_module::haas_enhancer_audio_module()
426 buffer = NULL;
427 srate = 0;
428 buf_size = 0;
429 write_ptr = 0;
431 m_source = 2;
432 s_delay[0] = 0;
433 s_delay[1] = 0;
434 s_bal_l[0] = 0.0f;
435 s_bal_l[1] = 0.0f;
436 s_bal_r[0] = 0.0f;
437 s_bal_r[1] = 0.0f;
440 haas_enhancer_audio_module::~haas_enhancer_audio_module()
442 if (buffer != NULL)
444 delete [] buffer;
445 buffer = NULL;
449 void haas_enhancer_audio_module::params_changed()
451 m_source = (uint32_t)(*params[par_m_source]);
452 s_delay[0] = (uint32_t)(*params[par_s_delay0] * 0.001 * srate);
453 s_delay[1] = (uint32_t)(*params[par_s_delay1] * 0.001 * srate);
455 float phase0 = ((*params[par_s_phase0]) > 0.5f) ? 1.0f : -1.0f;
456 float phase1 = ((*params[par_s_phase1]) > 0.5f) ? 1.0f : -1.0f;
458 s_bal_l[0] = (*params[par_s_balance0] + 1) / 2 * (*params[par_s_gain0]) * phase0;
459 s_bal_r[0] = (1.0 - (*params[par_s_balance0] + 1) / 2) * (*params[par_s_gain0]) * phase0;
460 s_bal_l[1] = (*params[par_s_balance1] + 1) / 2 * (*params[par_s_gain1]) * phase1;
461 s_bal_r[1] = (1.0 - (*params[par_s_balance1] + 1) / 2) * (*params[par_s_gain1]) * phase1;
464 void haas_enhancer_audio_module::activate()
466 write_ptr = 0;
469 void haas_enhancer_audio_module::deactivate()
473 void haas_enhancer_audio_module::set_sample_rate(uint32_t sr)
475 srate = sr;
476 float *old_buf = buffer;
478 uint32_t min_buf_size = (uint32_t)(srate * HAAS_ENHANCER_MAX_DELAY);
479 uint32_t new_buf_size = 1;
480 while (new_buf_size < min_buf_size)
481 new_buf_size <<= 1;
483 float *new_buf = new float[new_buf_size];
484 for (size_t i=0; i<new_buf_size; i++)
485 new_buf[i] = 0.0f;
487 // Assign new pointer and size
488 buffer = new_buf;
489 buf_size = new_buf_size;
491 // Delete old buffer
492 if (old_buf != NULL)
493 delete [] old_buf;
495 int meter[] = {param_meter_inL, param_meter_inR, param_meter_outL, param_meter_outR, param_meter_sideL, param_meter_sideR};
496 int clip[] = {param_clip_inL, param_clip_inR, param_clip_outL, param_clip_outR, -1, -1};
497 meters.init(params, meter, clip, 6, srate);
500 uint32_t haas_enhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
502 bool bypassed = bypass.update(*params[param_bypass] > 0.5f, numsamples);
503 uint32_t end = offset + numsamples;
504 uint32_t off_ = offset;
505 uint32_t w_ptr = write_ptr;
507 // Sample variables
508 float mid, side[2], side_l, side_r;
509 // Boundaries and pointers
510 uint32_t b_mask = buf_size-1;
512 while(offset < end) {
513 float values[] = {0, 0, 0, 0, 0, 0};
514 float *p = values;
516 // Get middle sample
517 switch (m_source)
519 case 0: mid = ins[0][offset]; break;
520 case 1: mid = ins[1][offset]; break;
521 case 2: mid = (ins[0][offset] + ins[1][offset]) * 0.5f; break;
522 case 3: mid = (ins[0][offset] - ins[1][offset]) * 0.5f; break;
523 default: mid = 0.0f;
526 // Store middle
527 buffer[w_ptr] = mid * *params[param_level_in];
529 if (bypassed) {
530 outs[0][offset] = ins[0][offset];
531 outs[1][offset] = ins[1][offset];
532 } else {
533 // Delays for mid and side. Unsigned math, that's why we add buf_size
534 uint32_t s0_ptr = (w_ptr + buf_size - s_delay[0]) & b_mask;
535 uint32_t s1_ptr = (w_ptr + buf_size - s_delay[1]) & b_mask;
537 // Calculate side
538 mid = mid * *params[param_level_in];
539 if (*params[par_m_phase] > 0.5f)
540 mid = -mid;
541 side[0] = buffer[s0_ptr] * (*params[par_s_gain]);
542 side[1] = buffer[s1_ptr] * (*params[par_s_gain]);
543 side_l = side[0] * s_bal_l[0] - side[1] * s_bal_l[1];
544 side_r = side[1] * s_bal_r[1] - side[0] * s_bal_r[0];
546 // Output stereo image
547 outs[0][offset] = (mid + side_l) * *params[param_level_out];
548 outs[1][offset] = (mid + side_r) * *params[param_level_out];
550 // Update pointers
551 s0_ptr = (s0_ptr + 1) & b_mask;
552 s1_ptr = (s1_ptr + 1) & b_mask;
554 *p++ = ins[0][offset]; *p++ = ins[1][offset];
555 *p++ = outs[0][offset]; *p++ = outs[1][offset];
556 *p++ = side_l; *p++ = side_r;
558 meters.process (values);
559 w_ptr = (w_ptr + 1) & b_mask;
560 ++offset;
562 if (!bypassed)
563 bypass.crossfade(ins, outs, 2, off_, numsamples);
564 write_ptr = w_ptr;
565 meters.fall(numsamples);
566 return outputs_mask;
569 /**********************************************************************
570 * REVERSE DELAY
571 **********************************************************************/
573 reverse_delay_audio_module::reverse_delay_audio_module()
575 for (int i = 0; i < MAX_DELAY; i++) {
576 buffers[0][i] = 0.f;
577 buffers[1][i] = 0.f;
580 counters[0] = 0;
581 counters[1] = 0;
583 feedback_buf[0] = 0;
584 feedback_buf[1] = 0;
587 void reverse_delay_audio_module::params_changed()
589 if (*params[par_sync] > 0.5f)
590 *params[par_bpm] = *params[par_bpm_host];
592 //Max delay line length: (60*192000/30)*16 = 6144000, see buffers declaration
593 float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]);
594 deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]);
595 deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]);
597 fb_val.set_inertia(*params[par_feedback]);
598 dry.set_inertia(*params[par_amount]);
600 counters[0] = 0;
601 counters[1] = 0;
603 ow[0].set_coef((*params[par_window] + 0.005), deltime_l/2);
604 ow[1].set_coef((*params[par_window] + 0.005), deltime_r/2);
606 width.set_inertia(*params[par_width]);
608 //Cleanup delay line buffers if reset
609 if(*params[par_reset])
611 for (int i = 0; i < MAX_DELAY; i++) {
612 buffers[0][i] = 0.f;
613 buffers[1][i] = 0.f;
616 feedback_buf[0] = 0;
617 feedback_buf[1] = 0;
621 void reverse_delay_audio_module::activate()
625 void reverse_delay_audio_module::deactivate()
629 void reverse_delay_audio_module::set_sample_rate(uint32_t sr)
631 srate = sr;
632 fb_val.set_sample_rate(sr);
633 dry.set_sample_rate(sr);
634 width.set_sample_rate(sr);
637 static float reverse_delay_line_impl(float in, float* buf, int* counter, int length)
639 float out = 0;
641 //Read data
642 if(*counter < length - 1)
644 unsigned int read_counter = length - 1 - (*counter);
645 out = buf[read_counter];
648 //Write data
649 *(buf + (*counter)) = in;
650 (*counter)++;
651 if ((*counter) > length-1)
652 (*counter) = 0;
654 return (out);
657 uint32_t reverse_delay_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
660 uint32_t ostate = 3; // XXXKF optimize!
661 uint32_t end = offset + numsamples;
663 //Loop
664 for(uint32_t i = offset; i < end; i++)
666 //Update sync led's
667 if(counters[0] < deltime_l/4)
668 *params[par_sync_led_l] = true;
669 else
670 *params[par_sync_led_l] = false;
672 if(counters[1] < deltime_r/4)
673 *params[par_sync_led_r] = true;
674 else
675 *params[par_sync_led_r] = false;
677 //Process
678 float feedback_val = fb_val.get();
679 float st_width_val = width.get();
681 float inL = ins[0][i] + st_width_val*ins[1][i];
682 float inR = ins[1][i]*(1 - st_width_val);
683 float outL = 0;
684 float outR = 0;
687 inL = inL + feedback_buf[0]* feedback_val*(1 - st_width_val) + feedback_buf[1]* st_width_val*feedback_val;
688 inR = inR + feedback_buf[1]* feedback_val*(1 - st_width_val) + feedback_buf[0]* st_width_val*feedback_val;
690 outL = reverse_delay_line_impl(inL, &buffers[0][0], &counters[0], deltime_l);
691 outR = reverse_delay_line_impl(inR, &buffers[1][0], &counters[1], deltime_r);
692 feedback_buf[0] = outL;
693 feedback_buf[1] = outR;
695 outL*= ow[0].get();
696 outR*= ow[1].get();
698 outL = outL*(1 + dry.get()) + inL*(1 - dry.get());
699 outR = outR*(1 + dry.get()) + inR*(1 - dry.get());
701 outs[0][i] = outL;
702 outs[1][i] = outR;
706 return ostate;