RedPhasor a phasor that can loop
superclass: UGen
Similar to Phasor but can also loop between two points. Useful for driving a BufRd.
If end point is less than start point, then the RedPhasor will automatically change direction.
See RedPhasor2 for a slightly different version that can have negative rate and thereby 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. must be positive.
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;
//no looping & it will play through once. mouse x acts as trigger
{SinOsc.ar(RedPhasor.kr(MouseX.kr>0.5, 0.3, 400, 800, 0, 500, 600), 0, 0.2)}.play
//mouse y controls looping on/off, mouse x trigger
{SinOsc.ar(RedPhasor.kr(MouseX.kr>0.5, 0.3, 400, 800, MouseY.kr>0.5, 500, 600), 0, 0.2)}.play
//notice that if you trigger with looping on it still jumps to the start value.
//this is what i needed to have control over and why i wrote the redphasor in the first case.
//mouse x controls loop rate, mouse y scales the start looppoint
{SinOsc.ar(RedPhasor.kr(0, MouseX.kr(0, 5), 400, 800, 1, MouseY.kr(200, 500), 500), 0, 0.2)}.play
//below different directions for start/end vs looppoints. automatic loop on/off
{SinOsc.ar(RedPhasor.kr(0, 0.6, 400, 800, LFPulse.kr(0.2), 500, 600), 0, 0.2)}.play
{SinOsc.ar(RedPhasor.kr(0, 0.6, 400, 800, LFPulse.kr(0.2), 600, 500), 0, 0.2)}.play
{SinOsc.ar(RedPhasor.kr(0, 0.6, 800, 400, LFPulse.kr(0.2), 500, 600), 0, 0.2)}.play
{SinOsc.ar(RedPhasor.kr(0, 0.6, 800, 400, LFPulse.kr(0.2), 500, 600), 0, 0.2)}.play
//notice how loopstart sometimes is greater than loopend
//watch out for looppoints out of range
{SinOsc.ar(RedPhasor.kr(Impulse.kr(0.5), 2, 800, 400, LFPulse.kr(0.4), 150, 1600), 0, 0.2)}.play
//the different types of looping. mouse x acts as trigger
a= {|loop= 0| SinOsc.ar(RedPhasor.kr(MouseX.kr>0.5, 0.3, 400, 800, loop, 500, 600), 0, 0.2)}.play
a.set(\loop, 0); //off
a.set(\loop, 1); //forward
a.set(\loop, 2); //pingpong
a.free
//--loopbuf examples:
b= Buffer.read(s, "sounds/a11wlk01.wav");
({ //mouse x/y controls looppoints
var rate= BufRateScale.ir(b.bufnum);
var end= BufFrames.ir(b.bufnum)-1;
var min= MouseX.kr*end;
var max= MouseY.kr*end;
var looptype= 2; //pingpong
var i= RedPhasor.ar(0, rate, min, max, 2, min, max);
BufRd.ar(1, b.bufnum, i, 0, 2);
}.play)
({ //click and drag
//mouse button starts looping between 45 and 55%. release it and the phasor continues to end
var rate= BufRateScale.ir(b.bufnum);
var end= BufFrames.ir(b.bufnum)-1;
var trig= MouseButton.kr(lag:0);
var i= RedPhasor.ar(trig, rate*MouseX.kr(0.1, 10), 0, end, trig, end*0.45, end*0.55);
BufRd.ar(1, b.bufnum, i, 0, 2);
}.play)
({ //audiorate control for trigger (unused here) and rate
var rate= SinOsc.ar(MouseX.kr(-50, 50), 0, MouseY.kr(0, 0.5), 1);
var end= BufFrames.ir(b.bufnum)-1;
var i= RedPhasor.ar(DC.ar(0), rate, 0, end, 2, 0, end);
BufRd.ar(1, b.bufnum, i, 0, 2);
}.play)
b.free
//--
b= Buffer.read(s, "sounds/a11wlk01.wav");
(
SynthDef(\redPhasorLooper, {|out= 0, bufnum, rate= 1, loop= 1, loopStart= 0, loopEnd= 1, gate= 1|
var e= EnvGen.kr(Env.asr(0.01, 1, 0.01), gate, doneAction: 2);
var end= BufFrames.kr(b.bufnum)-1;
var p= RedPhasor.ar(0, rate*BufRateScale.kr(bufnum), 0, end, loop, loopStart*end, loopEnd*end);
var z= BufRd.ar(1, bufnum, p, 0, 2);
Out.ar(out, z*e);
}).add;
)
a= Pmono(\redPhasorLooper, \dur, Pseq([Pn(0.25, 2), 0.5], inf), \rate, Pseq([0.5, 1, 2], inf)).play
a.stop
a= Pmono(\redPhasorLooper, \dur, Pseq([Pn(0.125, 2), 0.25], inf), \rate, Pseq([0.75, 1, 1.25, 1], inf), \loop, Pseq([1, 1, 1, 2, 0], inf), \loopStart, Pseq([0, 0.25, 0.5, 0.75], inf), \loopEnd, Pseq([0.99, 0.66, 0.33], inf)).play
a.stop
a= Pmono(\redPhasorLooper, \dur, 0.125, \rate, Pseq([2, 3, 4]*0.25, inf), \loop, Pseq([Pn(2, 64), Pn(0, 32)], inf), \loopStart, Pseq([0, 0.25, 0.5, 0.75], inf), \loopEnd, Pseq([0.99, 0.66, 0.33], inf)).play
a.stop
b.free
//--
b= Buffer.read(s, "sounds/a11wlk01.wav");
(
SynthDef(\redPhasorLooper2, {|out= 0, bufnum, rate= 1, lag= 0.01, gate= 1, amp= 0.5, pan= 0|
var e= EnvGen.ar(Env.asr(0.01, 1, 0.1), gate, doneAction:2);
var end= BufFrames.kr(b.bufnum)-1;
var startLoop= K2A.ar(MouseX.kr(0, end, 0, 0)); //no lag and convert to .ar
var endLoop= K2A.ar(MouseY.kr(0, end, 0, 0)); //no lag and convert to .ar
var r= Lag.kr(rate, lag);
var trig= Ramp.ar(HPZ2.ar(startLoop), 0.1);
var p= RedPhasor.ar(trig, r*BufRateScale.kr(bufnum), startLoop, end, 1, startLoop, endLoop);
var z= BufRd.ar(1, bufnum, p, 0, 2);
Out.ar(out, Pan2.ar(z*e, pan, amp));
}).add;
)
a= Synth(\redPhasorLooper2, [\bufnum, b.bufnum]);
a.set(\rate, 1.25)
a.free
b.free