clash, crash, crush.
クラッシュ、というカタカナコトバを英語で表記したとき、それにあたる英単語は3つある。crashは、車などが高速で衝突する、その結果、ものが壊れてしまう。または意図せずコンピュータがその機能を停止した時に使う。一方 clashの方は同じようなぶつかり合いではあるものの、ものは壊れない。らしい。そして、crushも同様に押しつぶされるようなイメージをもつ単語だか、それは、特に恋愛において使われる。 i have a crush on SC、私はSuperColliderに夢中なのです。
さて、本日より七夜に渡って「SCクラッシュ!わいふの七日間戦争。」と題し、「どうしたらSuperColliderをクラッシュさせることができるのか?」を探っていきましょう。このシリーズに含まれるサンプルコードを実行すると、マシンがクラッシュしてしまう可能性があります。私は責任を持ちませんので、どうぞご注意してください。
Note : I’m finding “How can I crash SuperCollider?”, please run the sample codes at your own risk ; )
// ————————————————————————————————–
第一夜「解き放たれない熱」〜不要になったSynthNodeは解放しよう
No.1 don’t forget to release the Nodes.
SCでクラッシュ、といえば、真っ先に思い浮かぶのは、Synthノードの解放のし忘れです。音を作る時には、SynthノードというものがSCのサーバーに作られます。
// サーバーパネルウィンドウの「Synth」の欄に注目。
// 音を出すと「Synths」の数が1つ増え、音を止めると1つ減ります。
{SinOsc.ar}.play;
さて、音量にエンヴェロープをかけてみましょう。エンヴェロープには、いわゆるADSR型などのgateを必要するものと、percの様にパーカッシブな音を作る為の2タイプがあります。前者はgateの値を0にしてやらないと音は止まりませんが、後者は自動的に音が止まってくれます。
{SinOsc.ar * EnvGen.kr(Env.perc)}.play;
上記のようなコードを実行したとき、音が減衰して聴こえなくなると、音が完全に無くなっているかのように見えます。しかし、synthノード自体はまだサーバーに残されています。この解放されていないノードが溜まっていくとCPUに負荷がかかりつづけ、問題をひき起こす場合があります。回避方法としては、エンヴェロープが終了した時に、一緒にノードも解放し忘れない事です。EnvGenのdoneActionアーギュメントの値を2にセットする必要があります。
{SinOsc.ar * EnvGen.kr(Env.perc, doneAction:2)}.play;
実際にクラッシュを試みてみましょう。今回は、SCの言語部分からは独立したscsynth、ローカルサーバーを使ってみます。必要な書類等は保存して、不要なアプリケーションを終了しておきます。マシンのCPU処理状態を表示してくれる「アクティビティ・モニタ」を監視しながら、実行スタート。
s = Server.local;
SynthDef('goodby', {arg freq = 300;
var source = MoogFF.ar(Pulse.ar([freq,freq*1.5], XLine.kr(0.45,0.5,0.2)), XLine.kr(freq*3,freq*5,0.1.rand+0.1), 2+1.0.rand)
* EnvGen.kr(Env.perc) * 0.6; // you need doneAction:2 for normal use
Out.ar(0, source)
}).store;
Pbind(
\instrument, 'goodby',
\tempo, 1,
\dur, 0.125,
\octave, Pseq([4,5,6],inf).stutter(8),
\degree, Pseq((0..6),inf) + Pseq([-2,2],inf),
\scale, Scale.mixolydian,
\post, Pfunc({Server.local.peakCPU.postln})
).play;
SCローカルサーバーのSynthsやPeakCPUの値がどんどんあがっていきます。PeakCPUが、110%を越したあたりから、音がブチブチと途切れ始めます。まるで心もとないラジオの電波を受信しているようで、ちょっとときめきます。218%を越したところで、マシンのファンが回転しはじめました。アクティビティモニタをみてみると、scsynthのCPUは 68%ほど。まだ余裕があります。どんどんノードの数が増えていきます。音はブツブツいいながらもまだ生成されているようで、息も絶え絶えになりつつ、新しいリズムを奏でているかのようです。こうした予期しないエラーは、いつもかっこいい。途中から音がでなくなったり、急にブツブツとでたりします…. しかしながらノードは着実に増えていきます。最終的にノードの数が1022、PeakCPU 557%、scsynthのCPUが80%になったところで「FAILURE /s_new too many nodes」というエラーが表示され始め、それ以上のノードは作られていないようでした。というわけで、クラッシュしっぱい!さすがSC、安心設計ですね。。
調べてみたら、サーバーで作成できるノードの最大数は、ServerOptionで設定をすることができます。デフォルトでは、1024とのこと。さっそく変更してみましょう。変更後にはサーバーを再起動する必要があるので忘れずに。
s.options.maxNodes = 4096;
s.reboot;
と、今度は、Synthが3264、PeakCPU 1761% scsynthが95%になったところで、
FAILURE /s_new alloc failed, increase server's memory allocation (e.g. via ServerOptions)
と表示され、それ以上、新しいノードは作られなくなりました。しかしまだサーバーはクラッシュはしていません。表示されたエラーは「ServerOptionsでサーバーのメモリの割当をふやしてください」とのことなので、指示?に従って、増やしてみましょう。
s.options.memSize // 現在の設定を取得、8192
s.options.memSize = 2.pow(16); // メモリの割当を65536に増やす
s.options.maxNodes = 4096*4; // ついでにこっちも増やしておこう
s.reboot;
さぁ、これでどうだ!ノードの数が6800を超えたあたりから、もう音はでなくなってしまいました。サーバーパネルのQuit / Bootボタンがチカチカして、起動と終了を勝手に繰り返しています。しかし、アクティビティモニタをみているとscsynth自体は落ちていない様子。SynthDef自体をもうちょっと重くしましょう。。ということで、GVerbを付け加えてみました。
SynthDef('goodby2', {arg freq = 300;
var source = GVerb.ar(MoogFF.ar(Pulse.ar([freq,freq*1.5], XLine.kr(0.45,0.5,0.2)), XLine.kr(freq*3,freq*5,0.1.rand+0.1), 2+1.0.rand))
* EnvGen.kr(Env.perc) * 0.6; // you need doneAction:2 for normal use
Out.ar(0, source)
}).store;
すると、PeakCPUが80%を超えたところで、ばしっとサーバーが落ち、scsynthアプリケーションが終了します。わーい、落ちた!
しかしながら、postウィンドウには数値が表示されつづけています。このことから分かる通り、scsynthが落ちても、sclagn部分は落ちていません。s.boot;を押し、ローカルサーバーを再起動すると、すぐにまた音を生成してくれます。これが、シンセサーバーと言語部分のクライアントが分かれているSuperColliderの大きな利点ですね。はぁ〜やっぱりSCは良いですね。らぶ。
(ちなみに、設定したServerOptionの値は、SCを再起動すると自動的にリセットされています。もし、設定を固定しておきたい場合は、startup.scdに記述しておきましょう。)
Posted: 5月 15th, 2012 under 日々のSC.
Comments: none