SuperCollider基礎文法最速マスター

SuperColliderの文法一覧です。他の言語をある程度知っている人がこれを読めばSuperColliderの基礎をマスターしてSuperColliderを書くことができるようになれると良いですね。簡易リファレンスとしても利用できたら良いですね。無理ですか、そうですよね。
これを読んでもスパコでシンセ、シーケンスが書けますか?いいえ、書けません。さらに細かいことを知る必要があります。また、SuperColliderはそこそこ難しい部類に入ると思います。柔軟性が高く、他人のコードを読んでもわけが分からなかったりします。

更新履歴

2010/11/27

  • 修正、追記

2010/09/25

  • 間違い削除

2010/02/14 19:00

  • 文字列部分にシンボルなど追記
  • 制御文に、do,switch文追加

2010/02/06 23:00
tn8さんに指摘していただいた

を修正
2010/02/06 18:00
新規

基礎の前に

基礎の前に
まずはその複雑さを確認しましょう。
max(a, b)
a.max(b)
は同じです。
g(f(a, b), c)
g(a.f(b), c)
f(a, b).g(c)
a.f(b).g(c)
これらも同じです。
複数の記述方法に対応しているのが、SCの特徴といえます。SCはオブジェクト指向言語です。オブジェクト指向言語は、おおまかにC言語形、smalltalk形に分けられます。基本的にはsmalltalk形ですが、SCはどちらにも対応しています。そのため、多彩な記述方法がありスパコはややこしいのです。以下は、helpのSyntax Shortcutsの例になります。なんと全て意味は同じなんですよ。

// new argument syntax
(1..10).collect({|n| n.squared }); 	// receiver syntax
collect((1..10), {|n| n.squared }); // function call syntax
(1..10).collect {|n| n.squared }; 	// receiver syntax with trailing function arg
collect ((1..10)) {|n| n.squared }; // function call syntax with trailing function arg
(1..10) collect: {|n| n.squared }; 	// binary operator syntax

// partial application syntax
(1..10).collect( _.squared ); 		// receiver syntax
collect((1..10), _.squared ); 		// function call syntax
(1..10) collect: _.squared ; 		// binary operator syntax

基礎

print文
	"Hello world";// 単に出力ならこれで出ます。
	"Hello world".post;// 改行なし
	"Hello world".postln;// 改行あり
	postln("Hello world");// この書き方でも出力できます。

	//ex)
	100;// ->100
	100.post;200.postln;// ->100 200\n 200
	"super collider".speak; 	//音響言語らしく、文字出力ではなく音出力。すーぱーこらーいだー

	/*
	Hello world
	Hello world
	と何故か2行出力されました。仕様です。スパコでは最終実行結果が常に出力されます。
	*/
コメント
//でコメント一行
/*
	で複数行コメント
*/
/* コメントの中に
	/*
		コメントを入れられます
	*/ 
	いれられます
*/
変数の宣言
	// ローカル変数はvarで宣言します
	// ローカルなので、ブロック内、関数内でのみ使用可能です。ブロック、関数は()や{}囲みになります。
	var myLocalVar = 1; myLocalVar.postln; // ->1
	myLocalVar.postln; // ERROR: 定義されていません
	
	// グローバル変数は〜で宣言します。
	~myGrobalVar = 10;
	~myGrobalVar.postln; // ->10
	
	// 小文字一文字でvar宣言しないとグローバル変数として定義されます。
	b=2; 
	b.postln; //->2
スクリプトの実行
	// 1行実行(mac: enter, ctl-c, ctl-return, shift-return), (emacs:C-c C-c), (win: ctl+enter)
	{SinOsc.ar(440)}.play; 
	(
		// 複数行実行は実行したい部分を選択し(mac: enter, ctl-c, ctl-return, shift-return), (emacs:C-c C-c), (win: ctl-enter)
		//(か)の後ろをダブルクリックで()内を選択できます。(mac: shift-cmd-bでもおkです)
		{
			SinOsc.ar(440) +
			SinOsc.ar(880)
		}.play
	)

数値

数値の表現
	// 数値の表現
	var num = 1;num; // int型として扱われる
	var num = 1.1;num; // float型として扱われる
	var num = 16rF0;num; // 16進数
	var num =  2r01101011;num; // バイナリ

	// 四則演算
	var num = 1+1;num;
	var num = 1-1;num;
	var num = 1*2;num;
	var num = 3/2; num;

	// 商と余り、累乗
	var num = floor(3/2); num; // 商はfloorで切り捨てます
	var num = (3/2).floor; num; // 同様に商
	var num = 3%2; num; // 余り
	var num = 3**2; num; // 累乗

	// インクリメントとデクリメント
	もしかしてない?
	+=とか代入演算子もないです。
	// ビット演算
	var num = 1&1; num; // and
	var num = 1|1; num; // or
	var num = 1<<1; num; // 左シフト
	var num = 11>>1; num; // 右シフト
	var num = 11+>>1; num; // ?

	// 関係演算
	1==1; // 同等
	1===1; // 同一
	1!=2; // 非同等
	1!==2; // 非同一
	1<2; // 小なり
	1<=2; // 小なりイコール
	1>2; // 大なり
	1>=2; // 大なりイコール
	true && false; // 論理積
	true || false; // 論理和

文字列

文字列の表現
	/*
		シングルクォート、ダブルクォートで囲みます。
		ダブルクォートの中では\t(タブ)や\n(改行)などの特殊文字を利用することができます。
		ダブルクォートで囲むと文字列、シングルクォートで囲むとシンボル。シンボルは\symbolとも書けます。
		$を頭に付けると文字。
		文字列とは文字の配列、集合を表しています。シンボルとは単一のものになりますので後述の操作はできません。
	*/
	$A		// 文字
	'abc'		// シンボル
	\abc		// こちらもシンボル
	"a\tb\nc"	// 文字列
文字列操作

//文字列は文字の配列のことですので、次項の配列操作が可能です。

	// 文字列は文字の配列のことですので、次項の配列操作が可能です。
	// 結合
	("aaa"+"bbb").postln; // スペース有り結合 aaa bbb
	("aaa"++"bbb").postln; // スペース無し結合 aaabbb

	// 分割
	"aaa/bbb/ccc".split.postln; // デフォルトセパレータは/
	"aaa@bbb@ccc".split($@).postln; // セパレータは任意のchar、ここでは@

	// 長さ
	("aaa").size.postln; // ->3

	// 切り出し
	"abcdef".at(2).postln; // ->c

	// 検索
	"abcdef".find("c").postln; // ->2 indexを返す
	"abcdefc".findAll("c").postln; // ->[2, 6]

	// 置換
	"abcdefg".replace("abc","aaa");

	// シンボルはこのような操作ができない
	'abc'.at(2).postln; // error	
	
	// 上記基本操作だけでなく、Stringクラスのメソッドは沢山あり、一通りなんでも操作可能です

配列

スパコでは配列が非常に重要になってきます。配列の要素を遷移させつつ読み込むことでパターンシーケンサーが作れたりします。またList,Array,Dictionaryなどのオブジェクトが配列としてありますが、ここではArrayのみにしています。

配列変数の宣言と要素の代入と参照
//配列の生成
	var myArray = Array.new(10); // 最大サイズを指定して生成(ただし、サイズ指定はあまり意味ない)
	var myArray = Array.with(1,2,3); myArray; // 要素に代入して生成
	var myArray = Array.series(10, 1, 2); myArray; // 等差数列、series(size,start,step)
	var myArray = Array.fill2D(2, 4, 1); myArray; // 2*4の2次元配列生成、3次元、多次元もあります
	var myArray = [1,2,3]; // 変数に配列を代入して生成
	
//要素の代入、参照
	// 一行づつ確認出来るようグローバル変数にしてます
	~myArray = Array.new(10); // 新規配列生成
	~myArray.add(1); // index0に1を代入
	~myArray.extend(10,2); // 指定サイズまで要素を代入

	~myArray.at(1); // indexを指定して参照
	~myArray[2]; // こちらもindexを指定して参照
配列の操作
	// 取り出し
	~myArray = Array.with(1,2,3); // 新規配列生成
	~myArray.removeAt(1); // index1を取り出す
	~myArray;// ->[1, 3]

	// 多くの言語がshiftメソッドで取り出しですが、SCのshiftは挙動が違います。
	~myArray = Array.with(1,2,3); // Array.withで要素代入済みの配列定義
	~myArray.shift(2); //  ->[0, 0, 1]  2要素右へシフト、移動分の要素は0に

	// 追加
	~myArray = [1,2,3]; // 新規配列
	~myArray.insert(1,10); // index1に10を代入
	~myArray.add(11); // 末尾に追加。ただし、新規配列が返されるためmyArrayは変化無し
	~myArray; // 追加されていない
	~myArray.addFirst(100); // 先頭に追加
	
	// 置換
	~myArray = [1,2,3]; // 新規配列
	~myArray.put(1,100); // index1を100に置換
	~myArray.clipPut(10,200); // index10を200に置換。最大サイズ超過時は末尾を置換
	~myArray.wrapPut(5,300); // 最大サイズ超過時は、最初から数え直す
	~myArray.foldPut(5,400); // 折り返す
	~myArray.fill(2); // 全て置換

	// 並べ替え
	~myArray = [1,2,3]; // 新規配列
	~myArray.reverse; // 逆
	~myArray.scramble; // スクランブル
	
	// その他
	~myArray = [1,2,3]; // 新規配列
	~myArray.mirror; // 中心を軸にコピー
	~myArray.stutter(2); // 要素を引数値だけ繰り返す
	~myArray.rotate(1); // ずらす

制御文

他の言語とちょい違います。

if文
	/*
		if(条件, 真の時, 偽の時);
		もしくは
		条件.if(真の時, 偽の時);
	*/
		if(true,1,2);	 // ->1
		false.if(1,2);	// ->2
while文
	/*
		while(条件,関数);
		もしくは
		条件.while(関数);
	*/
		(
			i=0;
			while(
				{i<5},
				{ i=i+1; i.postln; }
			)
		)
for文
	/*
		for(開始, 最後, 関数);
		もしくは
		開始値.for(終了値,関数);
		反復値が関数の引数として渡されます。
	*/
		for(1, 10, {arg i; i.postln; });	// 1から10まで出力(1から順に関数へ渡されています)
		1.for(10, {arg i; i.postln; });	// 上と同じ結果
forby文
	/*
		forBy(開始値, 終了値, ステップ値, 関数);
		もしくは
		開始値.forBy(終了値,ステップ値,関数);
		開始値から終了値までステップ値づつ増えます。
	*/
		forBy(1, 10,  2, {arg i; i.postln; });	//2づつ増加
Do文
	/*
		do(コレクション,関数);
		もしくは
		コレクション.do(関数);
		ここでのコレクションとは[ ]で括った集合のことです。
		n回繰り返すための制御文として主に使われる、コレクションを反復処理するための制御文でもあります。
		コレクションの頭から順に、関数の第1引数へ渡されます。コレクションではなく単に整数nにするとゼロからnまで繰り返します。
		関数に引数が二つあれば、第2引数は繰り返しのカウンタ値となります。
	*/
		do([ "a",1,10,'b'] , {arg item; item.postln; } );	// ->a 1 10 b
		do(5, {arg item; item.postln; });				//-> 0 1 2 3 4,最後に5が出力されるが仕様
		( 5 .. 10 ).do( {arg i, counter; [i , counter].postln; }); // ->[5.0] [6.1] [7,2] [8,3] [9,4] [10.5], こちらの書き方が一般的。
Switch文
	/*
		switch( 変数, 定数1, 定数1の時, 定数2, 定数2の時,・・・ );
		case文なるものもあります。
	*/
	(
		var x=2.rand;	// xは0か1
		switch(x, 0, { "x == 0" }, 1, { "x == 1" } );
	)

関数

		// {}で括ったものが関数となる
		// argは引数、varは変数
		~myFunction = { arg  a; var b = 1; a + b; };
		~myFunction.value(1);	// ->2 valueメソッドで引数にアクセス

		// 引数は| | でも書けます。
		~myFunction = { |a=1| var b = 1; a+b; };
		~myFunction.value;	// ->2

		// 引数で... bのように書くと配列と見なされます。
		~myFunction  = { arg ... a; a; };
		~myFunction.value(1,2,3,4,5,6);	// ->[1,2,3,4,5,6]

ファイル入出力

ここでは、とりあえずテキストのみ。サウンドの読み込みを書くと操作も書くことになるので。

//ファイル書き込み
(
	var f, g;
	f = File("test","w");
	f.write("Does this work?\n is this thing on ?\n");
	f.close;
)
//ファイル書き込み
(
	g = File("test","r");
	g.readAllString.postln;
	g.close;
)

いじょう

スパコは難しいです。ヘルプファイルは充実していますが、英語がよくわからないです。
とりあえず他の最速マスターに従って書いてあります。かなり省いた部分がありますので加筆していくかもしれません。もちろん間違っているところなど指摘していただければ修正します。しないかもしれません。
どう見ても見にくいので、sc.jpにrtfファイルを置かせていただいています。出来ればこちらをSCで開いて見てください。スパコwikiの文法です。