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メッセージが更新されます。タイミングによってはズレが生じますのでチューニングというか注意が必要になります。