Objects (객체)

SC는 소리를 내주는 UGen부터 숫자 하나까지 그 모든것이 객체로 이루어져있습니다
객체에 메시지를 보내 특정 행동을 지시할 수 있습니다

객체들은 클래스로부터 계층적으로 지정되고 
각 클래스마다 고유한 메쏘드 세트가 있습니다

알기 쉽게 비유하기 위해 Birds라는 객체의 추상 클래스가 있다고 가정해보겠습니다

Birds클래스는 모든 새들에 대한 공통적인 메쏘드(메시지)가 정의되어있습니다

ageweightspecies 등의 메쏘드를 이용해 해당 새에 대한 정보를 얻을 수 있습니다
flyeatsleep과 같은 메쏘드는 새에게 특정 행동을 수행하도록 합니다

또한 앵무새목, 참새목, 닭목, 펭귄목과 같은 Birds의 하위 클래스(subclass)들을 가질 수 있습니다
이런 하위 클래스는 부모 클래스의 모든 메쏘드를 상속받는 동시에 
고유한 메쏘드를 구현하여 특수 기능을 가질 수도 있습니다 

예를들어 위의 모든 하위 객체들은 Birds 클래스에서 상속된 .fly메시지를 수행할 수 있습니다 
Macaw.class는 해당 새의 종류를 반환합니다
이 메쏘드는 Macaw에서 파생된 모든 객체에도 공통적입니다 

Macaw는 말을 할 수도 있으므로 Macaw.speak를 호출하면 말을 시킬수 있습니다 
반면Penguin.speak는 다음과 같은 오류를 표시합니다. ERROR: Message ’speak’ not understood.

위 예에서 등장하는 대문자로 시작하는 단어가 객체를 나타내는 클래스입니다

클래스명 다음 점(.) 뒤에 오는 소문자는 
해당 객체로 전송되는 메시지(또는 메소드)
메시지 바로 뒤 괄호 안에 오는것들이 argument입니다

Penguin.eat("sardines", 2)에서, 메시지 'eat'은 
먹이, 그리고 수량에 대한 매우 구체적인 정보를 Penguin에게 보냅니다 

SC를 사용하다보면 Cockatoo.screaming(vol10)과 같이 
구체적으로 선언된 아규멘트를 쓸 수도 있습니다

정리하자면 기본 구조는 Receiver.message(arguments) 입니다


Messages와 Arguments

위에서 언급했듯이 메시지(메쏘드)는 
'
뛰어라, 연주해라' 와 같은 일종의 명령(commend)입니다
(즉, 무엇을 해야하는가)

아규멘트는 '수류탄을 15m가량 투척하라' 와 같은 명령에 대한 조건입니다
(즉, 그것을 하는 방법)

이를 SC 언어로 작성하면 다음과 같습니다

throw(15, grenade);
play("stockhausen X");

당연히 SC는 모든것을 이해하지 못하므로 SC가 이해하는 명령을 사용해야만 합니다
SC는 많은 수의 신스 및 패턴 관련 명령을 이해합니다

소문자 단어로 된 메시지 다음에는 아규멘트 목록을 포함하는 한쌍의 괄호가 붙습니다

rand(100); //비교 실행해볼것
rand(100.0);

일반적으로 float를 아규멘트로 사용하면 float이 반환되고 int를 사용하면 int가 반환됩니다
즉 100의 경우 정수만을, 100.0의 경우 실수(float)를 출력합니다

2개의 아규멘트를 가지는 메시지들도 있는데 아래와 같습니다. 
이는 2개의 아규멘트를 갖는 또다른 유형의 렌덤 메시지 입니다.

exprand(1, 1000); 
({exprand(1,1000)}!1000).plot;

rand와 exprand의 차이점으로 exprand메시지는 지수분포적인 결과를 산출합니다
선택의 절반은 1에서 100사이고 나머지는 100에서 1000 사이의 값이 출력됩니다

보통 인간이 동일하게 인식하는 연속적인 소리의 간격(옥타브)이 지수적이기 때문에
exprand는 주파수 선택에 용이합니다

메시지 몇가지를 더 살펴봅시다

dup("echo", 20) //duplicator, 첫번째 아규멘트인 리시버 "echo"를 두번째 아규멘트에 지정된 횟수만큼 복제
round([3.141, 5.9265, 358.98], 0.01) // 첫번재 아규멘트 리스트를 두번째 아규멘트의 정밀도로 반올림
sort([23, 54, 678, 1, 21, 91, 34, 78]) // 리스트 내 수들을 적은 수부터 정렬
round(dup({exprand(1, 10)}, 100), 0.1) // 1~10까지의 난수를 100개 선택한 후 반올림
sort(round(dup({exprand(1, 10)}, 100), 0.1)) //1~10까지의 난수를 100개 선택한 후 반올림 하고 정렬

위 마지막 줄의 메시지를 보면 exprand와 dub이 sort 내부의 round에 대한 아규멘트 리스트 안에 있는데
이를 중첩(Nesting)이라고 합니다

이해를 돕기 위해 가상의 앵무새에게 먹이를 주기 위한 준비를 가정해봅시다

껍질을 벗긴 사과와 바나나를 10조각으로 썰고, 알곡이나 펠렛을 10:5로  뿌린 후 섞어서 먹이를 급여합니다

feeding(
mix(
slice(peel(apple, banana), 10),
sprinkle(sum[(pellet(10), grain(5))])
)
)

위와같이 여러단계의 중첩이 사용될때마다 새로운 라인이 자동으로 들여쓰기됩니다.

이런식의 중첩을 Function에 적용할 수가 있습니다

(
{
CombN.ar(
SinOsc.ar(
(LFNoise1.kr(3, 24, LFSaw.kr([5, 5.123], 0, 3, 80)).midicps),
0, 0.4),
1, 0.3, 2)
}.play
)

위 예의 SinOscLFNoise1처럼 ar이나 kr과 같은 메세지 앞에 붙는것을 리시버(Receiver)라고 합니다
리시버로 사용할 수 유형으로는 UGens, numbers, string등이 있습니다

이들이 메시지와 연결되면 오디오 출력이나 개별 값, 또는 숫자들의 스트림을 생성할 수 있습니다

UGen이 kr이나 ar메시지를 보내면 신데시스 서버에서 오디오를 생성하는 프로세스가 설정됩니다
리시버와 메시지 사이의 점(.)은 대략"이것을 하라"라는 의미고 
아규멘트 리스트는 리시버가 명령을 완료하는 방법에 대한 설명입니다

따라서 LFNoise1.kr(3, 24)는 "LFNoise1을 통해 -24~24사이의 난수를 1초에 3번 생성함"을 의미합니다

 Numbers, functions, arrays, 및 strings 모두 점(.)을 통해 수행할 작업을 알려줍니다.

[45, 13, 10, 498, 78].sort // 아이템 컬렉션들, 적은 수부터 정렬
"echo".dup(20) // 이것을 실행하면; yourself를 20번 반복함
50.midicps // 숫자50, 이를 실행하면; Hz로 변환
444.cpsmidi // 444, 이를 실행하면; midi number로 변환
100.rand // 100, 이를 실행하면; 0에서 100사이의 무작위 숫자 추출
{100.rand}.dup(50) // 렌덤숫자추출, 이를 실행하면; 50회 반복
[1.001, 45.827, 187.18].round(0.1) // 아이템 컬렉션; 반올림


Receiver notation, functional notation

메시지를 표기하는 방법은 두가지가 있는데 
예를들어
rand(100)을 100.rand로 표기할 수 있습니다

결과적으로 아무 차이가 없으며 단지 문법의 차이인데

100.rand는 receiver 노테이션이고
rand(100)은 functional 노테이션입니다


어떨때 어떤 표기법을 사용할지는 스타일의 문제로 
대문자(SinOsc, Pan2, Array)로 시작하는것들은 
거의 항상 리시버 노테이션을 사용합니다

 숫자, 리스트 및 텍스트는 문맥에 따라 두가지 방법으로 작성하거나 섞어서 쓸 수 있습니다.

1000.0.rand.round(0.01).post //수를 뽑고, 반올림하고, post
{1000.0.rand.round(0.01).postln}.dup(100).plot //....

arg가 2개인 메쏘드는 다음과 같이 적을 수도 있습니다

// receiver syntax
"echo".dup(5)
[3.141, 5.9265, 358.98].round(0.01); 

// function call syntax
dup("echo"5)
round([3.141, 5.9265, 358.98], 0.01);

// binary operator syntax
"echo" dup5
[3.141, 5.9265, 358.98round0.01;


그 외에도 문법을 단축해주는 단축키가 있습니다

series(1, nil, 10)
(1..10) // 위와 동일

series(2, 7, 72)
(2, 7..72) // 위와 동일



 


Posted by Elec-Kiwi
,