Shifting arrays as a means of time travel

I’ve been working on ways of making future events available in the present as a way of extending the capabilities of various conditional operations. This is what I’ve come up with.
What I think is nice about it is that it allows for a resonable degree of live coding and live experimentation.

It is kind of a lot of text though so I’m really just asking for input on ways of expressing the same functionality in a neater way?
Maybe methods or classes i’ve overlooked.

(
// Run this block first
t = TempoClock.new(120/60).permanent_(true);
t.tempo_(120/60);
t.permanent_(true);

// These can be evaluated line by line with shift+return after running the containing block.
// When evaluated these patterns will be embeded in the Routines-streams below when the previously embedded pattern ends.
~hhPattern1 = Pshufn(Bjorklund(5, 8), 1);
~hhPattern1 = Pseq([1, 0, 0, 0, 0, 0, 0, 0],1);
~hhPattern2 = Pseq([1, 0, 0, 0, 1, 0, 0, 0],1);


// These make it so that the ~hhAmpArrayGen and the patterns above can be 
//evaluated separetaly and still keep putting out numbers on time.
~hhPatternRoutine1 = Routine{
	~hhPattern1.embedInStream;
}.loop;

~hhPatternRoutine2 = Routine{
	~hhPattern2.embedInStream;
}.loop;
)

// This function does all the conditional operations.
// It also keeps a record of what is going to happen and what has happened with a shifting array.
(
// Then this block 
var array=0!9;
~hhAmpArrayGen= {
	var shiftedArray, pat1, pat2;
	shiftedArray=array.shift(-1, 0);
	array=shiftedArray;
	pat1=~hhPatternRoutine1.next;
	pat2=~hhPatternRoutine2.next;
	((t.beats)%16).inclusivelyBetween(14,16)
	.if(
		{array.put(array.size-1, pat2)},
		{array.put(array.size-1, pat1)}
	);
	~hhArray=array;
	~hhArray.postln;
	array;
};
)

// Try running the function a few times to get an idea of what it's doing.
~hhAmpArrayGen.value

(
// When evaluated this function resets the "pattern routines" to make 
// sure the patterns start from the begining. 
~hhPatternRoutine1.reset;
~hhPatternRoutine2.reset;
~hhPlazy=Pn(Plazy({
	~hhAmpArrayGen;
	Pbind(
		\instrument, \default,
		\dur, 0.25,
		//The \amp-key only gets paired with the element currently at index 5. 
		\amp, Pseq([~hhAmpArrayGen.value[4]], 1),
		\rell, 0.1,
		\freq, Pif(Pkey(\amp) > 0, 1, \rest)
	)
}), inf).play(t, quant:[4, 1, 0.1]);
)

Check this out:

{ } // a function
r { } // a routine
p { } // a Prout

There are so many pattern objects, it’s hard to tell which ones are ‘critical’, and which ones are more… ‘arbitrary’.

Pseq is definitely critically, and if any others could be more so… as some may concur: Prout may be even more fundamental… for there is nowhere else in sclang… where it may been seen, by eyes of artistry & and legends alike, that such a form of expressive transformation, such for may be deemed, by the few and the many, as being so crucial, so critical, to the foundation of our time-based musical processes and synthesis, that, in a single keystroke… one may wield such power of transformation, that, by convention, (in a single letter…) shapes are shifted, consciousness transmutes, and expression evolves at a rate unsurpassed, save, however, by our tradtion long-standing and unshakeable convention… the eternally unambiguous, server letter s… the mere transfiguration of which, would be treated as the highest of transgressions… across space and time, in all fields, in practices… and… in most computer programming languages.

In SC, there is only two single letters… implemented as methods, and dedicated to singleton instances of pure transformation:

the letter r… and… the letter p…

…all things considered, the actual in-case usage of .r & .p appears somehwat rare… perhaps mostly due to the fact that it lacks a certain amount of clarity, and expression becomes to some degree unclear.

However, these single letter tranformations should work well in cases where one wants to shift focus away from the enclosing bracket transformation… and towards more meaningful or significant aspect of the piece as a whole.

Also… you can chain link Prouts like so:

Prout{ "will run first" } <> Prout { "2nd in chain" } <> Prout { "third in chain" }

…and, when .asEventStreamPlayer is called from the Pchain, all of the Prouts in the chain will inherit the yield time set by the first one:

(Prout{ loop{ 0.7.yield } } <> Prout{ loop{ 'a'.postln; inf.yield; 'b'.postln; inf.yield } } <> Prout{ loop { 'x'.postln; inf.yield; 'y'.postln; inf.yield} }).asEventStreamPlayer.play

1 Like