Just in Time (기초반 2) 


신스를 만드는 방법 두가지
1) function.play
{SinOsc.ar !2}.play // 실행시키면
//post창에 신스가 하나 생겼음을 나타난다.

우리가 function.play로 신스를 만들라고 요청하면
서버(신스 만드는 공장)는 만든다

방금 만든 신스는 뭘까...
스팸깡통처럼 생긴 신스가 있다고 해보자.
한번 생기면 밖에서 조절할 수 있는 단추도 없는...
하물며 끄는 단추도 없다...

변수에 저장하면 끄거나 할 수 있다.
x={SinOsc.ar!2}.play; 
x.run(false)
x.run(true)
x.free
x.run(true)

x.release(2)//느리게 끄거나

이 신스에 단추와 노브를 달아서 소리 높낮이, 크기를 조절하고 싶으면 매개변수(argument)를 
넣어서 만들어 달라고 해야한다.
x={|frequency=3, amp=0.2|	SinOsc.ar(frequency*100,0,amp)!2}.play

x.set(\frequency,5, \amp, 1 )
x.set(\frequency,3, \amp, 0.1 )

x.release(2)

요약) {SinOsc.ar}.play  라는 것은 "소리를 내주세요"가 아니라 신스를 만들라고 신스공장(서버)에 주문하는 것입니다.
밖에서 조절하고 싶으면 argument를 넣어주어야 합니다.
아규먼트는 set 메시지로 정해줍니다.

2) Synth.new
Synth.new(\default,[freq: 900])//new는 생략가능
SynthDef라는 설계도가 신스공장에 있기 때문에 모델명(신스이름)만 불러주면 바로 만들어줍니다.

많이 재사용되는 신스는 신스데프로 정의해 놓고 쓰면 편리합니다. 본질적으로 1번 방법(function.play)과 같습니다.

===========

x={|nopi=440,kugi=0.05| LFSaw.ar(nopi,0,kugi)!2}.play;
x.free;
크기에 LFO를 걸어보자

x={|nopi=440,kugi =0.1|                                  LFSaw.ar(nopi,0,SinOsc.ar(1,0,kugi))!2}.play;
	
x.set(\nopi,1000)
x.set(\nopi,1100)
x.set(\nopi,1200)
x.set(\kugi,0.01)
x.set(\kugi,0.2)
이렇게 해서 만들어진 신스로는 크기에 걸린 lfo의 크기를 바꾸는 볼륨은 있어도 그 파형을 바꿀 수 없다.
스팸캔 같이 생긴 박스에 볼륨 두개... 하나는 높이, 다른하나는 크기를 바꿀 수 있다.

x={|nopi=440,kugi=0.1| 
LFSaw.ar(nopi,0,kugi)!2}.play;
실행하면 에러다. 아규먼트에 오실레이터를 사용할 수 없다.

요점 : {SinOsc.ar}.play는 서버에게 하나의 신스를 만들어달라는 방법중에 하나이다.
위의 신스는 아무런 단추없어서 밖에서는 조절할 수 없다.
밖에서 조절하려면 arg를 달아야한다.
arg를 달아서 외부에서 조종해도 박스내부의 배선은 바꿀 수 없다.

굳이 하려면 이렇게 해야 하는데...
1) Bus로 여러 신스를 연결하여 컨트롤
Bus는 오디오신호나 컨트롤신호를 날라다 주는 것... 일단 전선으로 생각하시길...
s.meter
y = { Out.kr(10, SinOsc.ar(1)*400)}.play
y = { Out.kr(11, LFNoise0.ar(4)*400)}.play
y = { Out.kr(12, LFSaw.ar(1)*400)}.play
y = { Out.kr(13, LFTri.ar(1)*400)}.play
y.free
x = {  | inputBus=10 |  LFSaw.ar(In.kr(inputBus))/10!2}.play

x.set(\inputBus,10)
x.set(\inputBus,11)
x.set(\inputBus,12)
x.set(\inputBus,13)

2) 보다 빠르고 다이나믹하게 하려면 NodeProxy를 사용한다.(Just-in-time library)
 Proxy는 대리인이라는 실제 존재하지 않는 것을 사용하기위해 미리 자리 맡음하는 개념이다.

 제대로 공부하려면 꽤 양이 많지만 간단히 사용하여 코딩의 효율성을 높여보자.
 
 NodeProxy를 쉽게 사용하려면 ProxySpace로 들어가야한다.
 
 그전에 먼저 변수의 종류에 대해서 알아보자
 전역변수 : a, b, c, d,....
 로칼변수: var source...
 환경변수 : ~out (전역변수처럼 행동한다.)

 currentEnvironment.postln; // anEnvironment
~x; // access the enironment: there is nothing stored: nil
~x = 9; // store something
~x; 	// now 9 is stored
~x=~x + 100; // calculate with it
 currentEnvironment.postln; // anEnvironment

 p = ProxySpace.push(s)// proxyspace로 들어간다.
               p.pop // 나올때는 pop
~out // ~를 붙이면 기존에는 환경변수가 되었으나 ProxySpace로 가면 NodeProxy로 인식된다.
s.meter

~o.play
~o = {Pulse.ar([500,501])}

~o={LFSaw.ar(~f)*0.1}
~f={LFSaw.kr(1/5)*1199}
p.fadeTime =1
~o.release

================ NodeProxy는 여러개의 오브젝트를 동시에 표현할 수도 있다.
~z.play
~z[0..3] = [ {SinOsc.ar(220) * 0.1 },
 { SinOsc.ar(220*2) * 0.08 }, 
 { SinOsc.ar(220*3) * 0.08 }, 
 { SinOsc.ar(220*4) * 0.04 }];

~z.stop
~z.play
~z.pause
~z.resume

~z[0]=nil
~z[1]=nil
~z[2]=nil
~z[3]=nil
~z=nil
z.play
================시간 맞추기
~x.play
~y.play

~x={Pulse.ar(2)*SinOsc.ar(440)/10}
~y={Pulse.ar(3)*SinOsc.ar(880)/10}
==== 안맞아 시간이...
~x.stop;~y.stop
~x.clock = TempoClock.default; ~x.quant = 1.0;
~y.clock = TempoClock.default; ~y.quant = 1.0;
위 실행후 다시하면 맞아...
//p.clock = TempoClock.default; p.quant = 1.0; 이걸실행하면 전체 space에서 맞춰진다... 시간이...
p.clear; // 모두지우기.

//======= offset을 줄수도 잇다 [quant,offset]
~z.play; ~y.play;
~z = { Ringz.ar(Impulse.ar(2), exprand(300, 3400 ! 2), 0.08).dup * 0.2 };
~y.quant = [1, 0.3]; // offset of 0.3, quant of 1.0
~y = { Ringz.ar(Impulse.ar(1), 600, 0.05).dup };
~y.quant = [2, 1/3]; // offset of 1/3, quant of 2.0
~y = { Ringz.ar(Impulse.ar(0.5), 600, 0.05).dup };
//==================================본인자체를 참조하기
~a.play// 
~a = { SinOsc.ar(~a.ar * 700 * 10+ [100, 102]*~c, 0, 0.1) };
~c=1
~c ={MouseX.kr(0.1, 10.10)}
~m={LFSaw.ar(0.1,mul:3.3).round(0.5)+(SinOsc.ar(0.003)*7)}
~a= { SinOsc.ar(~a.ar * 6000 * MouseX.kr(1, 2.10) + [100, 104], 0, 0.1) };//기존방법으로는 에러난다.
p.pop