はじめに
TidalCyclesで曲を作ったあと、ProcessingやTouchDesigner、openFrameworksで音に同期させた映像をつくりたいことがあると思います。
今回はopenFrameworksを例としてTidalCyclesから送信されるOSCのログをopenFrameworksで取得・表示する方法を紹介します。
SuperColliderでの設定
まずSuperDirtを起動(SuperDirt.start;
)後、以下のコマンドをSuperColliderで実行します。
これによってTidalCyclesの全てのログはlocalhostのポート2020に送信されるようになります。
def.scd
// localhostの2020portにTidalCyclesのログ送る
(
var addr = NetAddr.new("127.0.0.1", 2020);
o = OSCFunc({
arg msg, time;
var latency = time - Main.elapsedTime;
addr.sendBundle(latency, msg)
},'dirt/play');
o.free; // ←これは不要かもしれません
o.fix;
)
openFrameworksのコード
コードはGithubにもおいてありますが、必要な機能のみに抑えたものを以下に記載しておきます。
今回はaddOnにofxOscを用います。
main:cpp
#include "ofMain.h"
#include "ofApp.h"
//========================================================================
int main( ){
ofSetupOpenGL(1500,600,OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp(new ofApp());
}
ofApp.h
#pragma once
#include "ofMain.h"
#include "ofxOsc.h"
// listening port
#define PORT 2020
// max number of rows
#define NUM_MSG_STRINGS 30
// number of seconds before message is deleted
#define TIMER 20
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
ofTrueTypeFont font;
ofxOscReceiver receiver;
int currentMsgString;
string msgStrings[NUM_MSG_STRINGS];
float timers[NUM_MSG_STRINGS];
};
ofApp.cpp
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
ofSetFrameRate(60); // run at 60 fps
ofSetVerticalSync(true);
// listen on the given port
receiver.setup(PORT);
}
//--------------------------------------------------------------
void ofApp::update(){
// hide old messages
for(int i = 0; i < NUM_MSG_STRINGS; i++){
if(timers[i] < ofGetElapsedTimef()){
msgStrings[i] = "";
}
}
// check for waiting messages
while(receiver.hasWaitingMessages()){
// get the next message
ofxOscMessage m;
receiver.getNextMessage(m);
// unrecognized message: display on the bottom of the screen
string msgString;
msgString = m.getAddress();
msgString += ":";
for(size_t i = 0; i < m.getNumArgs(); i++){
// get the argument type
msgString += " ";
msgString += m.getArgTypeName(i);
msgString += ":";
// display the argument - make sure we get the right type
if(m.getArgType(i) == OFXOSC_TYPE_INT32){
msgString += ofToString(m.getArgAsInt32(i));
}
else if(m.getArgType(i) == OFXOSC_TYPE_FLOAT){
msgString += ofToString(m.getArgAsFloat(i));
}
else if(m.getArgType(i) == OFXOSC_TYPE_STRING){
msgString += m.getArgAsString(i);
}
else{
msgString += "unhandled argument type " + m.getArgTypeName(i);
}
}
// add to the list of strings to display
msgStrings[currentMsgString] = msgString;
timers[currentMsgString] = ofGetElapsedTimef() + TIMER;
currentMsgString = (currentMsgString + 1) % NUM_MSG_STRINGS;
// clear the next line
msgStrings[currentMsgString] = "";
}
}
//--------------------------------------------------------------
void ofApp::draw(){
ofBackgroundGradient(100, 0);
// draw recent unrecognized messages
for(int i = 0; i < NUM_MSG_STRINGS; i++){
ofDrawBitmapStringHighlight(msgStrings[i], 10, 40 + 15 * i);
}
string buf = "listening for osc messages on port " + ofToString(PORT);
ofDrawBitmapStringHighlight(buf, 10, 20);
}
ログ確認
このコードでopenFrameworksのアプリを起動し、試しにTidalCyclesで以下のコードを実行してみます。
once $ s "bd" # gain 1.5
すると、アプリの画面に以下のようなログが表示されるかと思います。
/dirt/play: s:cps f:0.3625 s:cycle f:891.794 s:delta f:2.75862 s:gain f:1.5 s:n f:0 s:s s:bd