# Pstretch vs Pstretchp

Although undocumented, it’s pretty easy to figure out the basic usage of `Pstretch`

``````q = Pbind(*[dur: 0.01, freq: 550 + Pwhite(0, 50)])
p = Pstretch(10, q).play
p.stop
``````

Also, from the source the stretch value (first arg) can be a pattern or stream too.

``````p = Pstretch(Pwhite(1, 10), q).play
p.stop
``````

And Pstretch will exit its `embedInStream` if either stream becomes nil.

``````p = Pstretch(Pwhite(1, 10, 20), q).play // stops itself

q = Pbind(*[dur: 0.01, freq: 550 + Pwhite(0, 50, 5)])
p = Pstretch(Pwhite(1, 10, 20), q).play // stops even sooner
``````

I’m a little miffed what `Pstretchp` is supposed to add to that… The latter class uses two nested loops (but completely ignores any cleanups). So it looks like it will keep playing after the second stream returns nil. There are not many ways to generate something like that but here’s one

``````r = Pseq([1, nil], 3).asStream
r.nextN(7) // -> [ 1, nil, 1, nil, 1, nil, nil ]
``````

So, putting that to use here:

``````q = Pbind(*[dur: 0.01, freq: 550 + Pseq([Pwhite(0, 50, 5), nil], 3)])
q.play // only one burst

p = Pstretch(10, q).play // one stretched burst

p = Pstretchp(10, q).play // keeps going (forever) past q nils
p.stop

p = Pstretchp(Pseries(10, -2, 5), q).play // 5 linked bursts, decreasing stretch factor
``````

Following the model of Paddp, Pmulp etc., its intended purpose is to repeat the source pattern once for every value from the numeric pattern. That is: a Cartesian product between the two streams. So I think it would be quite odd if it didn’t keep going.

I was going to say that’s a legit bug, but I’m not sure that it is, thinking further. Pstretch needs its own cleanup because it might cause the source stream to terminate early. But Pstretchp will not terminate its source early – if Pstretchp ends under its own power, it must be at a boundary between one loop through the source pattern and the next – in which case, the source pattern already executed its own cleanup and there’s no need for Pstretchp to do it.

If there’s a reproducer where this doesn’t happen, then yes, it would be a bug. But I think it would be hard to find one.

hjh

1 Like