slider1:_paramSweepRate=1<0,8,0.1>Rate (Hz)
slider2:_paramWidth=20<0,100,1>Width (%)
slider3:_paramFeedback=70<0,100,1>Feedback (%)
slider4:_paramDelay=6<0,100,1>Delay (ms)
slider5:_paramMix=0<0,5,1{Mono Sum in,Stereo L+R in,Mono Sum in Minus,Stereo L+R in Minus,Mono Sum in --- Stereo out,Stereo L+R in --- Stereo out}>Mix Mode
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
_feedbackPhase = 1;
_sweepSamples = 0; // sweep width in # of samples
_fp = 0; // fill/write pointer
_sweep = 0; // current value of sweep in steps behind fill pointer

outval1 = outval2 = 0; // most recent output value (for feedback)
	
_mixLeftWet =
_mixLeftDry =
_mixRightWet =
_mixRightDry = 0.5;

_mixMono = 1;

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

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

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

function _sweepRate(x)
(
// rate
// map into param onto 0.05Hz - 10hz with log curve
_sweepRate = pow(10,_paramSweepRate*0.1);
_sweepRate -= 1;
_sweepRate *= 1.05556;
_sweepRate += 0.05;
);

@slider
width = _paramWidth * 0.0001;
sweep = _sweepRate();

(width != old_width || sweep != old_sweep) ? (
// width
// map so that we can spec between 0ms and 10ms
(width == 0) ? (
// eat some noise on the bottom end
_sweepSamples = 0;
):(
// otherwise calc # of samples for the total width
_sweepSamples = width * srate|0;
);

// sweep
// calc # of samples per second we'll need to move to achieve spec'd sweep rate
_step = (_sweepSamples * 2 * sweep) / srate;

// calc max and start sweep at 0
_sweep = 0;

_maxSweepSamples = _sweepSamples;

old_width = width;
old_sweep = sweep;
);

output = 10^(slider6/20);

@sample
_paramMix == 0 ? ( //mono sum in
_mixMono = 1;
_mixLeftWet = _mixRightWet = _mixLeftDry = _mixRightDry = 1;
_feedbackPhase = 1;
);
_paramMix == 1 ? ( //stereo l+r in
_mixMono = 0;
_mixLeftWet = _mixRightWet = 1;
_mixLeftDry = _mixRightDry = 1;
_feedbackPhase = 1;
);
_paramMix == 2 ? ( //mono sum in minus
_mixMono = 1;
_mixLeftWet = _mixRightWet = -1;
_mixLeftDry = _mixRightDry = 1;
_feedbackPhase = -1;
);
_paramMix == 3 ? ( //stereo l+r in minus
_mixMono = 0;
_mixLeftWet = _mixRightWet = -1;
_mixLeftDry = _mixRightDry = 1;
_feedbackPhase = -1;
);
_paramMix == 4 ? ( //mono sum in --- sterero out
_mixMono = 1;
_mixLeftWet = _mixLeftDry = _mixRightDry = 1;
_mixRightWet = -1;
_feedbackPhase = 1;
);
_paramMix == 5 ? ( //stereo l+r in --- stereo out
_mixMono = 0;
_mixLeftWet = _mixLeftDry = _mixRightDry = 1;
_mixRightWet = -1;
_feedbackPhase = 1;
);

(_mixMono) ? (
inval1 = inval2 = (spl0 + spl1)*0.5;
):(
inval1 = spl0;
inval2 = spl1;
);
		
inmix1 = inval1 + tanh(_paramFeedback * 0.01 * _feedbackPhase * outval1);
inmix2 = inval2 + tanh(_paramFeedback * 0.01 * _feedbackPhase * outval2);

buf1[_fp] = inmix1;
buf2[_fp] = inmix2;
_fp = (_fp + 1) & (BSZ-1);

// delay 0.0-1.0 maps to 0.02ms to 10ms (always have at least 1 sample of delay)
delaySamples = (_paramDelay * srate * 0.0001) + 1;
delaySamples += _sweep;

ep = _fp - delaySamples;
(ep < 0) ? (
ep += BSZ;
);

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

ep1 &= (BSZ-1);
ep2 = ep1 + 1;
ep2 &= (BSZ-1);
w1 = 1 - w2;
outval1 = buf1[ep1] * w1 + buf1[ep2] * w2;
outval2 = buf2[ep1] * w1 + buf2[ep2] * w2;

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

// see if we're doing sweep
(_step != 0) ? (
// increment the sweep
_sweep += _step;
(_sweep <= 0) ? (
// make sure we don't go negative
_sweep = 0;
// and reverse direction
_step = -_step;
) : (_sweep >= _maxSweepSamples) ? (
_step = -_step;
);
);

spl0 = out0*output*0.707;
spl1 = out1*output*0.707;
