Pbind using a Pseries with random step size

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?

My brain is running in circles…
Thanks
David

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 length couldn’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.

hjh

Thank you for the explanation.

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?

dvd

Ah, I didn’t quite understand that part.

I’d do this: Pn(Plazy { Pseries( ... random start ..., ... random step..., ... length ...) }, inf).

In that formulation, the Pseries inputs should be simple numbers, not patterns or functions.

hjh

Thanks a lot, those are the missing pattern puzzle pieces.
I should read more before straying too far off of the tutorial path.
dvd

Nah – this one is just a bit tricky. I’m not sure you would have found this in the help.

It’s a good question.

hjh