Working my way through the “A practical guide” pattern tutorials, in “Pattern Guide 04: Words to Phrases” I came across the following example:
// Scale segments, in the sequence: up, up, down (repeat)
(
TempoClock.default.tempo = 1;
p = Pbind(
\degree, Pseq([
Pseries({ rrand(0, 7) }, 1, { rrand(4, 8) }), // up (step = 1)
Pseries({ rrand(0, 7) }, 1, { rrand(4, 8) }), // up (step = 1)
Pseries({ rrand(7, 14) }, -1, { rrand(4, 8) }) // down (step = -1)
], inf),
\dur, 0.125
).play;
)
p.stop;
While trying out some variations I turned the fixed step size into a {rrand()} as well. This does not give result I was expecting: a new random step size with every “length” size iteration.
Instead the Pseries returns a BinaryOpFunction.
If I would use a Pattern for the step size, how would it know when to return a new random value?
How could I achieve a Pseries with random step size for each iteration in this setup?
Using a pattern for the step size is the solution.
There are two kinds of pattern inputs:
“first time” inputs: evaluated once when entering the pattern, and not again.
“every time” inputs: evaluated for each next call
In Pseries, start and length are first-time; step is every-time. (start and lengthcouldn’t be every-time.)
“Every time” inputs are converted into streams and the stream is evaluated each time. So patterns will work for every-time inputs. Functions don’t behave like streams, though, unless they are wrapped in Pfunc (or FuncStream, but usually we just use Pfunc). So an every-time input should be something that responds appropriately to asStream: a simple value, or a pattern (or a stream), but not a function.
“First time” inputs shouldn’t be converted into streams, because, if that’s done inside the pattern, then the first-time input would reset whenever entering the pattern. So the pattern just calls value on them. A first-time input should respond appropriately to value: a function, or a stream, but not a pattern.
The catch is: you can’t tell from looking at a pattern’s arguments which inputs are first-time and which are every-time. That’s admittedly a weakness. It can be learned but it’s confusing at first.
In this case how could a step size pattern “know” when the Pseries length, set by the rrand value, is reached to generate a new random step size value for the next Pseries iteration, as to not generate a new step size for every event?