23. Tdef

Tdef task reference definition

superclass: TaskProxy


Tdef는 reference를 task(time pattern)으로 유지시켜서 play되는 동안에 값이 전환될 수 있도록 해줍니다.
이는 old stream이 끝났을때 플래이 되고, 새로운 stream이 결정되고 beat의 단위로 schedule을 주게 됩니다.

Tdef(key)는 instance를 보내며, Tdef(key,pat)은 pattern을 결정하여 instance를 보냅니다. 이는 Pdef와 Ndef와 유사하며 TaskProxy와 비슷합니다. 

-instance message 
 *new(key, obj)
  task 를 key에 따라 global dictionary 에 저장합니다. 
  만약 이미 다른 Tdef가 있다면 이것은 새로운것으로 대체가 됩니다.
  obj 는 function 또는 시간값을 가진 pattern 입니다.
   
 *new(key)
  key에 있는 task로 접근합니다. (만약 아무것도 없으면 default task 가 생성됩니다.)
   
 *default
  a default source, 만약 아무것도 주어지지 았으면 default는 loop 으로 1.0 beat wait time을 무시합니다.
  
 *removeAll 모든 proxies를 제거
 *clear 모든 proxies 를 clear
 
 *all
  모든 저장된 Tdef들을 불러냅니다.
 
 *all_(envir)
  global environment를 set합니다. 
   
 quant_(beats)
  quantisation time 을 beat 의 단위를 가진 정확한 scheduling을 위해 쓰게 해줍니다. 
  [timingOffset, quant] 와 같이 pair로 사용가능합니다.
   
 clear 그 source 를 nil로 set
 
 *defaultQuant_(beats)
  default quantisation 을 new instances (default: 1.0)로 set
  [timingOffset, quant] 와 같이 pair로 사용가능합니다.

 condition_(func)
  새로운것이 삽입되었을때에 pattern이 적용되는곳에 어떤 condition 을 제공 합니다.
  stream value 와 count 가 그 function으로 적용됩니다.
  methods count_(n) 은 count를 n 까지 사용하게 해주며 그때 pattern을 켜줍니다.
 
 reset  
  pattern을 곧바로 켜줍니다. (stuck conditions 이 이로 인해 파괴될 수 있습니다.)


 envir_(event)
  default environment 가 proxy를 위해 제공됩니다. 
  주어진 후에 이것은 routine function의 environment 로 적용됩니다. 
  이것이 처음으로 주어졌을때는 routine pattern 이 재생성됩니다.
 
 set(key, val, key2, val2, …)
  arguments 를 environment에 set해줍니다.
  environment에 아무것도 없으면 주어진 값이 생성되고 routine pattern은 재생성 됩니다.

 endless
  a proxy를 지속적으로 play해주는 Proutine을 보냅니다. 
  이는 nil값을 default값으로 전환시켜 줍니다.(1 s. wait time)
  이는streams을 만들어 새로운 pattern이 삽입될때 까지 기다립니다.


a) stream reference로 사용할 때.
 
 
 embed 는 embedInStream의 축소형
 
 embedInStream(inval)
  stream처럼 stream위에 놓게 합니다.
 
 

 
b) Task로 사용될 때

 play(clock, doReset, quant)
  Pdef를 시작하여 player를 만듭니다.
  여러개의 instances를 재생하기 원하면 .playOnce(clock, doReset, quant)를 사용합니다. 여기서 quant는 [quant, phase]로 pair로 사용가능합니다.
   
 stop
  task를 멈춥니다.
 
 player 
  현재의 task (만약 Tdef이 단순히 다른 stream에서 사용되면 이것은 nil)

 pause / resume / reset / mute / unmute
  등이 적용될 수 있습니다. 
   
 isPlaying 
  Tdef가 현재 사용되고 있으면 true를 보냅니다.
  Tdef 가 play되고 있으면 그것의 stream 을 끝내고, 새로운 function이 적용될 때에 바로 task가 play될 수 있도록 schedule 해줍니다.




a) task player로의 사용.


Tdef(x).play; // 빈 Tdef를 만들고 play합니다. (즉 환경을 먼저 만듭니다.)

Tdef(x, { loop({ “ggggggggggggggggg9999ggg999ggg999gg”.scramble.postln; 0.5.wait; }) });// loop가 0.5초마다 적용되거 ” ” 내에 있는것을 scramble 시켜서 보내는 새로운 instance가 생성되었습니다.


Tdef(x, { loop({ “———////———————-“.scramble.postln; 0.25.wait; }) });//이제 새로운것으로 대체 되었습니다. 
Tdef(x, { loop({ thisThread.seconds.postln; 1.wait; }) });//이제 Thread가 초단위로 나가게 됩니다.
Tdef(x, { loop({ thisThread.seconds.postln; 1.01.wait; }) });//schedule시간을 변경해줍니다.

TempoClock.default.tempo = 2;//비트단위로 변경

Tdef(x, { “the end”.postln });//시간값이 없으니 instance만 보내고 멉춥니다.
Tdef(x, { “one more”.postln });//하나 더 보내봅니다.
Tdef(x, { loop({ “some more”.scramble.postln; 0.25.wait; }) });//다시 시간값을 주니 변합니다. 

TempoClock.default.tempo = 1;//시간단위 변경

Tdef(x).stop; //멈춥니다.
Tdef(x).play;//다시 실행

Tdef(x).clear;//instance를 지워줍니다.




// 소리의 예제

(
//간단한 synthdef를 하나 만들어봅니다.
s.boot;
SynthDef(“pdef_grainlet”, 
 { arg out=0, freq=440, sustain=0.05;
  var env;
  env = EnvGen.kr(Env.perc(0.01, sustain, 0.3), doneAction:2);
  Out.ar(out, SinOsc.ar(freq, 0, env))
 }).store;
)
Tdef(x).play;//Tdef를 x라는 이름으로 했음을 살펴보아주세요~
Server
(
Tdef(x, { 
 loop({
  s.sendMsg(“/s_new”, “pdef_grainlet”, -1,0,0, freq, rrand(600, 640));
  0.1.wait;
 })
})
)//이제 x에 instance를 만들어 줍니다. 서버에 메세지를 보내야겠지요. Synthdef는 늘 서버에 저장되니까요. 그다음 새로운 instance를 만들어 주고(“/s_new”), synth이름을 불러주고 (“pdef_grainlet”), nextNodeID는 nil이니 -1, group 0(RootNode), targetID 0, 그다음 argument값을 random값으로 바꾸어 주었습니다. 

(
Tdef(x, { 
 var x;
 x = Pseries(300, 20, 100).loop.asStream;
 loop({
  s.sendMsg(“/s_new”, “pdef_grainlet”, -1,0,0, freq, x.next);
  0.05.wait;
 })
})
)
//위에는 새로운 패턴을 적용시킨 예제입니다. Pseries로만든 stream을 freq에 적용

(
Tdef(x, { 
 var x;
 x = Plazy({ Pseries(300 + 300.rand, 10 + 30.rand, 10 + 30.rand) }).loop.asStream;
 loop({
  s.sendMsg(“/s_new”, “pdef_grainlet”, -1,0,0, freq, x.next);
  0.05.wait;
 })
})
)
//다음은 Plazy를 사용하여 stream들을 만들어 주었습니다. 
// metronome
Tdef(y, { loop({ s.sendMsg(“/s_new”, “pdef_grainlet”, -1,0,0, freq, 1500); 1.wait; }) }).play;
//여기에 새로운 y란 이름으로 메트로놈을 만들어 주었어요.

// play ending stream once
(
Tdef(x, { 
 var x, dt;
 dt = [0.1, 0.125, 0.05].choose;
 x = Plazy({ Pseries(1300 + 300.rand, 110 + 130.rand, 16) }).asStream;
 x.do({ arg item;
  s.sendMsg(“/s_new”, “pdef_grainlet”, -1,0,0, freq, item.postln);
  dt.wait;
 })
})
)

//다시 x 를 바꾸어 줍니다. dt값은 schedule을 컨트롤 하는데 쓰입니다. 자 여기서 이전의 Plazy는 freq를 컨트롤 하는데 사용되었는데, 여기서는 instance를 여러개 만들어 주기 위해서 사용되었습니다. loop가 없어서 한번의 stream이 사용되고 마쳐집니다. 여기서 item은 Plazy로 생성된 item을 받는것이죠. 값을 확인하고 싶다면 freq, item.postln해보세요.


Tdef(x).stop;
Tdef.removeAll;



b) embed 와 fork: 다른 Tasks / Routines내에 쓰이는 Tdef


(
Tdef(a, { “one”.postln; 1.wait; “two”.postln });
Tdef(c, { var z; z = Synth(default); 0.5.wait; z.release });
r = Task({
 “counting…”.postln;
 2.wait;
 Tdef(a).embed;
 1.wait;
 Tdef(c).embed;
 “done.”.postln;
});
)
//Tdef a는 one출력후 1초 기다리고, 다시 two를 출력하라이고
//Tdef c는 z란 default synth를 만든다음에, 0.5초 기다리고 출력하라고 되어있습니다.
//r은 task를 만들어서 위의 값에 stream을 주었는데요, counting한다음, 2초 기다리고, a를 보내고, 1초 기다리고, c를 보낸다음 done을 보냅니다.
//여기서 중요한 점은 Task안에 Tdef를 불러낼때에 play가 아닌 embed를 사용한다는 것.
r.play; // r 을 출력합니다.

Tdef(c, { var z; z = Synth(default, [freq, 300]); 1.5.wait; z.release }); // change the def
//c를 변경했네요.
r.reset;//reset하고
r.play;//다시 play

// 물론 Tdefs은 다른 Tdef들과도 사용가능합니다.
(
Tdef(b, {
 “counting…”.postln;
 2.wait;
 Tdef(a).embed;
 1.wait;
 Tdef(c).embed;
 “done.”.postln;
});
)
Tdef(b).fork;//fork를 사용한 출력입니다. 

// 만약에 stream하나를 분리해서 thread에 넣고 싶다면 asStream을 사용하면 됩니다.
// .playOnce 도 사용가능합니다. 
(
Routine({
 Tdef(c).fork;
 0.1.wait;
 Tdef(c).fork;
 0.1.wait;
 Tdef(a).fork;

}).play;
)

//Routine과 사용될때 fork가 사용됬다는 접을 기억하세요. 




Tdef as a time pattern

Pdefn을 time값으로 사용하지 않고 Tdef를 사용하는것도 유용합니다.
source를 변경할때에 stream의 값들을 clock으로 synchronized 되도록 유지시켜 줍니다.


(
// synthdef정의해줍니다. 
s.boot;
SynthDef(“pdef_grainlet”, 
 { arg out=0, freq=440, sustain=0.05;
  var env;
  env = EnvGen.kr(Env.perc(0.01, sustain, 0.3), doneAction:2);
  Out.ar(out, SinOsc.ar(freq, 0, env))
 }).store;//저장하고
)




Tdef(z, Pseq([1, 1, 1, 0.5, 0.5], inf));
하나의 Tdef를 먼저 정의해줍니다. 

(
 Pset(instrument, pdef_grainlet, //instrument로 위에 주어진 synthdef를 사용하고
  Ppar([
  Pbind(
  dur, Tdef(z),//duration값을 Tdef에서 불러줍니다.
  note, Pseq([1, 3, 2, 1, 0], inf),//note값을 Pseq으로 새롭게 정의
  x, Pfunc { TempoClock.default.elapsedBeats.postln } // onset times 을 출력해줍니다. 
  ),
  Pbind(
  dur, 4, //이것은 reference beat으로 사용될 값입니다.
  sustain, 0.1,
  note, 8
  )
  ])
 ).play(quant:1);
)


Tdef(z, Prand([1, 1, 0.23, 0.5, 0.5], inf)); //time pattern을 변경하기가 이리 쉽습니다.
Tdef(z, Pseq([1, 1, 1, 1], inf)); // pattern을 synch하도록
Tdef(z, Pseq([1, 1, 1, 0.5, 0.5], inf)); // 다른 순서로 정렬될 가능성이 있습니다. (

  // 이를 피하기 위해서 quant의 값을 설정해 주면 됩니다.

reference : SC3 메뉴얼





Leave a Comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed.