Is Pmono resume supposed to fail?

p = Pmono.new(\default, \dur, 5, \amp, 0.8, \degree, Pseq([1,2])).play
p.pause // hit before it finishes..
p.resume // FAILURE IN SERVER /n_set Node XXXX not found

Is this the intended semantics of Pmono? Clearly what should happen on pause/resume is not spelled out in the documentation…

PmonoArtic behaves similarly if you hit it with a pause during a note with legato=1, but manages to resume from the next “articulated” note (legato < 1).

I see there’s a p.canPause which is always false for Pmono, always true for Pbind, and for PmonoArtic is true while playing legato<1 notes and false otherwise. I guess you’re supposed to check this flag first before calling p.pause, which in itself seems to implement no such check… I think the flag might have better been called canResume since you can always pause, it just won’t resume properly when that flag is false…

IMO pause and resume should be removed. They are only synonyms for play and stop and (as we see here) add nothing except confusion.

Which leaves the question of Pmono(Artic) recovering from a node that has been freed. I think I see how to fix it but I’m not at the computer now. Soon, probably today.

hjh

Fix proposed: https://github.com/supercollider/supercollider/pull/4787

It will probably have to wait for a little while – the next release (3.11) is already in beta, and standard practice is not to introduce changes during a beta cycle (except to fix regression bugs). This is not a regression bug because it was broken in older versions too.

But you could grab the code changes and stick them in by yourself.

hjh

2 Likes

Although I’m probably veering off topic here, speaking of play/pause/resume/stop semantics… Pbind and Pdef are alas not interchangeable in this respect (as newbie might expect)

p = Pbind(\instrument, \default, \dur, 1, \amp, 0.8, \degree, Pseq([1,4,7], inf)).play

fork { p.pause; 1.5.wait; p.play } // resumes after pause on the next note
fork { p.pause; 1.5.wait; p.play(doReset: true) } // obviously this restarts/resets
fork { p.stop; 1.5.wait; p.play } // stop behaves like pause

p.stop

p = Pdef(\meh, Pbind(\instrument, \default, \dur, 1, \amp, 0.8, \degree, Pseq([1,4,7], inf))).play

fork { p.pause; 1.5.wait; p.play } // restarts/resets the stream on play
fork { p.pause; 1.5.wait; p.play(doReset: false) } // passing doReset:false has no effect
fork { p.pause; 1.5.wait; p.resume } // behaves like Pbind's play, i.e. resumes next note
fork { p.stop; 1.5.wait; p.resume } // p.stop nils p.player, so resume is a no-op here
fork { p.stop; 1.5.wait; p.play } // same as pause...play as seen from the outside

A somewhat oversimplified answer might be that Pbind is a pattern, while Pdef is like a pattern (but different in some respects).

The similarity leads to an assumption that Pdef is also a pattern… but it isn’t. It’s a named wrapper for an event pattern proxy. The predominant behavior for Pdef comes from the proxy-ness, not the pattern-ness.

I don’t use Pdef extensively, so I’m not intimately familiar with the fine print of its stop/start behavior. So I can’t answer whether the results you’re reporting are expected or not.

hjh