SuperCollider:例程和任务

在开始本课之前,请确保你已载入了上一课的\bleep SynthDef

目前为止,调度一直由为一个特定的时间调度一个函数来达到。为了遍历一个程序不同的阶段,一个具备一定量执行阶段的函数是很有帮助的。通过.value,它并非一次性被全部评估,但能够在每个多阶段中“产出(yield)”它的当前值。

这是一个例程(routine):

(
r=Routine({

1.yield; 

2.yield;

3.yield;

})
)

r.value; //运行此行四次

//另一个更多东西一起走的例子
(
var r;
r = Routine({
		var x;
		x = 1.0.rand;
		2.yield;
		x.yield;
		1000.yield;
		x.yield;
		x = 1.0.rand;
		x.yield;
	});

10.do({ r.value.postln });
)

// a routine can also have side effects

(
r = Routine({
		1.yield;
		Synth(\bleep);
		2.yield;
		1.yield;
		Synth(\bleep);
		1.yield;
	});
)

r.next; //顺便. r.next是一个同义词. r.value或r.next都返回"yield值".
r.next;
r.next;
r.next;

// 现在,我们可以通过在一个确定的Clock上演奏例程来使用它
(
r = Routine({
		0.5.yield;
		Synth(\bleep);
		1.yield;
		0.5.yield;
		Synth(\bleep, [\note, 43]);
		0.5.yield;
	});

SystemClock.sched(0, r);
)

但是,最好的做法常常是仅仅“演奏”例程,同时将它传递入Clock

r.reset;	// 将例程重置为其初始状态
r.play(SystemClock); 

r.reset;
r.play(TempoClock(3));

Yield可以返回任何类型的对象。
然而,一个有意义的时期值需要是一个浮点数或一个整数。
为了清楚的表明我们使用的是一个相对时间,我们用wait替代yield(二者意味是一样的)

TempoClock.default.tempo_(1); //1 bps

(
var r;
r = Routine.new({
	"I just began!".postln;
	1.0.wait;
	"1 second later".postln;
	2.0.wait;
	"finished".postln;
});

r.play; //默认到TempoClock.default;
)

(
var r;
r = Routine.new({
	16.do({ arg i; 

		Synth(\bleep, [ \note, 36+(3*i) ]);
		0.25.yield;  //  yield和wait意味着同样的东西 

	});
});

r.play;
)

inf.do可以用来无限进行;但你你必须细心一些,以不会遗漏掉一些正时间的.wait命令。因为否则的话,循环将变得无限快并且SC将崩溃。

(
var r;
r = Routine.new({
	inf.do({ arg i; 

		Synth(\bleep, [ \note, 36+(3*(i%10)) ]); //added %10 to stop it going up forever
		0.25.wait;   //do not miss me out!

	});
});

r.play;
)

一个任务即一个可以暂停和重新开始的例程。

(
t = Task.new({
		inf.do({ arg i; // 无限循环 (除非从外部停止)
			Synth(\bleep, [\note, 36+(2.3*(i%17))]);
			0.25.wait;
		});
});
)

t.play(TempoClock(1.4)); //开启任务

t.pause;  //暂停

t.resume;  //继续走

有一个特殊的例程捷径也许会有帮助:

{}.fork

这将自动将你的函数转换为一个例程并演奏它;你将Clock作为fork的引数传递给fork

{5.do{"hello".postln; 1.0.wait} }.fork(TempoClock(1))

(
{16.do{arg i; Synth(\bleep, [\note,rrand(48,84) ,\amp, rrand(0.0,0.125)]); 0.125.wait} }.fork(TempoClock(2))
)
Be Sociable, Share!

Leave a Reply

Your email address will not be published. Required fields are marked *