2. SuperCollider3 는 음악작곡, 오디오 신디시스를 위해
1996년 James McCartney에 의해 최초 개발된
프로그래밍 환경(언어+오디오엔진)이다.
Smalltalk 및 Ruby 언어 등에 영향을 받은 강력한 고수준
(high-level) 문법과 소리생성, 제어를 위한 다양한
UGen(UnitGenerator) 들을 제공하여 현재 Max/MSP,
Pd 등과 함께 가장 널리 사용되는 전자음악 도구가 되었다.
초기버젼에는 MacOSX 를 중심으로 개발되었으나(GUI, IDE등이 OSX 전용 개발 프레임워크를 사용), 현재는
다양한 플랫폼에서 동일한 프로그래밍 환경을 제공하는 크로스플랫폼 어플리케이션으로 진화하였다.
현재(2016.7.24) 기준으로 최신 버젼은 3.7.2 로 http://supercollider.github.io 통해 배포된다.
http://sccode.org 에는 유저들의 다양한 예제 코드들이 공유되고 있으며, 여러 프로그래밍 방법론들을
통해 유저마다 각자만의 사용하는 방식들이 존재함을 알 수 있다.
GPL v3 기반의 완전한 오픈소스 프로그램으로, 공식적으로 배포되는 어플리케이션 외에 여러 가지
사용 환경(IDE,언어)들이 존재한다.
3. SuperCollider Application 의 구조
SuperCollider는 기본적으로 오디오엔진(소리합성)을 담당하는 scsynth(server) 와 그 엔진을 제어하는
sclang(client)으로 구성되어 있으며 서로간에 OSC(OpenSoundControl) 프로토콜을 통해 제어 메시지 및
데이터를 주고 받는다. 최근엔 shared memory interface 를 지원하여 서버와 클라이언트가 같은 머쉰안에
존재한다면 메모리를 통해 컨트롤 값 및 오디오데이터(for Scope) 를 빠르게 주고받을 수 있다.
SCLang
(client)
SCSynth
(server)
OSC
shared memory, if supported it your system
서버와 클라이언트는 1 : 1 관계뿐만 아니라 N : 1, 1 : N, N : N 상황을 지원하여, 다른 프로그램과
연동하여 사용하기에도 매우 유연한 구조로 되어 있다.
sclang
Max/MSP
PureData
scsynth
scsynth
scsynth
서버와 클라이언트는 UDP/TCP 를 지원하기 때문에
동일 머쉰안에 존재하지 않을 수 있다.
5. 기본적인 산술연산
10 + 2 // 12
10 * 4 // 40
10 / 3 // 3.3333333333333
10 / 3.0 // 3.3333333333333
10 + 2 * 4 // 48
//일반적인 프로그래밍 언어과 연산자 우선순위가 다르다. sclang 에서는 열거된 순서대로 연산을 진행하므로
//위와 같이 여러 연산자들이 나올 경우 반드시 괄호를 사용하자!
숫자 객체들을 위한 다양한 메시지들
-10.abs // 10
4.8.floor // 4
4.8.sin // -0.99616460883584
4.8.cos // 0.087498983439446
4.8.tan // -11.384870654243
외에도 많은 메시지(메서드method) 들이 제공되므로 SuperCollider 가 제공하는 help 파일들을
항상 살펴보는 습관을 들이자!
7. UGen 이 생성하는 시그널 역시 숫자의 연속이므로 숫자(Number) 객체와
동일한 산술연산, 우선순위 규칙, 메시지를 제공한다.
{SinOsc.ar(440)}.plot {SinOsc.ar(440).abs}.plot
{SinOsc.ar(440)+4}.plot
{SinOsc.ar(440).mod(2)}.plot
{SinOsc.ar(440)*8}.plot
1
-1
5
3
11. 일반적인 SCLang 의 표현식을 중괄호로 감싸면 함수객체가 된다.
{ 10 + 20 }; // a Function
f = {|a,b| a + b}; // 함수에 인자를 사용하기.
f.value(10,2); // 함수 호출 문법. 함수객체에 value 메시지를 전달하면 호출된다.
f.(10,7); // 간단히 이렇게 사용도 가능!
SCLang 의 함수객체는 또 다른 함수객체의 인자로 전달 될 수 있다.
(
var add = {|a,b| a + b;};
var minus = {|a,b| a - b;};
var f = {|func| func.(4,5);};
f.(add).postln; // 9
f.(minus).postln // -1
)
12. 물론 함수의 리턴값으로도 사용이 가능하다.
// 누산기 만들기. ~make_accum 은 인자 i 를 받아 a 의 값을 증가시키는 함수객체를
// 리턴하는 함수이다.
~make_accum = {|a| f = {|i| a = a + i;}; f;};
a = ~make_accum.(4);
a.(8);
a.(4);
a.(10);
// 이때 ~make_accum 의 호출결과로 리턴되는 f 는 ~make_accum 의 인자 a 의 값을 캡쳐하게 되는데
// 이처럼 함수가 정의되는 시점의 주변환경을 기억하는 함수를 렉시컬 클로져(lexical closure) 라고 한다.
함수객체에 play 메시지를 전달하면 서버(scsynth) 에서 함수의 리턴값을 실행하게 되는데..
만약 함수객체의 리턴값이 UGen 이라면 소리를 들을 수 있다.
{ SinOsc.ar(440,0,0.2) }.play;
n = {|freq| SinOsc.ar(freq, 0, 0.2)}.play;
n.set(freq,880);
n.set(freq,1820);
n.free;
13. Coroutine
코루틴이란 일반적으로 진입 지점이 하나이고, 리턴될 장소가 정해져있는 일반함수와는 다르게,
여러 진입 지점(entry point) 를 가지고, 돌아갈 위치를 지정해줄 수 있는 서브루틴의 하나로써,
실행흐름의 제어를 사용자가 직접 통제할 수 있다는 특징을 가진다.
SCLang 에서는 Routine 클래스를 사용하여 코루틴을 구현하였으며, 일반적으로
1) 몇 몇 특수한 상황을 제외하고 blocking 을 허용하지 않는 주 실행분기(main-thread) 밖에서
작업을 수행해야 할 때,
2) TempoClock 등의 clock 오브젝트와 함께 event scheduling 을 수행할 때 사용된다.
(
r = Routine{|x|
var r;
r = (x + 4).yield;
r = (r + 11).yield;
r = (r - 5).yield;
}
)
r.next(10) //
r.next(2) //
r.next(8) //
14. Routine 객체는 play 메시지를 받으면 yield 된 이후에 정해진 시간(yield메시지를 받은 숫자)
이 지난 후 scheduler(Clock 객체)에 의해 자동으로 재시작 한다.
(
Routine{
"hello ".post;
2.yield;
"world".post;
2.yield;
"!".postln;
}.play;
)
이때 yield 메시지를 받는 숫자는 초(seconds) 가 아닌 beat 로 기본적으로 TempoClock.default 객체의
tempo 에 의존한다.
TempoClock.default.tempo_(4.0); // bpm = 60*4
(
Routine{
"hello ".post;
2.yield;
"world".post;
2.yield;
"!".postln;
}.play;
)
Routine 객체에 보내는 play 메시지의 인자로 사용할 Clock 객체를 지정할 수 있으며, 기본값은
TempoClock.default 객체다.
16. OSC(OpenSoundControl)
음향,멀티미디어 소프트웨어/기기 간 데이터 송수신을 목적으로 만들어진 데이터 인코딩 규격으로
MIDI 에 비해 다양한 데이터포맷(int,float,string,blob) 을 지원한다.
일반적으로 UDP 프로토콜을 통해 메시지를 주고 받으며, SuperCollider 는 TCP 와 UDP 모두 제공하며,
Internal Server 의 경우 SCLang<—> SCSynth 간에 메모리를 통해 내부적으로 메시지를 주고 받는다.
-UDP 의 장단점
속도가 빠르다. 하지만 한 번에 보낼 수 있는 최대 메시지 사이즈가 있으며,
순서가 보장되지 않으며, 전송을 보장하지 않는다.
SCLang 에서 PureData와 OSC 로 메시지를 주고 받기.
- 메시지 보내기
- 메시지 핸들링