環境/macOS Montery Apple Silicon Mac

TidalCyclesの演奏をリアルタイムで他のアプリに接続させるには、Open Sound Control (OSC)という通信プロトコルを利用します。

以前、Tidal CyclesとProcessingをOSCで通信・ビジュアライズさせる方法を記事にしました。その方法と考え方は一緒です。

本記事では、送信側のSuperCollider(Tidal Cycles)と受信側 openFrameworks という関係にて、送信側の設定は以前の記事と同じ、受信側 openFrameworksのOSC設定と簡単なビジュアライズを学んでいきます。
送信側のOSC設定は下記を参照ください。

前編/Tidal Cycles の演奏を Processing でビジュアライズする方法 〜前編〜 OSCの利用

ーーーーー
Index/目次
プロジェクトにofxOscアドオンを組み込む
受信側 openFrameworks のコードを記述
openFrameworks 側で受信したメッセージを確認
コード例/”kick”は赤、”clap”は青
あとがき
ーーーー

プロジェクトに ofcOsc アドオンを組み込む

新規プロジェクトを制作する場合、projectGeneratorアプリケーションを開き、addonsにてofxOscを選択しGenerateをクリックします。

途中のプロジェクトから進める場合は、下記通り、importボタンからプロジェクトフォルダを選択しaddonsにてofxOscを選択しUpdateをクリックします。

Success! と表示されたら、IDEでファイルを開きます。

受信側 openFrameworks のコードを記述

openFrameworksで先ほど追加した、ofxOscをインポートさせ、ポート等や受信メッセージを確認するコードを記述します。

【 main.cpp 】
デフォルトのまま

【 ofApp.h 】


#pragma once

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

//受信ポートの設定
#define PORT 2020

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();
        //メッセージをまとめるファンクション
        void msgOscAll(ofxOscMessage m);

		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 mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    
        //OSCレシーバーをインスタンス化
        ofxOscReceiver receiver;
        //メッセージを入れるための文字列
        string msgStrings;
};

【 ofApp.cpp 】


#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    //フレームレート
    ofSetFrameRate(60);
    //ポート接続
    receiver.setup(PORT);
}

//--------------------------------------------------------------
void ofApp::update(){
    //メッセージがある場合の処理
    while (receiver.hasWaitingMessages()) {
        ofxOscMessage m;
        receiver.getNextMessage(m);
        msgOscAll(m);
    }
}
//OSCメッセージの内容の型を合わせて出力する関数
void ofApp::msgOscAll(ofxOscMessage m){
    msgStrings = m.getAddress();
    for(int i = 0; i < m.getNumArgs(); i++){
        //文字間のスペース
        msgStrings += " ";
        //msgStringsに追加していくif文
        if (m.getArgType(i) == OFXOSC_TYPE_STRING){
            //String型の場合そのまま文字列に追加
            msgStrings += m.getArgAsString(i);
        }
        else if (m.getArgType(i) == OFXOSC_TYPE_INT32){
            //int型の場合、Stringに変更して文字列に追加
            msgStrings += ofToString(m.getArgAsInt32(i));
        }
        else if (m.getArgType(i) == OFXOSC_TYPE_FLOAT){
            //float型の場合、Stringに変更して文字列に追加
            msgStrings += ofToString(m.getArgAsFloat(i));
        }
    }
    //コンソールに出力
    cout << msgStrings << endl;
}

//----続くファンクションは省略

<コードの解説/ofApp.h>

ofApp.h にて、ofApp.cppに記述する下準備を行います。

送信されてくるメッセージを受信するため、PORT 2020で受信ポートの設定を行います。

受信したメッセージの型を揃え、文字列にまとめる関数として、void msgOscAll(ofxOcsMessage m); ファンクションを作成追加しておきます。

ofxOscReceiver receiver; にてOSCレシーバーをインスタンス化

string msgStrings; にてメッセージを入れる文字列(String)を作成しておきます。

<コードの解説/ofApp.cpp>

ofApp.cpp では、setupにて、フレームレート ofSetFrameRate(60); ポートの接続 receiver.setup(PORT); を行い、

update()にて、メッセージがある場合の処理、ある場合はmsgOscAll(m);でファンクションを呼び出し、引数 m の値を入れます。

msgOscAll(ofxOscMessage m)のファンクションでは、ofApp.h で準備したmsgStringsに文字を追加していきます。
まず、送られてきたアドレスを msgStrings = m.getAddress(); にて msgStrings 入れ、if文(条件文)でString型・int型・float型を特定し、全てString型に変えたものを msgStringsに追加していきます。

openFrameworks 側で受信したメッセージを確認

送信側のSuperColliderとTidalCycles(Atom)を起動します。
以前の投稿にて、SuperColliderから実行した内容をもとにポート番号は同じ2020ポートを使用します。
確認のため、下記、SuperColliderの記述です。

内容の詳細/前編/Tidal Cycles の演奏を Processing でビジュアライズする方法 〜前編〜 OSCの利用

openFrameworksにてコンソールを表示しておきます。
上部メニューバーより、 View -> Debug Area -> Actve Console と選択します。

先ほど作ったopenFrameworksのコードを実行します。

最後に、Atomにて、下記サンプルを演奏します。


d1 $ n "0*4" # sound "kick"

コンソール上に送られてきたOSCメッセージが表記されます。

Processingとの連携でも確認した内容と同じ順番にメッセージが届いているのがわかります。
Processing側で受信したメッセージを確認

これらメッセージを利用して、openFrameworksで映像を制作します。

コード例/”kick”は赤、”clap”は青

前回Processingの時と同様に、音源の種類によって画面の色を変えるコード例を行います。
下記TidalCyclesコードにてkickの場合は赤、clapは青とします。


d1 $ n "0*4" # sound "kick clap"

下記よりopenFrameworksコード

【 main.cpp 】
デフォルトのまま

【 ofApp.h 】


#pragma once

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

//受信ポートの設定
#define PORT 2020

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();
        //メッセージ受け取る
        void msgOscAll(ofxOscMessage m);

		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 mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    
        //OSCメッセージをインスタンス化
        ofxOscReceiver receiver;

        string sInst;
        string name;
};

【 ofApp.cpp 】


#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    //フレームレート
    ofSetFrameRate(30);
    ofBackground(0, 0, 0);
    //ポート接続
    receiver.setup(PORT);
    sInst = "";
}

//--------------------------------------------------------------
void ofApp::update(){
    //メッセージがある場合の処理
    while (receiver.hasWaitingMessages()) {
        ofxOscMessage m;
        receiver.getNextMessage(m);
        msgOscAll(m);
    }
}
//全てのメッセージ受け取る関数
void ofApp::msgOscAll(ofxOscMessage m){
    for(int i=0; i < m.getNumArgs(); i++){
        //Stringの場合nameに文字を入れる
        if (m.getArgType(i) == OFXOSC_TYPE_STRING){
            name = m.getArgAsString(i);
            }
        //nameがsの場合次の文字列をsInstに入れる
        if (name == "s") {
            sInst = m.getArgAsString(i+1);
        }
     }
}

void ofApp::draw(){
    ofFill();
    //kickの場合は赤
    if (sInst == "kick") {
        ofSetColor(180, 30, 30);
        ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight());
    }
    //clapの場合は青
    else if (sInst == "clap"){
        ofSetColor(30, 30, 180);
        ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight());
    }
}

上記を実行するとkickが赤、clapが青になります。

あとがき

Processingとの通信を行なった際に利用した内容に近いコードで記述しています。
また、ofxOsc にはその他いろんなクラスやファンクションが用意されているので利用してみるのも面白いです。
参考/openFrameworks documentation ofxOsc

barbe_generative_library

Beyond Interaction[改訂第3版]
クリエイティブ・コーディングのためのopenFrameworks実践ガイド

beyond-interaction-image

初版/ 2020.10.14
ページ数/280ページ
出版社/ビー・エヌ・エヌ新社
言語/日本語

【Amazon.co.jp で購入】

ーーーーー

”Books”では、”barbe_generative_Library”として、
barbe_generative_diary の創作において実際に購入し、読んだ本を紹介します。

ーーーーー