とりあえずosc4nodeとSC3


そろそろブラウザからもSCにOSCメッセージ送りたいですよね?それならosc4node使いましょう!すごい簡単にOSCメッセージの送受信が実装できます、素晴らしい!!

準備

Node.jsの環境構築などはググれば沢山ありますので、割愛。
osc4nodeについては
hideyukisaitoさんのblog
osc4node – GitHub

使う

SC側

とりあえず、OSCメッセージの送受信を実装しましょう。

/*
*	osc4node test
*/
/*
*	osc setting
*/
(
	//receive osc messages from node
	~oscReceive = NetAddr("127.0.0.1", 57120);
	o = OSCresponder(nil, '/sc3/synth', {
		arg t, r, msg;
		//msg[1]にシンセ名を送っているため、ここで分岐
		switch(msg[1],
			//kickの場合
			\osc4node_kick, { s.sendMsg("/s_new",msg[1],s.nextNodeID,0,0 ); },
			//sinの場合
			\osc4node_sinosc, {
				//シンセ作成、価変更、解放の分岐
				switch(msg[2],
					\play, { s.sendMsg("/s_new",msg[1],x = s.nextNodeID,0,0); },
					\set, { s.sendMsg("/n_set", x, "freq", msg[3]); },
					\free, { s.sendMsg("/n_free", x); }
				);
			}
		);
		[t,msg].postln;
	}).add;

	// send osc messages 2 node
	~oscSend = NetAddr("127.0.0.1", 57124);
	//osc4node_kick1のSendReply.krにて一旦サーバ側へOSCメッセージ送信。ここでメッセージを受信する
	OSCresponder(nil, '/scServer/4node', { 
		arg t, r, msg;
		//ここでnode側にメッセージ送信
		~oscSend.sendMsg('/sc3/2node', msg[3]);
		[t,msg].postln;		
	}).add;
	
	//check
	NetAddr.localAddr;
)

/*
*	synth def
*/
(
	SynthDef("osc4node_kick",{
		arg pan = 0, outBus = 0, clip_amp = 1.0, white_amp=0.0, filter_freq=1.0;
		var env_mul, env_freq, signal, outSend;

		env_mul = Env.new([0.5, 1, 0.5, 0], [0.005, 0.06, 0.26], [-4, -2, -4]);
		env_mul = EnvGen.ar(env_mul ,doneAction:2);
		env_freq = Env.new([110, 59, 29], [0.005, 0.29], [-4, -5]);
		env_freq = EnvGen.ar(env_freq).midicps;
		
		signal = SinOsc.ar(env_freq, 0, env_mul);
		signal = signal + PinkNoise.ar(white_amp);
		signal = LPF.ar(signal, env_freq*filter_freq, env_mul);
		signal = signal + SinOsc.ar(env_freq,0.5,env_mul);
		outSend = signal * clip_amp;
		outSend.clip2(1);
		//一旦scサーバに値を送る
		SendReply.kr(Impulse.kr(20), "/scServer/4node",[outSend.()]);

		//outSend.poll(Impulse.ar(20),"/sc3/4node",1);
		//pollで/trにugenの出力値を送ったりもできるけれど、受信後の処理が面倒かも

		Out.ar(outBus,
			Pan2.ar(outSend, pan)
		);
	}).store;

	SynthDef("osc4node_sinosc",{
		arg pan = 0, outBus = 0, freq = 440;
		var signal;
		signal = SinOsc.ar(freq,0,0.4);
		Out.ar(outBus,
			Pan2.ar(signal,pan);
		);
	}).store;
)
/*
*	osc clear ?
*/
OSCresponder.initClass;
Nodeサーバ側

osc4nodeの詳しい使い方は、@hideyukisaitoさんに直接聞くか、READMEとexampleを参照しましょう。socket.ioのバージョンによってちょっと書き方が違うっぽいです。
express使っていますので、app.jsとかです。

/**
 * osc4node test by ksy.
 */

var express = require('express'),
	socketIO = require('socket.io'),
	osc = require('osc4node');

var app = module.exports = express.createServer();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
});

app.configure('production', function(){
  app.use(express.errorHandler()); 
});

// Routes

app.get('/', function(req, res){
  res.render('index', {
    title: 'osc4node for sc3'
  });
});

app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

// osc4node setting
var oscserver = new osc.Server(57124,'127.0.0.1');
var oscclient = new osc.Client('127.0.0.1',57120);

//socket.io
var io = socketIO.listen(app);

////connection
io.sockets.on('connection', function(socket){
	console.log("connection");
	socket.on('message', function(data){
		console.log(data);
		io.sockets.emit('message', { value :data.value });
	});

	//oscmessage send 2 sc
	socket.on('oscmessage', function(data){
		io.sockets.emit('oscmessage', { address: data.address,message: data.message });
		var mes = new osc.Message(data.address,data.message);
		oscserver.send(mes, oscclient);
	});

	//oscmessage receive from sc
	oscserver.on('oscmessage', function(msg, rinfo){
		io.sockets.emit('oscreceive',{
			address: msg._address,
			typetag: msg._typetag,
			value:	msg._args[0].value,
			args: msg.argments
		});
	});
	
	//disconnect
	socket.on('disconnect', function(){
		console.log("disconnection");
	});
});
Nodeクライアント側

./public/javascript/xx.jsとか。かなり適当。スライダー使うため、途中でjQueryに切り替えてます。。。これに合わせて、view/*.ejsも作成します。

$(function(){
//自分の環境に
var socket = io.connect('xxx.xxx.xxx.xxx:3000');

socket.on('connect', function(msg){
	console.log("client: connection");
	document.getElementById("connectMsg").innerHTML = "your sessisonID is:" + socket.socket.transport.sessid;
});

socket.on('message', function(msg){
	document.getElementById("receiveMsg").innerHTML = msg.value;
});
socket.on('oscmessage', function(msg){
	document.getElementById("receiveMsg").innerHTML = "address from client:" + msg.address + "| message:" +  msg.message;
});

// receive message from sc
socket.on('oscreceive', function(msg){
	osc_address = msg.address;
	switch(osc_address){
	case "/sc3/test":
		$('#receiveFromSc').html("address from sc:" + msg.address + " | value: " + msg.value);
		break;
	case "/sc3/2node":
		$('#receiveFromSc').html("address from sc:" + msg.address + " | value: " + msg.value);
		break;
	default:
		break;
	}
});

//send osc message 2 SC
$('#playKick').click(function(){
	socket.send('message', { message: "test send"});
	socket.emit('oscmessage', { address: "/sc3/synth",message: [ "osc4node_kick","play"] });
});
$('#playSin').click(function(){
	socket.emit('oscmessage', { address: "/sc3/synth",message: [ "osc4node_sinosc","play"] });
});
$('#freeSin').click(function(){
	socket.emit('oscmessage', { address: "/sc3/synth",message: [ "osc4node_sinosc","free"] });
});
function discon(){
	socket.emit('message', { value: "client: discon" });
	socket.disconnect();
};

//UIs
$(".slider").slider({
	max:880,
	min:440,
	step:10,
	value:440,
	orientation:'vertical',
	slide: function( event, ui ){
		$("#slideAmount").val(ui.value);
		socket.emit('oscmessage', { address: "/sc3/synth",message: [ "osc4node_sinosc","set", ui.value] });
	}
});
$("#slideAmount").val($(".slider").slider("value"));
});

いじょう

とりあえず暫定で。
canvasとかを使用していかしたGUI作ってから載せようと思いましたが、面倒なので全然いじっていません。exampleにいかしたGUIサンプルがあります!
これでブラウザからoscの送受信がさくっとできますので、あとはweb audio apiかなんかでストリーミングできれば面白いかとー。

たとえば、

  • ライブ会場とかでお客さんにiPhoneとか使ってパラメータいじってもらうにはクライアントソフトが必要でした。しかし、これならブラウザがあればおkですから準備不要ですね。
  • 数人でライブする場合、リアルタイムで値が反映されますので状況把握しやすいかと。
  • SCならlinuxでも動きますので、サーバ建ててオンラインで色々できそうですね!