サーバサイドSuperCollider
基本
SCはaudio serverであるscsynthと、クライアントであるsclangに分かれて成り立っています。さらに、sclangはプログラム言語部分とインタプリタ部分に分かれています。sclangの機能として2つあり、サーバのクライアントとしての機能と、言語のインタプリタとしての機能です。要はコードを解釈して、サーバであるscsynthにメッセージを送るという役割を担っています。また、sclangとscsynthはOSCプロトコルを利用して情報のやり取りをしています。
SC内の一連の流れは、SCプログラミング言語で書かれたものをsclangのインタプリタが解釈しOSCメッセージに落とし込む。次に、そのOSCメッセージをsclangがscsynthに送信。scsynth側で送られてきたメッセージに従い処理する。となっています。なんらかの方法を用いて、scsynthにシンセを作成し、そのシンセに対して挙動を制御できれば音が鳴るってことです。じゃあ、scsynthだけ動かすサーバたてて、クライアントはsclangじゃなくてなんでも使って良いんだよね!?ClientVsServer.htmlを読むとまさにそんなことが書いてあります、もっとも、sclang使うとscsynthへSynthDefsの作成と読み込みが楽だし、sclang使ってね!と書いてありますけれど。
sclangからscsynthをコントロールするには、Serverオブジェクトを利用します。Serverオブジェクトはクライアント(sclang)と同じマシンで動いているscsynthを表すことが多いですが、リモートマシン上のscsynthでもおkです。
なんか間違っているかも。。。
具体例
端末は1台でも試せますが、できれば2台端末を用意してください。サーバとして使用する側にてターミナルでifconfigして、ループバックアドレスではないアドレスが端末に割り振られていることを確認してください。以下は192.168.11.2が割り振られている場合の例になります。クライアントからServerオブジェクトを使えば、リモートホストのscsynthをコントロールできると述べました。
では、クライアント側から以下を実行してみてください。
~myServer = Server( \test, NetAddr( "192.168.11.2", 57110 ) ); ~myServer.makeWindow;
お、いつもと違うGUIが立ち上がりましたね。boot,quitボタンがありません。
~myServer.boot;
リモートでのサーバブートは許可されていないためfailedになりました。
じゃあリモートサーバをbootするには、どうするのっと。
scsynthを立ち上げたいサーバ(ホスト)にsshなどでログインし、ターミナルにて"$ scsynth -u ポート番号"でブートさせることが可能です。ポート番号はNetAddrで指定したポートになりますよ。
macをサーバとしたときには、ディレクトリを/Application/SuperColliderに移動しておかないとエラーが出るかもしれません。
もちろん、サーバ側でSuperCollider.appとかを立ち上げて通常通りlocalサーバをブートしても行けます。
じゃあ、早速サーバ側で音を鳴らしてみましょう。
~myServer.sendMsg( "/s_new", \default, x =~myServer.nextNodeID, 0, 0 ); ~myServer.sendMsg( "/n_free", x );
簡単ですね。ただし、defaultシンセはあらかじめサーバ側に保存されているものです。クライアント側からシンセを定義して送りたいんだ! 送り先をデフォルトサーバのsではなく、先ほど定義したサーバを指定するだけです。
( SynthDef( "network_test", { arg freq=1200; var signal,env; signal = SinOsc.ar( freq, 0, 0.5 ); env = EnvGen.ar( Env.perc ( 0, 1, 1, -12 ), doneAction: 2 ); Out.ar( 0, Pan2.ar( signal * env, 0 ) ); }).send( ~myServer ); ) ~myServer.sendMsg( "/s_new", \network_test, x = ~myServer.nextNodeID, 0, 0 ); ~myServer.sendMsg( "/n_free", x );
ちゃんと音が鳴りました!
scsynthとsclangが同じ端末だと、なんか起動していないから送れないよ。とかエラーでるかもしれませんが、たぶん送れてます。
サーバの終了はいつもの。
~myServer.quit;
local vs internal
ん?これってlocalサーバ、internalサーバ?ここでちょっと寄り道してlocalサーバとinternalサーバのお話。
何が違うの?って、ちゃんとヘルプに書いてあります。localサーバはsclangとscsynthが違うアドレス空間で動いています。internalはsclangとscsynthが同じアドレス空間で動いています。internalはメモリを共有しているので、scopeとかSharedIn/SharedOutが使えるよ。んで、(sclangとscsynth間での)メッセージのレイテンシが小さいよ。localサーバは別々なのでsclangがこけてもscsynthは生きているから音は出続けてロバストだよ。らしいです、家で使うときはinternalで良いんじゃないですかね?
scsynthとsclangが別端末の場合は、localサーバと同じですね。scopeは使えません!
いじょう
SCは構造としてサーバとクライアントが分離されており、ある意味サーバサイドであり、クライアントからコードを送ってサーバ側で音を鳴らすことができることが分かりました。
ここで、問題となるのがレスポンス。残念ながらサーバ側で音が鳴るだけです。クライアント側に音を返してこそサーバサイドだ!どうやってクライアントに音を返すか?SC側に実装はされていないような気がします。じゃあ、ストリーミング?