SuperCollider基礎文法最速マスター
SuperColliderの文法一覧です。他の言語をある程度知っている人がこれを読めばSuperColliderの基礎をマスターしてSuperColliderを書くことができるようになれると良いですね。簡易リファレンスとしても利用できたら良いですね。無理ですか、そうですよね。
これを読んでもスパコでシンセ、シーケンスが書けますか?いいえ、書けません。さらに細かいことを知る必要があります。また、SuperColliderはそこそこ難しい部類に入ると思います。柔軟性が高く、他人のコードを読んでもわけが分からなかったりします。
更新履歴
2010/11/27
- 修正、追記
2010/09/25
- 間違い削除
2010/02/14 19:00
- 文字列部分にシンボルなど追記
- 制御文に、do,switch文追加
2010/02/06 23:00
tn8さんに指摘していただいた
- 小文字で変数宣言しない場合はグルーバル変数
- SuperColliderの記述
- macにおけるスクリプトの実行コマンド
を修正
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; )