21. Event? (1)

Event

Event는 하나의 Environment로서 Play메세지를 받을 경우에 액션을 취하도록 만들어진 것입니다.
Event는 defaultParentEvent를 제공하는데 이는 다양한 다른 event type 을 정의해주고 각각의 type에 default key.value pairs를 제공해 줍니다.
type 은 type, note의 값에 의해 결정됩니다.

Event 는 다음과 같이 정의되지요

( ).play; // the default note
( freq: 500, pan: -1) .play; // 500 Hz, panned left
( degree: (0..12)).play // a whole tone cluster
Events 와 SynthDefs

SynthDef에서는 하나의 instrument를 정의내려 줍니다. 그 instrument는 ‘Event’에 의해 실행되어 주는 것이지요.
다음의 예제를 보세요.

SynthDef(“pm”, { | out=0, freq=440, amp=0.1, pan=0, gate=1, ratio = 1, index = 1, ar = 0.1, dr = 0.1 |
var z;
z = LPF.ar(
PMOsc.ar(freq, freq * ratio, Linen.kr(gate, ar,index, dr), 0, 0.3),
XLine.kr(Rand(4000,5000), Rand(2500,3200), 1)
) * Linen.kr(gate, 0.01, 0.7, dr, 2);
OffsetOut.ar(out, Pan2.ar(z, pan, amp));
}).store;

(instrument: “pm”).play;
(instrument: “pm”, ratio: 3.42, index: 12, freq: 150, ar: 8, dr: 3, sustain: 10).play;

pm이라는 SynthDef가 정의내려졌고, store에 의해 서버에 보내집니다.
** 서버에 보내진 synthDef를 확인하시려면 Users/Library/ApplicationSupports/SuperCollider3/synthdefs폴더에 저장됩니다. 이를 사용하여 다른곳에서도 SynthDef에 접근 가능한데 참고하세요.
아래 instrument를 사용하여 pm을 연주해 주는것이 event입니다.
Events 와 Patterns
이벤트는 페턴 라이브러리와 함께 적용됩니다. pattern은 다른곳에서 다루어 보도록 하겠습니다.
다음은 몇개의 keys가 패턴에 적용된 예제입니다. 여기서 key들은 stepsPerOctave, note, ctranspose, detune, sustain, dur, db가 사용되었습니다.
(
p = Pbind(*[
stepsPerOctave: Pstep(Pseq((2..12).mirror, inf),12), // 3 – 12 tone e.t. scales
note: Pseq((0..12).mirror, inf),

ctranspose: Pwhite(-0.2, 0.2), // detune up to +-20 cents
detune: Pwhite(-1.0, 1.0), // detune up to 1 Hz
sustain: Prand([0.2, 0.2, 0.2, 4], inf), // notes last 0.2 or 4 seconds
dur: Prand([0.2, 0.2, 0.2, 0.2, 0.2, 0.8], inf), // 1 in 6 chance note lasts 0.8 seconds
db: Pstep( // 4 beat accent structure
Pseq([-15, -25, -20, -25], inf),
0.8
)
]);
p.play
)

Event play method.
Event나 다른 Environment가 use(function)메세지를 받으면, 그 즉시 이는 currentEnvironment가 되며, function을 계산하고, currentEnvironment의 원래 값을 다시 저장합니다.
이렇게 확인합니다.
currentEnvironment.at(keyName)
또는 ~keyName
다른 키값을 설정할때에는
currentEnvironment.put(keyNamem value)
이는 다음과 같습니다.
~keyName = value
여기서 ~keyName은 물론 저장된 키의 값, 위의 예제로 볼것같으면 ~sustain, 또는 ~dur등등이 되겠지요.
‘~Name'(environment)에 대해서는 다음에 다시 깊게 다루도록 하겠습니다.

다음은 Enevt play method를 정의한 예제입니다.
play {
if (parent.isNil) { parent = defaultParentEvent };
this.use { ~play.value };
}

위에 예제를 설명하자면 ~play에 저장되어 있는 값이 없다면 defaultParentEvent를 재생하라는 뜻입니다.

-Reference
SC Help file.


 












.send, .send(s)와 .memStore

SynthDef를 서버에 올리는 두가지 방법이 있습니다.
.send, .send(s)와 .memStore인데 초반에는 send(s)만 사용되었지만 최근 1~2년사이에 .memStore도 함께 사용되고 있는데요
이 차이점을 이야기 해본다면,
흔하게 사용되는 Pbinds의 경우는 send(s)로 서버에 올려질 수 없습니다.

그렇다면 send와 send(s)의 차이는 무엇일까요?
그것은 send(s)는 하나의 서버로, 그리고 send는 활성화 되고있는 모든 서버로 synthDef를보내게 된다는 것입니다.

참고하세요~

28. ListPatterns

ListPatterns

ListPattern은 여러 방법으로 오브젝트의 array를 반복해서 실행하는 방법이다. 모든 ListPatterns은 공통적으로 instance variables list and repeats를 가진다. List variable 은 array로 구성되어 반복적으로 실행되어질 값들이며, repeats variable은 얼마만큼 실행할것인지를 지정해준다. default repetition은 1이다.

대표적인 예로 Pseq가 있다.

(
var a, b;
a = Pseq.new(#[1, 2, 3], 2); // 1, 2, 3을 2번 반복.
b = a.asStream;//stream으로 만들어 줍니다. 
7.do({ b.next.postln; });
)

위를 실행해보면, 총 7번 실행해야 하는데 stream은 6개의 값(1,2,3,1,2,3)만 가지고 있어서 마지막 값은 nil이 나오고 7을 출력해주는데, 그 7은 stream에 있는 수가 아닌 do의 실행횟수를 의미합니다. 

(
var a, b;
a = Pseq.new(#[1, 2, 3, 4], 3, 2); // repeat 3, offset 2, 실행시켜보면 3부터 읽기 시작합니다.
b = a.asStream;
13.do({ b.next.postln; });
)

Pseq을 pitch 값으로 사용해 봅니다. 

(
s = Server.internal;
SynthDef( “Help-SPE3-SimpleSine”, {
 arg freq, sustain=1.0;
 var osc;
 osc = SinOsc.ar( [freq,freq+0.05.rand] ) * EnvGen.ar( 
  Env.perc, doneAction: 2, levelScale: 0.3, timeScale: sustain
 );
 Out.ar(0,osc);
}).send(s);
)

(
var a, d;
a = Pseq(#[60, 61, 63, 65, 67, 63], inf ).asStream.midicps;//숫자들을 midi값으로 지정해주고
d = 0.3;
Task({
 12.do({
  Synth(“Help-SPE3-SimpleSine”, [ freq, a.next, sustain, d ]);
  d.wait;
 });
}).play
)
Pser는 list의 수를 순서대로 주어진 수 만큼 출력한다. 
(
var a, b;
a = Pser.new(#[1, 2, 3], 5); // return 5 items
b = a.asStream;
6.do({ b.next.postln; });
)
Prand는 주어진 수를 random으로 추출하여 두번째 argument에 주어진 수 만큼 출력한다.
(
var a, b;
a = Prand.new(#[1, 2, 3, 4, 5], 6); // return 6 items
b = a.asStream;
7.do({ b.next.postln; });
)
(
var a, d;
a = Prand(#[60, 61, 63, 65], inf).midicps.asStream;//inf라고 되어있는것은 무한대로 추출한다는 뜻. 값의 중복도 일어남.
d = 0.3;
Task({
 12.do({
  Synth(“Help-SPE3-SimpleSine”,[freq, a.next]);
  d.wait;
 });
}).play;
)
Pxrand 는 Prand와 비슷하지만, Prand 에서 처럼 이웃하는 값이 중복값으로 주어지지 않는다. 
(
var a, b;
a = Pxrand.new(#[1, 2, 3], 10); // return 10 items
b = a.asStream;
11.do({ b.next.postln; });
)
Psuf는 Pser와 값으나 그 값이 scramble 된다. 그러나 이와 Pxrand 와 다른점은 list가 단 한번 scramble된 후, 그것을 반복한다.
(
var a, b;
a = Pshuf.new(#[1, 2, 3, 4], 3);
b = a.asStream;
13.do({ b.next.postln; });
)
(
var a, b;
a = Pshuf(#[60, 61, 65, 67], inf).midicps.asStream;
Task({
 12.do({
  Synth(“Help-SPE3-SimpleSine”,[freq, a.next]);
  0.5.wait;
 });
}).play;
)

Nesting Patterns

Pattern을 Pattern내부에 사용하여 Stream을 만들수 있다.
(
var a, b;
a = Pseq.new([1, Pseq.new([100,200], 2), 3], 3); 
b = a.asStream;
19.do({ b.next.postln; });
)
(
var a, b;
a = Prand.new([
  Pseq.new([1, 2], 2), 
  Pseq.new([3, 4], 2), 
  Pseq.new([5, 6], 2)
 ], 3); 
b = a.asStream;
13.do({ b.next.postln; });
)
//Pitch변화를 위한 Sequence. 
(
var a;
a = Prand([
  Pseq(#[60, 61, 63, 65, 67, 63]),
  Prand(#[72, 73, 75, 77, 79], 6),
  Pshuf(#[48, 53, 55, 58], 2)
 ], inf 
).midicps.asStream;
Task({
 loop({
  Synth( “Help-SPE3-SimpleSine”, [freq, a.next.postln] );
  0.3.wait;
 });
}).play;
)
(
var a;
a = Pseq(#[60, 62, 63, 65, 67, 63], inf) + Pseq(#[0, 0, 0, 0, -12], inf);
a = a.asStream.midicps;
Task({
 25.do({
  Synth(“Help-SPE3-SimpleSine”,[freq, a.next]);
  0.3.wait;
 });
}).play;
)