読者です 読者をやめる 読者になる 読者になる

アールテクニカ地下ガレージ

アールテクニカ株式会社の製品開発・研究開発・日々の活動です

Novation LauchpadとopenFrameworksを使ってResolumeのVJコントローラを作る : コーディング編

C++ VJ openFrameworks

VJコントローラを作る記事第2回です。

第1回はこちら。
Novation LauchpadとopenFrameworksを使ってResolumeのVJコントローラを作る: セットアップ編 - アールテクニカ地下ガレージ

さっそく簡易的なコントローラを作っていきます。
今回作るのはResolumeのレイヤーの不透明度をLaunchpadでコントロールするものです。

Launchpadのパッドの縦方向をレイヤー番号、横方向を不透明度とします。
レイヤーの不透明度に合わせてLEDが光り、パッドを押すとレイヤーの不透明度が変化するという操作にします。
図にすると、こういうレイアウトです。
f:id:tobetchi-at:20160930152501p:plain:w450

OSCアドレス取得

ResolumeのOSCアドレスの調べ方は、
・ResolumeのApplication OSC Mapで調べる
Resolume OSCアドレス一覧 - アールテクニカ地下ガレージを参照する
です。
レイヤーの不透明度のアドレスは以下です。

/layer1/video/opacity/values Int

レイヤー番号はアドレスに組み入れられており、レイヤー2は/layer2/video/opacity/valuesとなります。
このOSCアドレスを送受信することでレイヤーの不透明度を操作できるようになります。

OSCの送受信

ResolumeとのOSCの送受信方法です。
OSCの通信はofxOSCアドオンを使います。

OSC受信

ofxOscReceiverクラスでOSCメッセージを受信します。
setup() でResolumeのOSC出力ポート番号を設定しておきます。

ofxOscReceiver receiver;
receiver.setup(PORT);

以下のようにイテレータを回し、OSCメッセージ(ofxOscMessageクラス)の取得ができます。

while (receiver.hasWaitingMessages()) {
    ofxOscMessage m;
    receiver.getNextMessage(m);
    // アドレスを取得
    string address = m.getAddress();
    // 0番目のInt型の引数の値を取得
    int arg = m.getArgAsInt32(0);
}

OSC引数の値は型ごとに取得メソッドが違うので、型に合ったメソッドで取得します。

getArgAsInt(index);    // Int型の値を取得
getArgAsFloat(index);  // Float型の値を取得
getArgAsString(index); // String型の値を取得

取得したいOSCアドレスは文字列マッチで補足します。
正規表現でレイヤー番号も取得可能です。

std::regex re("/layer([0-9]+)/video/opacity/values");

OSC送信

ofxOscSenderクラスで送信します。

ofxOscSender sender;
sender.setup("localhost", 7000);

setup()でホスト名・IPとポート番号を設定します。

setAddress()でアドレスを指定し、addFloatArg()で引数の値を設定してsendMessage()でメッセージを送信します。

ofxOscMessage m;
m.setAddress("/layer1/video/opacity/values");
m.addFloatArg(0.5);
sender.sendMessage(m);
m.clear();

引数の値の設定も型ごとにメソッドが用意されています。

addIntArg(int);       // Int型の値を追加
addFloatArg(float);   // Float型の値を追加
addStringArg(string); // String型の値を追加

MIDI送受信

次はLaunchpadとMIDIの送受信をします。
MIDIの通信はofxMidiアドオンを使います。

MIDI受信

ofxMidiInクラスでの接続は以下のようになります。

ofxMidiIn midiIn;
midiIn.listPorts();
midiIn.openPort("Launchpad");
midiIn.addListener(this);

openPort() にポート番号もしくはポート名を指定してLauchpadに接続します。
MIDIデバイスのポート番号とポート名の調べ方は、listPorts() を実行すると、MIDIデバイスのポート番号とポート名がログに出力されるので、それを使います。
addListener() で受信側のオブジェクトをリスナに登録します。

また、midiIn.setVerbose(true) をしておくと、受信したMIDIメッセージがログに出力されるようになります。

MIDIメッセージの受信は、
ofxMidiListenerクラスを継承し、

class ofApp : public ofBaseApp, public ofxMidiListener {
    ...
    ofxMidiIn midiIn;
    void newMidiMessage(ofxMidiMessage& msg);
};

newMidiMessageメソッド内で受け取ります。

void ofApp::newMidiMessage(ofxMidiMessage& msg) {
    ofxMidiMessage::getStatusString(msg.status)
    msg.pitch;
    msg.velocity;
    msg.channel;
    msg.control;
    msg.value;
    msg.deltatime;
}

ピッチやベロシティなど各種パラメータが受けとれます。
msg.bytesで生のバイトデータを取得することも可能。
msg.deltatime は前のメッセージからの経過時間。

MIDI送信

MIDIメッセージの送信はofxMidiOutクラスを使います。
MIDI受信の時のようにopenPort()でMIDIデバイスに接続します。

ofxMidiOut midiOut;
midiOut.openPort(port);

MIDIメッセージの送信はノートオン・オフなどのメッセージが用意されています。
sendMidiByte()で生バイトを送ることも可能。

midiOut.sendNoteOn(channel, pitch, velocity);
midiOut.sendNoteOff(channel, pitch, velocity);
midiOut.sendProgramChange(channel, value);
midiOut.sendControlChange(channel, control, value);


実際にLaunchpadのパッドを押してMIDIメッセージを受信すると、以下のようにノート番号が振られているのが分かります。
これでどのパッドが押されたか判別可能となります。

0 1 2 3 4 5 6 7
16 17 18 19 20 21 22 23
32 33 34 35 36 37 38 39
48 49 50 51 52 53 54 55
64 65 66 67 68 69 70 71
80 81 82 83 84 85 86 87
96 97 98 99 100 101 102 103
112 113 114 115 116 117 118 119

逆にノートオンする信号を送ればパッドのLEDを光らせることができます。
左下のパッドを光らせるには、

sendNoteOn(1, 112, 127);

パッドのLEDを消すには、

sendNoteOn(1, 112, 0);

といった具合です。

これでResolumeの操作とLaunchpadの操作が可能になったので、あとは片方の操作がもう片方に反映されるようにコードを繋いでいって出来上がりです。

という訳で今回のコードはこちら。

Simple VJ Controller: Resolume + Launchpad + openF ...


Author

とべっち

ART Teknika佐賀スタジオマネージャ、プログラマ。WebプログラマからiOSプログラマへ転身。VJとしても活動中。

スポンサーリンク