Other than Pseq(Array.rand(), inf) [MIDIOut]

I’ve been trying to figure out how to yield sequences of repeating patterns that repeat an arbitrary (pseudo-random, or whatever pattern might be applied) number of times and change—in real-time (or, ‘generatively’)—not only pitch content but also length, tempo, legato, etc. values of sequence without having to re-evaluate the line of code. For now, I’ve been writing parameters like this, e.g:

Pdefn(\notes, Pseq(Array.rand(rand(12), 25, 81), inf))

and a Pdefn for tempo might be written like this, in the same line:

Pdefn(\tempo, Pseq(Array.rand(1, 0.33, 18.6), inf))

but to change the sequence length, tempo, and pitch content I have to arbitrarily trigger it via cmd+return. I’ve been writing it this way for each parameter so that the re-evaluations are synchronized, i.e. \notes changes at the same time as tempo, \legato, \amp, etc.

Is there any way to write this—in a more efficient manner—to yield the desired result? I’m using Pdefn because I want to be able to modify lines and re-evaluate them in real-time. Anyway, I’ve been trying to figure this out for the past several days and am coming up nil, probably because I’m not looking in the right place in the help-guide or something. Pif seems like it might be what I’m looking for, though I’m not sure I understand it. Thanks in advance.

[fwiw, I’m using MIDIOut to an external AU, no SynthDef.]

I’m also desperate to figure out how to apply patterns to \program changes w/in the Pbind, but this seems to be a similar issue as using pitch bend in a Pbind.

Take a look at Pn(). It’s for repeating patterns. The syntax is Pn(pattern, repeats)

The latter demand sounds like a job for Pbindef.
Concerning the repetition question there are many variants how repetition can be build in via Patterns and they slightly differ. Besides Pn Pstutter is also a useful repetition pattern, it can be appplied to value and event patterns. Pn + Plazy is also often very handy.

1 Like

Thank you for your reply! Regarding Pbindef, would this replace Pbind? Or would it replace Pdefn? Here’s an example of how I’ve been writing it thus far:

Pdefn(\legato, Pseq(Array.rand(1, 0.1, 1), inf)); Pdefn(\notes, Pn(Plazy({Pseq((55..66).rand, 11.rand)}, 1))); Pdefn(\tempo, 9); Pdefn(\amp, Pseq(Array.rand(1, 0.5, 1), inf)); a.stop; a = Pbind(\type, \midi, \chan, 1, \midicmd, \noteOn, \midiout, m, \tempo, Pdefn(\tempo), \midinote, Pdefn(\notes), \amp, Pdefn(\amp), \legato, Pdefn(\legato)).trace.play;

Regarding Pn + Plazy: as you can see I’ve only been able to figure out how to yield a random pattern of fixed length—seemingly determined by the specified note range?—that repeats anywhere between 0 and 11 times before changing the note order of the previous pattern. I’m seeking to not only randomize the amount of pattern repetitions, but also its size. For example, the pattern size could be 7 notes and repeat 4 times, the next evaluation would yield a 2 note pattern that repeats 9 times, and so on.

It would replace Pbind and it would save writing Pdefn repeatedly, see its help file and, btw, the Pattern Guide in the SC help:

http://doc.sccode.org/Tutorials/A-Practical-Guide/PG_01_Introduction.html

Concerning variable length you could write like this:

TempoClock.default.tempo = 1;

p = Pbindef(\test,
	\dur, 0.12,
	\midinote, Pn(Plazy { Pseq((50..90).scramble.keep(rrand(3, 10)), rrand(2, 5)) }).trace
).play	
)


// live replacement

Pbindef(\test, Pn(Plazy { Pseq((60..90).scramble.keep(rrand(2, 5)), rrand(2, 3)) })
	
Pbindef(\test).stop

Another point: better do not set tempo within Pbind/Pbindef. It changes the default TempoClock, so if you go on playing the next time, the tempo would be different. You can instead pass a dedicated TempoClock with different tempo as arg to Pattern::play.

A formal thing: if you post code via the forum, please enclose it with 3 backticks, that way it is reasonably readable in the web interface.

1 Like

Thanks so much, this was extremely helpful. I’m almost there: how might I synchronize the re-evaluation of the \degree pattern with a \dur? In other words, each time the \degree pattern size changes, the duration at which it plays changes? I tried \dur, Pkey(\degree) though that just caused a crash, for reasons that are probably obvious. I’m having a bit of trouble understanding how what is demonstrated in the Data Sharing section could be applied here, though maybe I’m looking in the wrong place. (Forgive me and thank you for your patience, I’m clearl a novice and have only been doing anything in SC for the past few weeks or so. I’ve tried to do as much reading as possible in that span of time.) Many thanks again.

Also, do you have any suggestions for applying a Pattern to MIDI program changes inside the Pbindef? Or would I need to write one separately from that which contains \noteOn as its only midicmd?

Plazy can also produce Event Patterns, so you can do

(
p = Pn(Plazy {
	Pbindef(\test,
		\dur, rrand(0.07, 0.25),
		\midinote, Pseq((50..90).scramble.keep(rrand(3, 5)), rrand(2, 5)) 
	)
}, 20).play	
)

Another option would be this, but a bit more clumsy:

(
p = Pbindef(\test,
	\seqLength, Pwhite(2, 4),
	\seqRep, Pwhite(2, 5),
	// take over values from current Event in the Plazy
	\dur, Pn(Plazy { |e| Pn(rrand(0.07, 0.25), e[\seqLength] * e[\seqRep]) }),
	\midinote, Pn(Plazy { |e| Pseq((50..90).scramble.keep(e[\seqLength]), e[\seqRep]) })
).play	
)

In principle yes. Sorry, no time atm to work out an example, but the scheme could be this:

~template = Pbind(...);

~noteOn = Pbind(
    \type, \midi,
    \midicmd, \noteOn
	...
);

~prgChange = Pbind(
    \type, \midi,
    \midicmd, \program
	...
)

Ppar([~noteOn <> ~template, ~prgChange <> ~template])

<> stands for Pchain.

See these two threads for related discussions:

1 Like

hopefully last question, you’ve already been extraordinarily helpful: I’m unsure what exactly would be specified in this Pbind? The rest of the scheme makes sense.

Probably mainly the durations, maybe other data that can be used to affect both prgchange and noteOn data. It’s important to note that with <> the first applies to the second, so the first is the latter.

been having a tough time with debugging this over the past couple days. everything registers except program changes? here’s what I have right now:

(
~template = Pbind(\dur, rrand(0.035, 0.21), \midiout, m, \chan, 1);

~noteOn = Pn(Plazy{Pbind(\type, \midi, \midinote, Pseq((30..90).scramble.keep(rrand(1, 25)), rrand(2, 15)))}, inf);

~prgChange = Pn(Plazy{Pbind(\test, \midi, \program, rrand(1, 15))});

Ppar([~noteOn <> ~template, ~prgChange <> ~template]).trace.play;
)

also for reasons I can’t quite figure out—again, relative novice, apologies—code evaluation causes a hung note albeit strangely coming from the server (which has not been booted). nothing excelt “Kill All Servers” gets rid of it.

Your third pattern includes a typo, should be ‘type’ instead of ‘test’. BTW a shorter writing would be defining the type in the template:

(
~template = Pbind(\dur, 0.3, \midiout, m, \chan, 1, \type, \midi);

~noteOn = Pn(Plazy{Pbind(\midinote, Pseq((30..90).scramble.keep(rrand(1, 25)), rrand(2, 15)))}, inf);

~prgChange = Pn(Plazy{Pbind(\program, rrand(1, 15))});

Ppar([~noteOn <> ~template, ~prgChange <> ~template]).trace.play;
)

Also please see this parallel thread with the almost same problem, with a dedicated event type you could write it even more simple. Though I see, redefining Patterns via Event types is a bit advanced.

1 Like