Parallel loops inside a Tdef

Dear community,

I’m working with Tdef in order to change several synth control settings on the fly with a single command. For example, I can instantly modify one loop by redefining the Tdef:

(
		Tdef(\test,{
			loop {
				"loop A".postln;
				0.5.wait;
			}
		}).stop.play;
	);
	
	(
		Tdef(\test,{
			loop {
				"loop B".postln;
				0.5.wait;
			}
		}).stop.play;
	)
	

However, I haven’t found a way to run multiple loops in parallel within the same Tdef. Using fork { … } launches independent tasks, but they don’t stop or update when I redefine the Tdef.

(
Tdef(\test,{
	fork{loop {"loop A".postln;0.5.wait}};
	fork{loop {"loop B".postln;0.7.wait}};
}).stop.play;
);

(
Tdef(\test,{
	loop {
		"loop C".postln;
		0.2.wait;
	}
}).stop.play;
)

Is it possible to structure a Tdef so that multiple loops run in parallel, but still stop or get replaced when the Tdef is redefined? I should add that using Pbindef instead of Tdef does not work in this case. Thank you in advance for your suggestions.

Hi,

you’d need something designed for doing parallel scheduling, e.g., Ppar:

(
Pdef(\test,
	Ppar([
		Pbind(
			\type, \rest, 
			\dur, 0.5,
		).trace,
		Pbind(
			\type, \rest, 
			\dur, 0.7
		).trace
	])
).play
)

(
Pdef(\test,
	Pbind(
		\type, \rest, 
		\dur, 0.2,
	).trace
).stop.play
)

A bit more clumsy in this case, though immensely more options exist with Pspawner

(
Pdef(\test,
	Pspawner { |sp|
		sp.par(
			Pbind(
				\type, \rest, 
				\dur, 0.5,
			).trace
		);
		sp.par(
			Pbind(
				\type, \rest, 
				\dur, 0.7
			).trace
		);	
	}
).play
)

(
Pdef(\test,
	Pbind(
		\type, \rest, 
		\dur, 0.2,
	).trace
).stop.play
)

You could also have a look into the classes PLbindef and PLbindefPar from miSCellanous_lib. PLbindefPar provides many shortcuts for partial replacements as well.

With Pspawner, you can use Prout instead of Routine and it will be basically transparently like the original request.

(
p = Pspawner { |sp|
	sp.par(Prout {
		inf.do { |i|
			i.asInteger.postln;
			1.0.wait;
		}
	});
	sp.wait(0.5);
	sp.par(Prout {
		inf.do { |i|
			(i + 1000).asInteger.postln;
			0.875.wait;
		}
	});
}
.play;
)

p.stop;

hjh

A big thank you to both of you, dkmayer and jamshark70, for your suggestions. At first, it seemed to me that patterns were not well suited to address Synths that already contain Demands. But Pdef, wrapping combinations of Prout, Ppar, Pspawner, and Pbind(\type, \set), is really interesting and extremely flexible. So I’m going with this solution instead of Tdef. :pray: