node.jsとSuperColliderをOSCでつないでみる


nodejs  icon.supercollider

node.js はほぼ初体験ですが、どうしてもSuperColliderと組み合わせたくてチャレンジしてみました。

node.js とは、スケーラブルなネットワークプログラムをかんたんに開発するためのプラットフォームです。最近ではメタCSSのLESSがnode.jsで動いていて、ぼくもなんとなくLESSのためにMacにインストールしていたのですが、HTMLテンプレート言語のEJS, Webアプリケーションフレームワークのexpress, Sails.jsHogan.jsなどなどが出てきて、Webサービスの開発言語にどんどん採用されている…というイメージです。

で、node.jsとSuperColliderがどうつながるか、ですが、もともとnode.jsのデモとしてチャットシステムを見せてもらったんですが、完全にリアルタイムなんですよ。Skypeチャットなどはタイプした瞬間に相手にも見えているわけですが、それと同じようなことが自分でもできるというわけです。これは、リアルタイム性が要求される音楽の領域においては魅力的ですよね。

しかも、node.jsは言語としてはJavascriptなので習得がかんたん、npmというパッケージ管理システムがあるため環境構築もかんたん、イイコトずくめというわけです。

とはいえ普段仕事が忙しすぎてなかなか取り組む機会がないため、大阪で開催されたNode.jsの勉強会に参加して、どんな風に使われているのかと、環境構築についてちょっと勉強して来ました。

まず node.js のインストール

node.js のインストールは nodebrew を使うのがおすすめらしいです。node.js の開発では色々なモジュールを自在に組み合わせてプロジェクトを作ることが多いそうなのですが、その過程で依存関係の解決のために、node.js のバージョンも切り替えることがよくあるそうです。nodebrew を使うとかんたんに node.js のバージョンを切り替えられます。

とりあえずターミナルからワンライナーでインストール

$ curl -L git.io/nodebrew | perl - setup

~/.bashrc に1行足してパスを通します

export PATH=$HOME/.nodebrew/current/bin:$PATH

.bashrc ファイルを保存したらリロードします

$ source ~/.bashrc

nodebrew コマンドが使えるようになってたらOK。

$ nodebrew help

って、レポジトリのREADMEそのまんまですね。詳しくはググりましょう。

ちなみに、インストール時はc++でコンパイルできる環境が必要です。ぼくはここでひっかかりました。かなり古いバージョンのXcodeからアップデートしてなかったせいのようです。最新のXcodeをApp Storeを使ってインストールし、Preferencesウィンドウを開く → Downladsタブを開く → Command Line Tools の「Install」ボタンをクリック。これでOKです。

nodebrew を入れただけでは node.js は入っていませんので、nodebrew を使ってインストールします。適当にバージョン0.8.x(0.8系の最新バージョン)を入れてみました。インストールしたら nodebrew use コマンドでそのバージョンを使うことを明示する必要があります。複数のバージョンを切り替えられるがゆえにこういうしくみになっているわけですね。どのバージョンがインストールされているかの確認は nodebrew list コマンドで。

$ nodebrew install v0.8.x
$ nodebrew list
$ nodebrew use v0.8.23
$ node -v
v0.8.23

インストールができたら、サンプルコードを動かしてみます。

ファイルを作成

$ vim example.js

サンプルコード

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

で、作成したexample.jsをコマンドラインから起動します

$ node example.js
Server running at http://127.0.0.1:1337/

ブラウザから http://127.0.0.1:1337/ にアクセスし、Hello World というメッセージが表示されたらOK!1337ポートでHello Worldを表示するだけのWebサーバーの完成です。カンタンですね!

ちなみに、example.js は実行しっぱなしだとサーバーが起動したまんまなので、 Ctrl + c で終了できます。ちょっと、Command + . で終了するSuperColliderと似てるなと思って親近感!

SuperCollider と OSC

ここまでできたらさっそく SuperCollider との連携に取りかかります。SuperCollider は Open Sound Control(OSC)に対応しています。OSCはMIDIの代替となることを目指して開発されたオープンな通信プロトコルで、MIDIに比べてはるかに自由な通信が可能です。とはいえ、88鍵と127段階で表すMidiはシンセサイザーとともに広く普及したため未だにOSCが取って代わるには至っていません…。

SuperCollider はOSCに対応している、という言うよりは、OSCが実装の根幹に関わっています。SuperColliderはサーバーと言語(クライアント)に分かれていて、言語からOSCメッセージをサーバーに送信することで、サーバーから音がなるという仕組みになっています。そのため、他のアプリケーションからSuperColliderサーバーにOSCメッセージを送ることで、SuperCollider言語からメッセージを送るのと同様にサーバーから音を鳴らすことができます。

Sclang as a high-level client
Sclang as a high-level client

SuperCollider GUIDES: Client vs Server

Node.js と OSC

さて、node.js で OSC を使えるようにするモジュールですが、結構色々と公開されています。

Node.JS Modules : osc https://nodejsmodules.org/tags/osc

今回はこの中でもシンプルな osc-min を使ってみることにしました。

OSCを送受信するかんたんなスクリプトを書いてみる

まずパッケージ用のディレクトリを作成します。作成したらディレクトリに移動し、npm コマンドでプロジェクトを作成します。

$ npm init

パッケージの名前やバージョンなどを聞かれますので、ポチポチと入力したり飛ばしたりすると package.json が作成されます。作成されたらjsonファイルを開いて、依存モジュールの指定(dependencies)を追加します。最初はjsonファイルにdependenciesはありません。

{
  "name": "test_osc",
  "version": "0.0.1",
  "description": "ERROR: No README.md file found!",
  "dependencies": {
    "node-osc": "*"
  },
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": "",
  "keywords": [
    "osc"
  ],
  "author": "umbrellaprocess",
  "license": "BSD"
}

なんかエラーが書いてありますが、最初だから気にしない!あとで調べる。
package.json ができたら、npm install コマンドを実行すると、依存モジュールに指定した node-osc が自動で node_modules フォルダにインストールされます。

$ npm install
npm WARN package.json test_osc@0.0.1 No README.md file found!
npm http GET https://registry.npmjs.org/node-osc
npm http 304 https://registry.npmjs.org/node-osc
npm http GET https://registry.npmjs.org/jspack/0.0.1
npm http GET https://registry.npmjs.org/osc-min/0.0.5
npm http 304 https://registry.npmjs.org/jspack/0.0.1
npm http 304 https://registry.npmjs.org/osc-min/0.0.5
npm http GET https://registry.npmjs.org/coffee-script/1.3.0
npm http GET https://registry.npmjs.org/binpack
npm http 304 https://registry.npmjs.org/coffee-script/1.3.0
npm http 304 https://registry.npmjs.org/binpack
npm http GET https://registry.npmjs.org/bindings
npm http 304 https://registry.npmjs.org/bindings

> binpack@0.0.14 install /Users/name/Documents/nodejs/test_osc/node_modules/node-osc/node_modules/osc-min/node_modules/binpack
> node-gyp rebuild

  CXX(target) Release/obj.target/binpack/src/binpack.o
  SOLINK_MODULE(target) Release/binpack.node
  SOLINK_MODULE(target) Release/binpack.node: Finished
node-osc@0.1.2 node_modules/node-osc
├── jspack@0.0.1
└── osc-min@0.0.5 (coffee-script@1.3.0, binpack@0.0.14)

これで準備がおわり。

Node.js → SuperCollider

それでは、node.js から SuperCollider にOSCメッセージを送ってみます。まずSuperCollider側の準備です。OSCresponderNodeクラスでOSCメッセージを受信するレスポンダーを作ります。第一引数がnilなので、とりあえずどこからのOSCメッセージでも反応するはず。コードを選択し、Command + enter で実行しておきます。

o = OSCresponderNode(nil,"/test",{ arg time,responder,msg;
	"message receive:".postln;
	msg.postln;
}).add;

次にパッケージディレクトリに send.js を作成します。内容はこんな感じ。SClangのポート番号でクライアントを作成。5秒ごとに /test というパスに “Hello SuperCollider!” というメッセージを送っています(このようにURL風のメッセージ送信ができるのがOSCの特徴)。

var osc = require('node-osc');

var client = new osc.Client('127.0.0.1', 57120);

setInterval(function(){
  client.send('/test', "Hello SuperCollider!");
  console.log("messege send");
}, 5000);

実行してみます。

$ node send.js

SuperColliderのPost windowにメッセージが表示されました!

message receive:
[ /test, Hello SuperCollider! ]

SuperCollider → Node.js

次に、逆方向です。まずパッケージディレクトリに receive.js を作成します。内容はこちら。3000番ポートでOSCメッセージをリスンするサーバーを立てています。

var osc = require('node-osc/lib/osc');

var oscServer = new osc.Server(3000, '127.0.0.1');
oscServer.on("message", function (msg, rinfo) {
      console.log("message receive:");
      console.log(msg);
});

サーバーを実行します。

$ node receive.js

次に、SuperCollider側です。下記のコードを実行します。ローカルホストの3000番ポートに “Hello Node.js!” というメッセージを送ります。

m = NetAddr("127.0.0.1", 3000);
m.sendMsg("/test", "Hello Node.js!");

ターミナルにメッセージが表示されました!

message receive:
[ '/test', 'Hello Node.js!' ]

というわけで、めでたく node.js と SuperCollider の間で OSC メッセージのやり取りができました! SuperCollider がWebサーバーを手に入れることで、いろんな可能性が広がりそうですよね!とくに、GUIを作るのめんどいんで、HTMLでさっくり作りたいなぁ〜と。続報はまたいずれ。

node.jsとSuperColliderをOSCでつないでみる」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です