slider1:_paramSweepRate=1<0,8,0.1>Rate (Hz)
slider2:_paramWidth=15<0,100,1>Width (%)
slider3:_paramDelay=30<0,100,1>Delay (ms)
slider4:_paramMix=0<0,3,1{Mono,Stereo,Mono Wet Only,Stereo Wet Only}>Mix Mode
slider5:0<0,100,1>Dry Mix (%)
slider6:0<-30,12,0.1>Output (dB)
slider7:0<0,1,1{tanh,hard}>--Limit

in_pin:L in
in_pin:R in
out_pin:L out
out_pin:R out

@init
_sweepSamples = 0; // sweep width in # of samples
_fp = 0; // fill/write pointer
_sweep = 0;

_mixLeftWet =
_mixLeftDry =
_mixRightWet =
_mixRightDry = 0.5;

BSZ = 8192; // ~0.2*srate
buf = BSZ;
memset(buf,0,BSZ);

i=0;
while(i<BSZ) (
i+=1;
buf[i]=0;
);

function tanh(x)
(
x = exp(2*x);
(x - 1) / (x + 1);
);

function _sweepRate(x)
(
// rate
// map into param onto desired sweep range with log curve
_sweepRate = pow(10,_paramSweepRate*0.1);
_sweepRate -= 1;
_sweepRate *= 1.1;
_sweepRate += 0.1;
);

@slider
width = _paramWidth * 0.0005;
delay = pow(10, _paramDelay * 0.02)/1000; // map logarithmically and convert to seconds
sweep = _sweepRate();

(width != old_width || delay != old_delay || sweep != old_sweep) ? (
// width
// map so that we can spec between 0ms and 50ms
_sweepSamples = ceil(width * srate);

// delay
_delaySamples = ceil(delay * srate);

// sweep
_step = (_sweepSamples * 2 * sweep) / srate;

// calc min and max sweep now
_minSweepSamples = _delaySamples;
_maxSweepSamples = _delaySamples + _sweepSamples;

// set intial sweep pointer to midrange
_sweep = (_minSweepSamples + _maxSweepSamples) / 2;

old_width = width;
old_delay = delay;
old_sweep = sweep;
);

mix = slider5 * 0.01;
output = 10^(slider6/20);

@sample
_paramMix == 0 ? ( //mono
_mixLeftWet = _mixRightWet = 1;
_mixLeftDry = _mixRightDry = 1;
);
_paramMix == 1 ? ( //stereo
_mixLeftWet = 1;
_mixLeftDry = 1;
_mixRightWet = -1;
_mixRightDry = 1;
);
_paramMix == 2 ? ( //mono wet only
_mixLeftWet = _mixRightWet = 1;
_mixLeftDry = _mixRightDry = 0;
);
_paramMix == 3 ? ( //stereo wet only
_mixLeftWet = 1;
_mixLeftDry = 0;
_mixRightWet = -1;
_mixRightDry = 0;
);

inval = (spl0 + spl1)*0.5;

buf[_fp] = inval;
_fp = (_fp + 1) & (BSZ-1);

// build the two emptying pointers and do linear interpolation
ep = _fp - _sweep;

outval = 0;

/*
// build the two emptying pointers and do linear interpolation
Samples = (_paramDelay * srate * 0.0001) + 1;
Samples += _sweep;

ep = _fp - Samples;
(ep < 0) ? (
ep += BSZ;
);
*/

ep1 = ep|0;
w2 = ep-ep1;

ep1 &= (BSZ-1);
ep2 = ep1 + 1;
ep2 &= (BSZ-1);
w1 = 1 - w2;
outval = buf[ep1] * w1 + buf[ep2] * w2;

// develop output mix
slider7 ? (
out0 = min(max(_mixLeftDry * inval + _mixLeftWet * outval,-0.99), 0.99);
out1 = min(max(_mixRightDry * inval + _mixRightWet * outval,-0.99), 0.99);
):(
out0 = tanh(_mixLeftDry * inval + _mixLeftWet * outval);
out1 = tanh(_mixRightDry * inval + _mixRightWet * outval);
);

// increment the sweep
_sweep += _step;
(_sweep >= _maxSweepSamples || _sweep <= _minSweepSamples) ? (
_step = -_step;
);

_paramMix > 1 ? (
spl0 = (spl0*mix + out0*(1-mix))*output;
spl1 = (spl1*mix + out1*(1-mix))*output;
):(
spl0 = out0*output*0.707;
spl1 = out1*output*0.707;
);
