Growing array in pattern


#1

hi i would like to use growing arrays inside a Pbind. something like Pseq + adding a new element in the array each time the pattern repeats (basically use and modify dynamic arrays in patterns)
i tried fiddling with Pfunc/Prout but without luck… thanks!

Pbind(\instrument, \xyz,
\freq, 400,
\dur, Pseq([1,2,3,4],inf) // i would like to do [1,2,3,4].add(5) after the Pseq played ‘4’
);


#2

Hi fish

what is the difference, for your purposes, between a) just writing [1,2,3,4, 5] when you define the Pbind and b) adding the 5 later?

.

cheers

eddi


#3

I’m not sure if you mean something with the effect of this:

(
Pbind(
	\instrument, \default,
	\dur, Pseq([Pseq([1,2,3,4],2),Pseq([5],1)], inf), 
	\freq, 400,
).play;
)

There’s probably a more elegant way of doing this if we know what you need to do.

Hope that helps.


#4

thanks guys, @joesh yes something like that, but the resulting array should keep growing like this:

[1,2,3,4]
[1,2,3,4,5]
[1,2,3,4,5,6]

actually in my piece i want something like this each repeat for my \dur key:

[0.25,1.25,0.5,0.5] //3 beats
[0.25,1.25,0.5,0.5, 0.5, 0.5, 0.5, 0.5] // 5 beats
[0.25,1.25,0.5,0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5] // 7 beats

or be able to inverse this. basically i want to dynamically grow or shrink the resulting array each repeat.


#5

Ah, I think (if I understand), you’d need Pseries.

(
Pbind(
	\instrument, \default,
	\dur, Pseries(1, 1, 7).trace, 
	\freq, 400,
).play;
)

Try this and if it’s correct (see the trace in the post window), then alter it as needed.

Hope that helps.


#6

thanks @joesh, i tried pseries but its not exactly what i want. basically i want to be able to concatenate the Pseq array with another array each repeat (or slice it for inverse).

[0.25,1.25,0.5,0.5] // original pseq
[0.25,1.25,0.5,0.5] ++ [0.5, 0.5, 0.5, 0.5] // first repeat
[0.25,1.25,0.5,0.5, 0.5] ++ [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5] // second repeat

in this case i was thinking to do something like this: Pseq([0.25,1.25,0.5,0.5])++Pseq([0.5,0.5,0.5,0.5], Pseries(1,1,1)) //using Pseries to increase second Pseq repeat value.
but this does not work. and actually i want to inject the first Pseq array with any arbitrary value/array each repeat. sorry if i’m not clear :slight_smile:


#7

Hi Fish, I suspect for a better solution you might need to wait for the more experienced users to see your question (and demonstrate a more practical version). However, I wondered if you might - depending on what else you need doing - use Pdef and Psym. This is a very nice way of playing sequences, which can be changed mid stream. I’m not sure I got the order correct from your answer, but here’s what it could look like.

Load up your Pbinds here. I used your arrays so you can easily see which pattern applies to which.
(
a = [0.25, 1.25, 0.5, 0.5]; // original pseq
b = [0.5, 0.5, 0.5, 0.5]; // first repeat
c = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]; // second repeat

Pdef(\a, Pbind(\instrument, \default,\dur, Pseq(a, 1), \freq, 400));
Pdef(\b, Pbind(\instrument, \default,\dur, Pseq(b, 1), \freq, 400));
Pdef(\c, Pbind(\instrument, \default,\dur, Pseq(c, 1), \freq, 400));
);

Then play the whole thing here using a Pdef and Psym. Psym reads symbols, so in a way this works like a sequencer, just type in the symbol of your Pdef as needed. You can update this ‘live’, but it will start the sequence again.

Pdef(\play, Psym(Pseq("aabac", inf).trace)).play;  

Lastly, you said you wanted to add a random/arbitrary value/array in. If so I guess you could follow the same principle as above and make a new Pdef(\f) with Prand, Pwhite, or whatever?

Hope that helps.


#8

Hi,

you are touching a subtle topic: patterns and repetitions.
The difficult thing is that it crosses the boundaries between Patterns and Streams and this is difficult to grasp, partially it’s not sufficiently documented as well. E.g. Pn is the Pattern for repeated embedding, its repeat arg is not thought to be a Pattern, but surprisingly it can be a Stream (so also a Pattern made to a Stream) and then we are already there (instead of ‘asStream’ you can write ‘iter’):

Pseq([0.25, 1.25, Pn(0.5, Pseq([3, 5, 7], inf).iter)], inf).iter.nextN(30)

Pbind(
	\dur, Pseq([0.25, 1.25, Pn(0.5, Pseq([3, 5, 7], inf).iter)], inf) / 2,
	\midinote, Pseq([60, 55, 62, 65, 67], inf)
).play

Daniel


#9

thanks guys. @dkmayer this is what i am after! i’m back from a SC hiatus and remember being stuck on problems like this and indeed having difficulty grasping the difference between streams and patterns. another question, how would you reverse the process? like removing some elements from the array each repeat?


#10

Then just define it in the Pattern which defines the number of repetitions

Pn(0.5, Pseq([7,5,3], inf).iter)

or similar


#11

thanks! should have found that myself hehe


#12

When things become more complicated, why not return to more traditionnal programming ?

(
// Example of "growing" and "shrinking" array
// Not the most clever programming, but it works...
var values = [1, 2, 3, 4, 5, 6, 7, 8];
// (It's easier for me to count from 1 ...)
var value,
    pos = 1, // actual position in array
    num = 1, // number of values to play in the array
    max = values.size, // size of the array
   sign = 1;

var myFunc = {
	pos.postln;
	value = values[pos-1];

	pos = pos + 1;
	if(pos > num, { pos = 1; num = num + sign; });
	if(num > max, { num = num - 2; pos = 1; sign = -1;});
	if(num < 2, {if(sign == -1, { num = 1; pos = 1; sign = 1})});

	value - 1;
};

Pbind(\degree, Pfunc(myFunc), \dur, 0.25).play;

)

#13

Here’s another potential solution, a good balance of Pattern-class modularity and functional-code clarity:

Pdefn(\base, { Pseq([0.25,1.25,0.5,0.5]).postln });
Pdefn(\variation, {
	[
		Pseq([0.5, 0.5, 0.5, 0.5]),
		Pseq([0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]),
		Pn(0.5, rrand(4, 10)) // just repeat a random number of times
	].choose.postln
});
Pdefn(\repeater, Pseq([
	Pdefn(\base),
	Pdefn(\variation)
], inf));

Pdef(\repeater, Pbind(
	\degree, Pdefn(\repeater).trace
)).play

#14

And because I think the ORIGINAL question also had something to do with modifying patterns at runtime - there’s a somewhat compatible solution to this also:

~list = TextView(bounds:400@80)
	.font_(Font(size:18))
	.value_("")
	.keyUpAction_({
		try {
            Pdefn(\variation, "[%]".format(~list.string).interpret)
		}
	})
	.front;
Pdefn(\base, { Pseq([0.25,1.25,0.5,0.5]).postln });
Pdefn(\variation, Pseq([0]);
Pdefn(\repeater, Pseq([
	Pdefn(\base),
	Pdefn(\variation)
], inf));

Pdef(\repeater, Pbind(
	\dur, 0.25,
	\degree, Pdefn(\repeater).trace
)).play