Hardsync of two Phasors

hey,
after looking at this video describing a specific rhythm technique used by mark fell on intra,
I thought this is basically hard sync of two ramps. Would someone know how to implement that with two phasors?

This was my first attempt following the description in the video:

``````(
{ |innerLoop = 3, outerLoop = 7|
var rate = 250;

var outerPhase = (Phasor.ar(DC.ar(0), rate * SampleDur.ir, 0, 1) * outerLoop - SampleDur.ir).wrap(0, outerLoop);
var outerImpulse = HPZ1.ar(outerPhase) < 0;

var innerPhase = (Phasor.ar(outerImpulse, rate * SampleDur.ir, 0, 1) * innerLoop - SampleDur.ir).wrap(0, innerLoop);
var innerImpulse = HPZ1.ar(innerPhase) < 0;

[innerPhase, innerImpulse, outerPhase, outerImpulse];
}.plot(0.02);
)
``````

EDIT: In the book about gen~ which is mentioned in the video its stated that sometimes its better to derive triggers from phases and not phases from triggers. The book makes an argument for using phasors instead of triggers for organising rhythmic structures with the different possibilites for shaping the ramps and getting triggers, steps, lfos etc from it which are synced to the triggers. One advantage i found already is, that its possible to have asynchronous triggers and a continuous phase and for example divide the phase by non-integer values to get non-integer divisions.

Hi,
Something like this?

``````(
{
var a = Phasor.ar(0, s.sampleRate.reciprocal * (1/3), 0, 1); // 1/3Hz
var b = Phasor.ar(Slope.ar(a), s.sampleRate.reciprocal * (1/2), 0, 1); // 1/2 Hz
var c = Trig.ar(Slope.ar(b), 0.1);
[a,b, c];
}.plot(6);
)

``````

Iâ€™m not done watching the video yet, so I assume this is what you mean.

cool it seems to work.
I have addtionally subtracted `SampleDur.ir` before wrapping the Phasors, so you also get the initial trigger and replaced `Trig.ar` by `Trig1.ar` and used `SampleDur.ir` for its duration. This seems to result in an appropriate range between 0 and 1 for the trigger.

``````(
{ |innerLoop = 4, outerLoop = 7|
var rate = 100;
var a = (Phasor.ar(0, rate * SampleDur.ir * innerLoop, 0, 1) - SampleDur.ir).wrap(0, 1);
var b = (Phasor.ar(Slope.ar(a), rate * SampleDur.ir * outerLoop, 0, 1) - SampleDur.ir).wrap(0, 1);
var c = Trig1.ar(Slope.ar(b), SampleDur.ir);
[a, b, c];
}.plot(0.02);
)
``````

Is the `Slope / Trig1` combination equal to `HPZ1` in terms of accurancy?

``````(
{ |innerLoop = 4, outerLoop = 7|
var rate = 100;
var a = (Phasor.ar(0, rate * SampleDur.ir * innerLoop, 0, 1) - SampleDur.ir).wrap(0, 1);
var b = (Phasor.ar(HPZ1.ar(a) < 0, rate * SampleDur.ir * outerLoop, 0, 1) - SampleDur.ir).wrap(0, 1);
var c = HPZ1.ar(b) < 0;
[a, b, c];
}.plot(0.02);
)
``````

EDIT: i guess not:

Slope / Trig1

HPZ1

adding Impulse.ar(0) to HPZ1 without subtracting SampleDur.ir from Phasor

2 Likes

I tried to mock up a Pattern version that has the same trigger semantics - I couldnâ€™t come up with anything off the top of my head, but it would be a cool thing to solve. Obviously, continuously varying the rates wouldnâ€™t work, but I think one could still achieve some cool results?

not sure but couldnâ€™t the pattern version be as simple as something like

``````Pseq( {|i| [1, 0, 0].wrapAt(i.mod(7)) }.dup(7), inf).asStream.nextN(7)
``````

at least based on the diagram he showed at the beginning of the video.

1 Like

the scaling of the rates could be done more intuitively i guess, but its additionally good to latch the syncedRatio:

``````(
var hardSyncTrigs = { |rate, syncRatio, syncedRatio|
var syncPhase = Phasor.ar(DC.ar(0), rate * syncRatio * SampleDur.ir, 0, 1);
var syncTrig = HPZ1.ar(syncPhase) < 0 + Impulse.ar(0);
var syncedPhase = Phasor.ar(syncTrig, rate * Latch.ar(syncedRatio, syncTrig).poll * SampleDur.ir, 0, 1);
HPZ1.ar(syncedPhase) < 0 + Impulse.ar(0);
};

{
var rate, syncedRatio, syncRatio, trig, freqs, exc, sig;

rate = 12;
syncRatio = 1 / 11;
syncedRatio = 1 / LFSaw.ar(0.1, 1).linlin(-1, 1, 2, 9).round(1);
trig = hardSyncTrigs.(rate, syncRatio, syncedRatio);

freqs = (60.5 + [0, 2, 4, 7, 11]).midicps;

exc = Hasher.ar(Sweep.ar(trig)) * -10.dbamp;
sig = Pluck.ar(exc, trig, freqs.reciprocal, freqs.reciprocal, \dec.kr(0.5), \coef.kr(0.2)).sum;
sig = LeakDC.ar(sig);

sig = Pan2.ar(sig, \pan.kr(0));

sig * \amp.kr(-15.dbamp);

}.play;
)
``````