12. Routine/.do

12. Routine

Routine은 function으로 실행을 멈추고 (중간으로 돌아가) 다시 계속할수 있게 해준다.

구문 : (Routine({function})

메세지 yielf, wait이 있는데 초단위의 숫자(SystemClock사용시)나 비트단위(TempoClock사용시)의 숫자를 요구한다.
//——————————————
//ex1)
(
        r = Routine({
                        var counter = 0;
                        { counter = counter + 1;
                          counter.postln;
                          1.yield;//1.wait
                          }.loop;//looo의 사용은 loop가 계속적으로 지속되도록 하기 위함
                          })
)//이렇게 루틴을 만든후 아래와 같이 실행

r.play(SystemClock)
r.stop
r.reset.play(SystemClock)

//ex2)Karplus routine(11장에서 사용한 Karplus사용)
(
SynthDef(“Karplus”,
{
        arg midiPitch = 69, decayTime = 2.0;
        var burstEnv, att = 0, dec = 0.001, signalOut, delayTime;
        delayTime = midiPitch.midicps.reciprocal;
        burstEnv = EnvGen.kr(Env.perc(att, dec));
        signalOut = CombL.ar(WhiteNoise.ar(burstEnv), delayTime, delayTime, decayTime);
        DetectSilence.ar(signalOut, doneAction: 2);
        Out.ar(0,signalOut);
}).load(s)
)

(
r = Routine({
        {        Synth(“Karplus”,[midiPitch, rrand(50,90), delayTime,rrand(2.0,3)]);
        [0.5,0.75,1].choose.wait;
        }.loop;
}).play(SysyemClock)
)

//ex3) Sine Grain
(
SynthDef(“SineGrain”, {
                |out = 0, freq, amp = 1, decay = 0.01|
                var signal;
        
                signal = SinOsc.ar(freq, mul:amp) *
                                EnvGen.kr(Env.perc(0.001,decay,0.2),1,doneAction:2);
                signal = Pan2.ar(signal, Rand(-1.0,1.0));//Rand geberates 1 randon value when SunthDef starts playing
                Out.ar(out,signal)
                }).send(s)
)        
//2가지 방법으로 SineGrain에 메세지를 보내보자.
//1.s_new, synthname, ID, add Action(0 is add to head). Target ( Group)ID
//if ID in s_new message is -1, the server generates an ID and you cannot access it by number
//This is convenient if SynthDef turns off and deallocates the synth.

(
r = Routine({
        { s.sendMsg(s_new, SineGrain, -1,0,0,freq,rrand(5000.0,5100));
                rrand(0.001,0.1).wait;
        }.loop
        }).play(SystemClock)
)
//using Synth
(
r = Routine({
                {Synth(SineGrain,[freq,rrand(1000.0,5100),decay,rrand(0.1,1),amp,rrand(0.05,0.1)]);
                rrand(0.001,0.1).wait;
                }.loop
        }).play(SystemClock)
)

//——————————————
number.do({function});
10.do({|i = 0| i.postln;})

위 구문은 0~10까지를 프린트.
do는 루틴을 여러개 만들때 유용하게 사용된다. 아래는 SineGrain의 레이어를 여러개 만든다.

(
20.do({Routine({
        { Synth(SineGrain,[freq,rrand(1000.0,5100),decay,rrand(0.1,1),amp,rrand(0.05,0.1)]);
                rrand(0.001,0.1).wait;
        }.loop
        }).play(SystemClock)
        })
)

array.do({function});
array의 값은 argument에 할당된다.
[1,3,5].do ({|i| i.postln})
//다음은 루틴의 array를 만든다.
(
a = { Routine({
        { Synth(SineGrain,[freq, rrand(1000.0,5100), decay, rrand(0.1,1), amp, rrand(0.05,0.1)]);
        rrand(0.001,0.1).wait}.loop
        })
        } ! 5;
)
do를 사용하여 play and stop
a.do({|i| i.play(SystemClock)})
a.do({|i| i.stop})
a.do({|i| i.reset.play(SystemClock)})
//——————————————
http://csound.x-y.net
Ji Youn Kang,
Csound Max Community

11. SynthDef

11. Synth Def

SynthDef는 patch에 이름을 만들어 다른곳에서 불릴수 있도록 한다. 서버로 불려지면 SynthDef 는 메세지를 받아 값을 변경시킬수 있다.

-Basic Format:
SynthDef(“name”, {Out.ar(busNumber,Ugen});

“name”은 /name이렇게 쓰여질수도 있다.

(
SynthDef(“onesine”,{|freq = 440, bus = 0|
                Out.ar(bus, SinOsc.ar(freq,0,0.1));
                }).load(s);//file을 저장하고 서버로 보낸다.
)

-SynthDef은 또한 파일로 저장되어 다음에 다시 사용될 수 있다.
Default directory는 synthdefs/이다.

다음은 명령메세지들이다.

writeDefFile (dir) :  file로 쓰기
load(server) : defFile을 쓰고 서버로 보내기 위한 메세지를 보낸다.
send(server) : def를 compile 하고 파일로 쓰지않고 서버로 보낸다.
play(server) : def를 compile 하고 서버로 보내고 하나의 synth를 만든다.

Raw messages는 SynthDef의 새로운 instance를 만들거나 이미 존재하는것의argment값을 바꾸기 위해서 서버로 보내질수 있다.

메세지 정의는 다름을 참고:
[Server-Command-Reference]        

// To create a new instance of a synth
s.sendMsg(“/s_new”, “onesine”, 1000,1,0);

//1000이 ID
//1은 action (0: head로 더해지고 1은 꼬리에 더해지고)
//0은 target  ID (group)

To free node 1000:
s.sendMsg(“/n_free”, 1000);

To change the frequency in node 1000 (which must be active):
s.sendMsg(“/n_set”, 1000,freq,200);
s.sendMsg(“/n_set”, 1000,”freq”,500);

//*Note : freq와 “freq” 둘다 위 메세지에 사용되었다.

여러개의 nodes만들기
        s.sendMsg(“/s_new”, “onesine”, 1000,1,0,freq,100);
        s.sendMsg(“/s_new”, “onesine”, 1001,1,0,freq,230);
        s.sendMsg(“/s_new”, “onesine”, 1002,1,0,freq,470);
        s.sendMsg(“/s_new”, “onesine”, 1003,1,0,freq,1000);

To free these nodes:

s.sendMsg(“/n_free”, 1000);
s.sendMsg(“/n_free”, 1001);
s.sendMsg(“/n_free”, 1002);
s.sendMsg(“/n_free”, 1003);

-또다른 SynthDef:

(
SynthDef(“filteredNoise”, {|center = 2000|
        Out.ar(0,Resonz.ar(WhiteNoise.ar(0.5), center, 0.1));
        }).load(s);
)

a = Synth(“filteredNoise”,[center,500]);
b = Synth(“filteredNoise”,[center,1000]);
a.free;
b.free;

To browse available SynthDefs:
(
SynthDescLib.global.read;
SynthDescLib.global.browse;
)

-Karplus-Strong as SynthDef

(
SynthDef(“Karplus”,
{
        arg midiPitch = 69, decayTime = 2.0;
        var burstEnv, att = 0, dec = 0.001, signalOut, delayTime;
        delayTime = midiPitch.midicps.reciprocal;
        burstEnv = EnvGen.kr(Env.perc(att, dec));
        signalOut = CombL.ar(WhiteNoise.ar(burstEnv), delayTime, delayTime, decayTime);
        DetectSilence.ar(signalOut, doneAction: 2);
        Out.ar(0,signalOut);
}).load(s)
)

// note :arg syntax (arg ..  ;   instead of |arg, arg|
// note :the way that Out is used
// DetectSilence – evaluates doneAction when input falls below a certain threshold

Synth(“Karplus”)
Synth(“Karplus”, [midiPitch, 60])   // uses a new node each time

a = Synth(“Karplus”);
a.set(midiPitch, 60);   // synth is turned off before this happens

Synth(“Karplus”, [midiPitch, rrand(50,80), decayTime, 3.0]);
//——————————————
http://csound.x-y.net
Ji Youn Kang,
Csound Max Community

10. Server

Server

language나 다른 application으로부터 commands(OSC)를 받는 synthesis engine
synth server 와 its clients는 아마 같은 machine내에 있거나 network를 사이에 두고 있다.

synthesis definitions (SynthDef) 는 서버에 올려질수 있는것.
서버는 MIDI를 send/receive하는것이 아니고 client가 control messages를 서버에 보내는 것이다.

Server는 nodes (a network)의 tree를 사용하며 그 tree 들은 synths이거나 groups이다.

-Synth : a collection of Unit Generators that run together
-Group : a collection of nodes represented as a linked list
            (each node points to the next one).
      새로운 node는 시작의 head에 더해지거나 list끝에 써진다.
      
SynthDefs를 실행하기위한 명령은 중요하다. (예를들어 reverb unit에 들어가기 위한 signal이라면 반드시 reverb processing 이전에 만들어 져야 한다.). 이 명령은 nodes (head or tail)의 명령과 함께 결정된다.

Audio 또한 SynthDef로 부터 또 다른곳으로, Audio Buffers (an array of 128 channels)와 같은 Audio output device 불려질수 있다.  

Control information 또한 control buses (an array of 4096 buses)와 함께 전달된다.

{SinOsc.ar(440,mul: 0.1)}.play(s); // play and scope produce a synth definition

Synth(“temp__1966342724” : 1001)   // name and node of a synth definition (in post window)
      
이 구문은 다음의 evaluating 에 의해 응답된다.:
Synth(“temp__1966342724”)

**letters a – z 는 ‘global’ variables로 정의되서 결과를 저장시킬수 있다.

a = {SinOsc.ar(440,mul: 0.1)}.play(s);
b = {SinOsc.ar(660,mul: 0.1)}.play(s);
c = {SinOsc.ar(740,mul: 0.1)}.play(s);

a.free;
b.free;
c.free;

//——————————————
http://csound.x-y.net
Ji Youn Kang,
Csound Max Community