RedPhasor2 a phasor that can loop - version2


superclass: UGen


Similar to RedPhasor but if end point is less than start point, then the RedPhasor2 will not change direction.

But then use negative rate to go backwards.


*ar(trig, rate, start, end, loop, loopstart, loopend)

*kr(trig, rate, start, end, loop, loopstart, loopend)

trig - when triggered, ramp resets and goes to start.

rate - amount of change per sample.

start - ramp resets to this value when triggered.

end - final value of ramp.

loop - type of looping:

0= off.  no looping.  just ramp through once and stay at the end.

1= forward.  normal looping between points.

2= pingpong.  back and forth looping between points.

loopstart - start point of the loop.

loopend - marks the end of the loop.



//--

s.boot;


{SinOsc.ar(RedPhasor2.kr(MouseX.kr>0.5, 0.3, 400, 800, 0, 500, 600), 0, 0.2)}.play

{SinOsc.ar(RedPhasor2.kr(MouseX.kr>0.5, -0.3, 800, 400, 0, 500, 600), 0, 0.2)}.play



//--

//compares RedPhasor and RedPhasor2

(

var syn, osc, min= 400, max= 800, lmin= 0.3, lmax= 0.7;

var w= Window("redPhasor", Rect(400, 400, 400, 400)).front;

var startSld= Slider(w, Rect(10, 30, 20, 200)).value_(0)

.action= {|v|

if(startSld.value<endSld.value, {

loopStartSld.valueAction= loopStartSld.value.clip(startSld.value, endSld.value);

loopEndSld.valueAction= loopEndSld.value.clip(startSld.value, endSld.value);

}, {

loopStartSld.valueAction= loopStartSld.value.clip(endSld.value, startSld.value);

loopEndSld.valueAction= loopEndSld.value.clip(endSld.value, startSld.value);

});

syn.set(\start, v.value.linexp(0, 1, min, max));

};

var endSld= Slider(w, Rect(30, 30, 20, 200)).value_(1)

.action= {|v|

if(endSld.value>startSld.value, {

loopStartSld.valueAction= loopStartSld.value.clip(startSld.value, endSld.value);

loopEndSld.valueAction= loopEndSld.value.clip(startSld.value, endSld.value);

}, {

loopStartSld.valueAction= loopStartSld.value.clip(endSld.value, startSld.value);

loopEndSld.valueAction= loopEndSld.value.clip(endSld.value, startSld.value);

});

syn.set(\end, v.value.linexp(0, 1, min, max));

};

var loopStartSld= Slider(w, Rect(110, 30, 20, 200)).value_(lmin)

.action= {|v|

if(startSld.value<endSld.value, {

v.value= v.value.clip(startSld.value, endSld.value);

}, {

v.value= v.value.clip(endSld.value, startSld.value);

});

syn.set(\loopStart, v.value.linexp(0, 1, min, max));

};

var loopEndSld= Slider(w, Rect(130, 30, 20, 200)).value_(lmax)

.action= {|v|

if(endSld.value>startSld.value, {

v.value= v.value.clip(startSld.value, endSld.value);

}, {

v.value= v.value.clip(endSld.value, startSld.value);

});

syn.set(\loopEnd, v.value.linexp(0, 1, min, max));

};

var mult1= MultiSliderView(w, Rect(10, 260, 180, 120)).value_(0.dup(180))

.indexThumbSize_(1).gap_(0).valueThumbSize_(1);

var mult2= MultiSliderView(w, Rect(210, 260, 180, 120)).value_(0.dup(180))

.indexThumbSize_(1).gap_(0).valueThumbSize_(1);

Button(w, Rect(200, 60, 180, 20))

.states_([["trig"]])

.action_{syn.set(\t_trig, 1)};

Button(w, Rect(200, 120, 180, 20))

.states_([["loop= 0 (off)"], ["loop= 1 (on)"], ["loop= 2 (palindrome)"]])

.action_{|v| syn.set(\loop, v.value)};

Slider(w, Rect(200, 180, 180, 20)).value_(0.75)

.action_{|v| syn.set(\rate, v.value.linlin(0, 1, -1, 1))};

StaticText(w, Rect(60, 380, 100, 20)).string_("RedPhasor");

StaticText(w, Rect(260, 380, 100, 20)).string_("RedPhasor2");

StaticText(w, Rect(5, 10, 100, 20)).string_("start/end");

StaticText(w, Rect(80, 10, 100, 20)).string_("loopStart/loopEnd");

StaticText(w, Rect(280, 200, 100, 20)).string_("rate -1 to 1");

syn= SynthDef(\redPhasor, {|t_trig= 1, rate= 0.5, start= 400, end= 800, loop= 0, loopStart= 500, loopEnd= 600|

var rp1= RedPhasor.kr(t_trig, rate, start, end, loop, loopStart, loopEnd);

var rp2= RedPhasor2.kr(t_trig, rate, start, end, loop, loopStart, loopEnd);

var report= Impulse.kr(40);

SendTrig.kr(report, #[0, 1], [rp1, rp2]);

Out.ar(0, SinOsc.ar([rp1, rp2], 0, 0.3));

}).play(s, [\start, min, \end, max, \loopStart, lmin.linexp(0, 1, min, max), \loopEnd, lmax.linexp(0, 1, min, max)]);

osc= OSCresponder(s.addr, '/tr', {|t, r, m|

switch(m[2],

0, {{mult1.value= mult1.value.rotate(-1).put(179, m[3].explin(min, max, 0, 1))}.defer},

1, {{mult2.value= mult2.value.rotate(-1).put(179, m[3].explin(min, max, 0, 1))}.defer}

);

}).add;

w.onClose= {osc.remove; syn.free};

CmdPeriod.doOnce({if(w.isClosed.not, {w.close})});

)