Making patterns aware of bars and beats

Hi, my first post here! Thanks for setting up such a nice forum!

Is there a straightforward way to treat a set of parallel patterns as if the events were placed on a timeline and to jump around using bars and beats?
I.e. if i have a structure like this:

(
~pitchArray = (0..11);
~durArray = [1, 2, 4];
p = Ppar([
	Pbind(
		\degree, Pseq(~pitchArray, inf),
		\dur, Pseq(~durArray, inf)
	),
	Pbind(
		\degree, Pseq(~pitchArray, inf),
		\dur, Pseq(~durArray*0.25, inf)
	)
]).play;
)

And then be able to start it from something like bar 22 beat 3 or something (e.g. for reharsals with other musicians following a fixed score etc). I’ve done similar things before putting parts (pbinds for example) of a piece in a Pseq like this

Pseq([part1, part2, part3], 1, offset);

and then i can at least jump to a different part using offset. But this doesn’t work when you need flexibility.
Any ideas?

In the past there has been some discussion about fastforwarding, but in general it’s not a trivial problem given the flexibility of patterns (which may include random durations etc).

http://sc-users.bham.ac.narkive.com/IUvoCSGV/fast-forwarding-a-pattern

1 Like

Thanks! Fast forward was the only keyword i didn’t include in my googling. I suspected people had this need before. And yeah, i realize it’s non-trivial. It’s sort of against the nature of patterns maybe. :wink:

1 Like

You can hack it if none of your patterns are aware of the clock (e.g. no PEnv). You basically create a pattern and keep hitting next until the right number of beats have gone past.

And yes, it kind of is against the nature of patterns I’m afraid.

I wouldn’t be that pessimistic. It’s one of the classical FAQs and I remember various people made suggestions. Unfortunately search is a pain ATM, I found these two posts:

https://www.listarc.bham.ac.uk/lists/sc-users-2014/msg39151.html
https://www.listarc.bham.ac.uk/lists/sc-users-2016/msg50148.html

And I am quite sure Julian Rohrhuber posted a solution some years ago, maybe ask him ?

Daniel

1 Like

James’ solution (and the class by simdax) seems to work quite good actually. Thanks Daniel!

Right. But if your pattern includes a PEnv, or Ptime, or any other pattern that checks the number of elapsed beats then I don’t think this approach will work.

Did you try? Ptime seems to work as expected here. Never used Penv and since it’s undocumented i don’t really know what to expect. No errors if i just throw it into my current structure though.

You won’t get errors, it just won’t give you the same results as if you ran it in real time. Look at the code if you don’t believe me (this problem also exists if you want to generate NRT scores using patterns. Any patterns that depend upon the thread/clock won’t give you the right result).

Penv is just a pattern version of EnvGen. I keep meaning to write documentation for it, but it’s discussed in James’ patterns tutorial.

1 Like

Ok. Good to know for the future. My more immediate issues seems to be solved at least.

Okay I found a solution to this. I always forget that thread in SuperCollider means something different to conventional usages of the term.

As soon as I’ve made my solution less of a hack I’ll post something.

1 Like

You could probably mess with Thread.endBeat which is a semi-hidden feature that time-dependent patterns use, but just finding (all) the Threads that need be messed with is difficult. (You’d need to traverse the tree of Threads spawned from the main Stream of the player, or something like that.) The real alternative imho is to not use time-dependent patterns. Sometimes that’s feasible and even desirable. But sometimes something like PtimeClutch is really handy.

And fast-forward is not the only time when time-dependent patterns have issues. As I noted in a linked thread:

Unfortunately all the Ptime -like patterns get desynchronized from the underlying stream if you pause the Stream[Player].

In a more “future vision” (rather than how to hack the present system), there could probably be a dependent-clock registration system implemented so that when you pause or FF a thread some “related” threads would get the same treatment for their clocks. But with pausing there’s the additional issue that clocks once stopped (=paused) cannot be restarted (for some reason). You have to create a new clock…

Hi,

Still on this topic, I would like to align patterns using the offset parameter according to this example :

Where in my case I have 4 parts corresponding to one bar each so that it represents a 4 bars of 4 beats pattern.

Here is an example to illustrate the issue I’m facing :

(
t = TempoClock.new(100/60);
~postBeats = {("bar:" + ((t.beats/4).floor%4+1) + (" beat:" + (t.beats%4+1))).postln;1};
t.schedAbs(t.nextBar, {~postBeats.value});

~deg1 = [1,1,Rest(1),Rest(1)];
~deg2 = [1,1,1,Rest(1)];
)

(
//\degree, Pseq([part1, part2, part3, part4], inf, offset): 
//part1's degree is 1 (bar 1), part2's degree is 2 (bar 2), etc...
a = Pbindef(\test,
	\degree, Pseq([Pseq(~deg1,1),Pseq(~deg1+1,1),Pseq(~deg1+2,1),Pseq(~deg1+3,1)], inf,(t.beats/4).floor%4+1).trace
);
a.play(t, quant: 4);
)

// First case : the "\degree" parameter of the pattern "a" is modified -> bars and degrees are still aligned
Pbindef(\test,\degree, Pseq([Pseq(~deg2,1), Pseq(~deg2+1,1), Pseq(~deg2+2,1), Pseq(~deg2+3,1)], inf, (t.beats/4).floor%4+1)).quant_(4);
Pbindef(\test,\degree, Pseq([Pseq(~deg1,1), Pseq(~deg1+1,1), Pseq(~deg1+2,1), Pseq(~deg1+3,1)], inf, (t.beats/4).floor%4+1)).quant_(4);


// Second case : pattern "a" is stopped at the end of the bar and pattern "b" is started -> bars and degrees are not aligned
(
b = Pbindef(\test2,
	\degree, Pseq([Pseq(~deg2,1), Pseq(~deg2+1,1), Pseq(~deg2+2,1), Pseq(~deg2+3,1)], inf, (t.beats/4).floor%4+1).trace
);

t.schedAbs((t.nextTimeOnGrid(4)), {a.stop; b.play(t, quant: 4)});
t.schedAbs((t.nextTimeOnGrid(4)), {b.stop; a.play(t, quant: 4)});

The first case (one pattern modified) seems to be robust. But in the second case, where a pattern is stopped and another started, the alignment is lost and notes overlapping appears. Is there a mistake in the schedAbs arguments ? Would it be more reliable to use fastForward method instead, as shown here: Live Coding, Pdef, Quantization and timming ?

mic

It actually appears that the link between the pattern and the TempoClock is broken after stopping the pattern, hence the offset parameter is nil. The solution I found (maybe not ideal) is to create a function with a TempoClock as argument and to define the offset with this argument :

t = TempoClock.new(100/60);

~pat = {arg tempo;
	a = Pbindef(\test,
	      \degree, Pseq([part1, part2, part3, part4], inf, (tempo.beats/4).floor%4+1).trace
        )
};

~pat.value(t).play(t, quant: 4); 

t.schedAbs((t.nextTimeOnGrid(4, -0.001)), {a.stop});

Still I would be glad to have other views, as there might be a more subtle way of keeping this TempoClock reference in the pattern.

mic