Collectionからパターンシーケンスを作るまで(途中)

7/10にtokyo SuperCollider #1が多摩美ハッカースペースにて開催されます。私も参加したいです。
ちょっと勘違いしていて、超初心者入門中心かなと思っておりました。ならパターンシーケンスについてちょっとまとめてみるかなと、前にまとめておいたものを修正しておりました。
しかし、どうやら発起人の@itaruさんが初心者入門をやってくださり、あとはお好きなネタをどぞって形らしいですので、初心者らしく聴く方で参加したいと思います。中途半端になっていますが、なんらかの参考になればとさっきまで書いていたものをコピペしておきます。整形していないので、rtfかなにかにコピペした方が良いかと。間違っている内容があるかもしれません。たぶん、あります。

実は、oFARtoolKitPlusネタでもできたらなと思いきや、コンパイルできなかったので早々に諦めたんですけれどw

2010/07/08
ちょっと追加

/*
	collectionで何ができるの?
	collectionとstreamとpatternを使用することで、パターンシーケンスが作成可能です
*/

/*
	スパコでのコレクションとはオブジェクトの集合を指し、CollectionクラスのサブクラスにArray,Listなどなどがあります。
	helpから抜粋。
Collection - abstract superclass of all Collection subclasses; many methods are inherited from this class
	SequenceableCollection - abstract superclass of collections whose objects can be indexed by integer
	ArrayedCollection - abstract superclass of Collections of fixed maximum size whose elements are held in a vector of slots
	Array - an ArrayedCollection whose slots may contain any object; more efficient than List
	RawArray - abstract superclass of array classes that hold raw data values
	Order - order of elements with a numerical index
	SparseArray - array of elements optimized for huge gaps between them
	LinkedList - a doubly linked list
	List - an expandable SequenceableCollection (compare to ArrayedCollection and Array)


Collectionのメソッドは、Arrayクラス、Listクラスでも使えます。が、ArrayCollectionのメソッドはListでは使えません。さらに、同じようなメソッドが沢山ありますのでごっちゃにならないようにしましょう。

	パターンシーケンスを作成するうえで非常に重要になります。なると思います。
*/

/*
	ArrayとListの違いって?
	Arrayは最大サイズが固定なので、指定サイズを超えた要素は廃棄されます。
	さらにArrayは最大サイズが32までです。
	Listはサイズが固定ではないため、指定サイズを超えた要素は廃棄されず挿入されます。
	使えるメソッドの違いはありますが、あまり深く考える必要はなさそうです。
*/
(
	var myArray;
	myArray = Array.series(31,1,1);	//要素を31個 1から1づつ増やして格納
	myArray.add(10);				//要素を32個目にいれます
	myArray.at(31).postln;			//32個目の要素はなあに?			
	myArray.size.postln;
	myArray.add(100); 				//要素を一つ加えます
	myArray.at(32).postln;			//加えた要素はどうなるのっと
	myArray.size;					//廃棄されました
)
(
	var myList;
	myList = List.series(31,1,1);	//要素を31個 1から1づつ増やして格納
	myList.add(10);				//要素を32個目にいれます
	myList.at(31).postln;			//32個目の要素はなあに?			
	myList.size.postln;
	myList.add(100); 			//要素を一つ加えます
	myList.at(32).postln;			//加えた要素はどうなるのっと
	myList.size;					//廃棄されません
)
//というわけで、とりあえずListだけ。

/*
	新規生成
*/
(	//グローバル変数
~myList;
~myNewList;
~myNewClearList;
)
(
	~myList = List[1,2,3];				//直接要素を代入して生成
	("myList is" + ~myList).postln;
	
	~myNewList = List.new(3);			//サイズだけ指定して空で生成
	("myNewList is" + ~myNewList + "and size is " + ~myNewList.size).postln;
	
	~myNewClearList = List.newClear(3);	//サイズを指定して、要素nilで埋めて生成
	("myNewClearList is" + ~myNewClearList + "and size is" + ~myNewClearList.size).postln;
	
	
	5.do({ arg i; ~myNewList.add( i ); ~myNewClearList.fill( i ); } );	
	~myNewList.postln;~myNewList.size.postln;~myNewClearList;
)

/*
	要素追加
*/
(
	//末尾に要素追加
	("myList before" + ~myList).postln;
	~myList.add(100);
	("myList after" + ~myList).postln;
	
	//先頭に要素追加
	("myNewList before" + ~myNewList).postln;
	~myNewList.addFirst(100);
	("myNewList after" + ~myNewList).postln;
	
	//指定位置に要素追加
	("myNewClearList before" + ~myNewClearList).postln;
	~myNewClearList.insert( 2, 100);
	("myNewClearList after" + ~myNewClearList);
	
)
/*
	要素置換
*/
(
	("myList before" + ~myList).postln;
	~myList.put(1, 200);
	("myList after" + ~myList).postln;
	
	//indexが配列の最大サイズを超えている場合は最終indexをput
	("myNewList before" + ~myNewList).postln;
	~myNewList.clipPut(10, 20);
	("myNewList after" + ~myNewList).postln;
	
	//最初にもどる
	("myNewClearList before" + ~myNewClearList).postln;
	~myNewClearList.wrapPut( 4, 100);
	("myNewClearList after" + ~myNewClearList).postln;	
	
	//折り返し
	("myNewClearList before" + ~myNewClearList).postln;
	~myNewClearList.foldPut( 4, 200);/
	("myNewClearList after" + ~myNewClearList).postln;	
	
	//要素全てを置換 *collectionのfillメソッドとは異なります
	("myNewClearList before" + ~myNewClearList).postln;
	~myNewClearList.fill(2);
	("myNewClearList after" + ~myNewClearList);	

)
/*
	要素の並べ替えなどの操作
	新規リストを生成するので、元のリストは変更されません。変更したものを使い回したいなら別の変数に代入しましょう。
*/
(
	//逆に並べ替え
	("myList before" + ~myList).postln;
	~myList.reverse;
	("myList after" + ~myList).postln;
	//スクランブルに並べ替え
	("myList before" + ~myList).postln;
	~myList.scramble;
	("myList after" + ~myList).postln;
	//配列の中心要素を軸にミラー(mirror1,mirror2なら3つの要素|3つの要素 になります)
	("myList before" + ~myList).postln;
	~myList.mirror;
	("myList after" + ~myList).postln;
	//要素を引数分繰り返します
	("myList before" + ~myList).postln;
	~myList.stutter(10);
	("myList after" + ~myList).postln;
	//引数値だけ要素の順番をずらします
	("myList before" + ~myList).postln;
	~myList.rotate(2);
	("myList after" + ~myList).postln;
)
//他のメソッドはhelpを見てね

/*
	コレクションの基本的な説明は上記として
	patternクラスを使用して、ステップシーケンスを作成してみましょう。
	patternクラスも非常に多数ありますので、ごく一部だけ。
*/

/*
	その前にちょっとStreamsの説明を
	SC3でのstreamとは、単なるシーケンスの値を表します。1,2,3,1,2,3といった数値の連続のことです。
	シーケンスの次の値を取得するにはstreamのobjectのnextを使用します。
	streamクラスのサブクラスにFuncStreamとかRoutineがありますが、ここでは割愛。
	
	なんらかのループ処理( streamオブジェクト.next )でstreamオブジェクトの中身を順番に取り出すことでシーケンスを作成できる、ということです。
*/

/*
	patternクラスって?
	patternクラス(そのサブクラス)はコレクションを一つの固まりと見なし、
	中身をごにょごにょしたり、何回繰り返すかを決めて、パターンオブジェクトを返します。
	そして、asStreamメッセージによってパターンオブジェクトをストリームとして扱うことができます。
	要は、コレクションの中身をいじくり倒して、nextメソッドで順番に要素を取り出すことができるということです。
	
	また、patternクラスには、ListPatternsとFilterPatternsなどに分類でき、
	ListPatternsは、引数にコレクションを渡して、コレクションの要素を並べ替えたりします。
	FilterPatternsは、引数にパターンを渡して、パターンをいじくります。
*/

//myListはコレクション、Pseqクラスはコレクションを順番通りに何回繰り返すか決めます
(
	var pat;
	~myList.postln;
	pat = Pseq(~myList, 2);		//patにmyListを2回繰り返したものをパターンとして代入します
	pat = pat.asStream.postln;		//patをstream(routine)として扱います
	6.do({ pat.next.postln;});		//6回ループ、ここでnextメソッドを使用してpatから取り出す値をずらしていきます
)
//Prandクラスはコレクションの中身をランダムに取り出します。
//Pseedクラスはフィルタパターンクラスであり、引数のパターンオブジェクトにシードを与えてやります。
(
	var pat;
	~myList.postln;
	pat = Prand(~myList, 6);		//myListからランダムに一つの要素を6回抜き出して、patに代入します
	pat = Pseed(2010, pat, 6);
	pat = pat.asStream.postln;		//patをstream(routine)として扱います
	6.do({ pat.next.postln;});		//6回ループ、ここでnextメソッドを使用してpatから取り出す値をずらしていきます
)

/*
	では、基本は一通り押さえましたのでシーケンスを作ってみましょう
*/

//まずはシンセを定義

(
	SynthDef("collectSynth",
	{
		arg amp,  freq=440, gate=1, pan=0, outBus=0, fxBus=10, fx=0.0, vol=1.0;
		var signal, env, outSend, fxSend, scale, key;
		
		env = Env.adsr();	//シーケンスパートにてgate=0で解放しないと鳴りっぱなし。
		scale = Scale.major;
		key = DegreeToKey.kr(
			scale.as(LocalBuf),	//bufnum 
			MouseX.kr(0, 10),	//indexとしてのinput signal
			scale.stepsPerOctave,
			1,	//mul
			72	//offset
		).midicps;
		signal = SinOsc.ar(key, 0, amp) * vol;
		fxSend = signal * fx;
		outSend = signal * (1.0 - fx);
		Out.ar(fxBus,
			Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * fxSend, pan)
		);
		Out.ar(outBus,
			Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * outSend, pan)
		);
	}).store;	
)

//シーケンスパート
~myList = List[1,0,1,0,1,0];
(
	var t, n, synth1, synth1Loop;
	~effectGroup = Group.tail(s);
	~synthGroup = Group.tail(s);
	
	t = TempoClock(120/60);		//120bps
	//n = NetAddr("127.0.0.1",57124);	//oscで他ソフトにメッセージ送る場合
	
	synth1 = Task({
		var pattern;
		pattern = Pseq(~myList, inf).asStream;
		loop({
			synth1Loop = Synth.tail(~synthGroup, "collectSynth",
				[\amp, pattern.next, \outBus, 0, \fxBus, 10, \vol, 0.8]
			);
		(t.beatDur).wait;
		synth1Loop.set(\gate, 0);	//synthのenvがadsrの時はここらで解放してやります
		});
	});
	t.sched(0, { synth1.start });
)
	

~myList.insert(3, 0);  //要素の挿入
~myList[3] = 1;        //要素の置換