Loop, iterations and routines (newbie question)

For a sound installation, I’m making an infinite loop made of successive sequences (named here “episodes”) which are Routines.

I would like that after 2 iterations of the entire loop, episode 2a (for instance) is replaced by episode 2b, then becomes 2a again at the next iteration (in my example below, I try to do something a bit likewise with wchoose).
Is there a way to do so?

2nd question: in case I have to use wchoose, how can I link the following .stop to the previously chosen episode? I guess with some kind of Pkey logic?

(
Routine.new{({
~episode1.play;
150.wait;
[~episode2a, ~episode2b].wchoose([0.8, 0.2]).play;
~episode1.stop;
150.wait;
~episode3.play;
~episode2a.stop;
150.wait;
~episode4.play;
~episode3.stop;
150.wait;
}).loop;
}.play;
)

Using patterns is very handy for this case, change it into stream and call .next on it.

No need for Pkey since you are not inside a pattern, you can use local variables.

(
Routine.new{
	var current;
	var episode_seq = Pseq([
		~episode2a,
		~episode2b,
	],inf).asStream;
	({
		~episode1.play;
		150.wait;
		current = episode_seq.next;
		current.play;
		~episode1.stop;
		150.wait;
		~episode3.play;
		current.stop;
		150.wait;
		~episode4.play;
		~episode3.stop;
		150.wait;
	}).loop;
}.play;
)
1 Like

Be careful about this – Pseq doesn’t return the items in the array; it embeds them. I believe next on this stream will return not the ~episode2a routine, but rather, values yielded from that routine in succession.

A workaround would be to wrap the Routines in sub-arrays, and unpack them in the main routine. I’m not at the computer so it’s inconvenient to write an example right now. (I believe – memory may be faulty here – that you can’t use Ref for this because embedding a Ref in a stream embeds its value, which is exactly what we want to prevent.)

hjh

2 Likes

Thank you, @hemiketal! Sadly your solution doesn’t work (error message below in the post window).
Anyway, asStream seems a pretty good idea…

ERROR: Message ‘play’ not understood.
RECEIVER:
Integer 30
ARGS:
PATH: F:/Christophe/Documents/SuperCollider/tablemoving/composition1.scd
CALL STACK:
DoesNotUnderstandError:reportError
arg this =
Nil:handleError
arg this = nil
arg error =
Thread:handleError
arg this =
arg error =
Thread:handleError
arg this =
arg error =
Object:throw
arg this =
Object:doesNotUnderstand
arg this = 30
arg selector = ‘play’
arg args = [*0]
< closed FunctionDef >
var current = 30
var episode_seq =
Routine:prStart
arg this =
arg inval = 67.4729846
^^ The preceding error dump is for ERROR: Message ‘play’ not understood.
RECEIVER: 30

This is exactly what I said – a Pseq of routines will not yield the routines as objects. It will yield the values produced by those routines.

This is to be expected: What is the expected return value of Pseq([Pseries(1, 1, 10)]).asStream.next? For the earlier suggestion to work, the return value would have to be the Pseries object. The actual value will be 1, because Pseq embeds the Pseries into the active stream. Routines are similarly embedded.

So the Pseq needs to be written with something to prevent embedding. As I noted before, I believe a Ref won’t do it. An array will:

	var episode_seq = Pseq([
		[~episode2a],
		[~episode2b],
	], inf).collect { |yielded| yielded.unbubble }.asStream;

hjh

1 Like

Thank you so much @jamshark70 ! It works fine. I’m not familiar with arrayed collections. Still so much to learn…

Oops, actually, current.play works, but current.stop doesn’t :disappointed_relieved:

http://doc.sccode.org/Tutorials/A-Practical-Guide/PG_03_What_Is_Pbind.html#Event,%20.play%20and%20event%20prototypes

When a pattern is played, an object called EventStreamPlayer is created. This object reads out the events one by one from the pattern’s stream (using a given event prototype as the base), and calls play on each. The 'delta' value in the event determines how many beats to wait until the next event. Play continues until the pattern stops producing events, or you call .stop on the EventStreamPlayer. (Note that calling .stop on the pattern does nothing. Patterns are stateless and cannot play or stop by themselves.)

You need to save the result of current.play on another variable, and call stop on the second variable.

hjh

1 Like

Thank you again, that’s very helpful. I think I have this problem in other parts of my code.