SuperColliderとopenframeworks

SuperColliderにメッセージ送るならofxOscじゃなくて、ofxSuperCollider使えば良いじゃん。とまあそうですが、ざっとソース見たところofxSuperColliderではSuperColliderからoscメッセージを受け取ることはできなさそうですので、基本的な手法をメモ。ほぼoFのサンプルまんまですが。

SuperCollider

(
SynthDef("oscTestSin",
{
	arg amp, pan = 0, outBus = 0, fxBus = 10, fx = 0.0, vol = 0.8;
	var env, signal, outSend, fxSend;
	env = Env.perc(0.001, 0.2, 1, -3);
	signal = SinOsc.ar(440, 0, amp) * vol;
	fxSend = signal * fx;
	outSend = signal * (1.0 - fx);
	Out.ar(fxBus,
		Pan2.ar(EnvGen.ar(env, doneAction: 2) * fxSend, pan)
	);
	Out.ar(outBus,
		Pan2.ar(EnvGen.ar(env, doneAction: 2) * outSend, pan)
	);
}).store;
)

(
var t,n,sin,pan;
~effectGroup = Group.tail(s);
~synthGroup = Group.tail(s);

t = TempoClock(210/60);
n = NetAddr("127.0.0.1",57124);

sin = Task({
	var pat,pat2,pattern;
	pattern = [1.0,0.0,1.0,0.0,1.0,0.1,1.0,0.0];
	pat = Pseq(pattern,inf).asStream;
	pat2 = Pseq(pattern,inf).asStream; //ここが問題
	loop({
		Synth.tail(~synthGroup, "oscTestSin",
			[\amp, pat.next, \outBus, 0, \fxSend, 10,  \vol, 1.0, \fx, 0.0]
		);
		n.sendMsg("/scSinReceive",pat2.next); //力技でメッセージ送っています
		(t.beatDur).wait;
	});
});
t.sched(0, {sin.start});
)

oF側(ofxOsc使います)

[testApp.h]

#ifndef _TEST_APP
#define _TEST_APP

#include "ofMain.h"
#include "ofxOsc.h"

#define HOST "localhost"
#define PORT 57124
#define NUM_MSG_STRINGS 20

class testApp : public ofBaseApp{
	public:	
		void setup();
		void update();
		void draw();
		
		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void windowResized(int w, int h);
	
		void oscReceive();
	private:	
		ofxOscReceiver receiver;
		int			current_msg_string;
		string		msg_strings[NUM_MSG_STRINGS];
		float		timers[NUM_MSG_STRINGS];
		float		sinAmp;
		int		flag;
};

#endif
[testApp.cpp]

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
	ofSetWindowTitle("oscTest");
	ofSetFrameRate(60);
	ofBackground(0,0,0);
	receiver.setup( PORT );
	flag = 0;
}
//--------------------------------------------------------------
void testApp::update(){
	oscReceive();
}
//--------------------------------------------------------------
void testApp::draw(){
	
	string buf;
	buf = "listening for osc messages on port" + ofToString( PORT );
	ofDrawBitmapString( buf, 10, 20 );

	ofDrawBitmapString("flag : "+ofToString(flag), 50, 60);
	ofDrawBitmapString("sinAmp : "+ofToString(sinAmp), 50, 70);
}
void testApp::oscReceive()
{
	
	// hide old messages おまじない
	for ( int i=0; i<NUM_MSG_STRINGS; i++ )
	{
		if ( timers[i] < ofGetElapsedTimef() )
			msg_strings[i] = "";
	}
	// check for waiting messages
	while( receiver.hasWaitingMessages() )
	{
		ofxOscMessage receiveSC;
		receiver.getNextMessage( &receiveSC );

		if(receiveSC.getAddress() == "/scSinReceive")
		{
			flag = 1;	//テスト用
			sinAmp = receiveSC.getArgAsFloat(0); //ここでfloat型に変換してsinAmpに代入します。
//getArgAsFloat(1)とかにしますとn.sendMsg("/scSinReceive",pat2.next,arg1);のarg1を読み込めます。
		}
	}
}	
//--------------------------------------------------------------
keyPressed以下略
}

駄目だなあ

sc3側で上手くoscメッセージを送る手法がよく分かっていませんので、シンセに送っているメッセージと同じものをコピーしてoFにも送っています。もっと上手くoscメッセージを送る手法があると思うのですが、help見てもよくわかりませんでした。

注意点としては、update関数内でoscメッセージ読み込むようにしますと、frameRate()で指定したレートで読み込みます。当然、指定レートでoscメッセージが更新されます。タイミングによってはズレが生じますのでチューニングというか注意が必要になります。