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

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

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

Novation LauchpadとopenFrameworksを使ってResolumeのVJコントローラを作る : アドバンスド編

C++ VJ openFrameworks

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

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

前回は簡易的なVJコントローラを作成しました。
パッドを押すとレイヤーの不透明度が変化し、パッドのLEDが光るというものです。

実は前回の実装には処理が遅延してしまうという問題があります。
実際にパッドと素早く押し続けたり、Resolume側で操作を続けると処理が遅延したりフリーズしたりします。

遅延・フリーズ問題

原因は何かというと、Launchpadのチップの処理性能の問題です。
この事はリファレンスマニュアルに記載されており、

  • 1秒間に処理できるMIDIメッセージは400メッセージ
  • 80ある全てのLEDを更新するのに200msかかる
  • 1秒間に5回までしか全書き換えができない

となっています。

Launchpadが処理できる以上のMIDIメッセージを送信して処理が遅延してしまっていた、という訳です。

そこで、パッドを押したりOSCの受信があれば逐一MIDIメッセージを送信する、という前回のコードの実装方法を変更し、LEDのOn/Off状態をバッファに溜めておき、安全なリフレッシュレートで一括で変更する、という方針にします。

int ledBuf[64] = {};  // LEDのOn/Offのバッファ
int refreshRate = 200; // バッファを送信するまでの時間(ms)
int prevTime = 0;
...

void ofApp::update() {
    int time = ofGetElapsedTimeMillis();

    if(time - prevTime > refreshRate) {
        ledRefresh(ledBuf); // バッファの内容をMIDI送信する
        prevTime = time;
    }
    
    ...

    // 受信したOSCメッセージを処理する箇所
    for (int i=0; i<ledWidth; i++) {
        set = i <= x ? 127 : 0;
        ledBuf[y*ledWidth+i] = set; // 逐一MIDI送信していたのをバッファに溜めるようにする
    }
    ...
}

...

// 8x8のLEDを全更新する
void ofApp::ledRefresh(int data[]) {
  for(int i=0,size=ledWidth*ledHeight; i<size; i++) {
    midiOut.sendNoteOn(1, midiMap[i], data[i]);
  }
}

高速モード

通常80個のLEDパッドを更新するのに200msかかるわけですが、ノートオンのChannelに3を指定すると2倍高速になるモードが用意されています。

midiOut.sendNoteOn(3, 1st_led_velocity, 2nd_led_velocity);
midiOut.sendNoteOn(3, 3rd_led_velocity, 4th_led_velocity);
midiOut.sendNoteOn(3, 5th_led_velocity, 6th_led_velocity);
...

このようにLEDのノート番号を指定せずに、1つのMIDIメッセージに2つ分のベロシティを指定し、頭から順番に送信していきます。
指定する順番は、
1. 8x8のパッドを左から右へ、上から下へ
2. 右側のシーンランチボタンを上から下へ
3. 上側のAutomap/Liveボタンを左から右へ
となります。
モードの終了はノートオン、ノートオフ、コントロールチェンジのいずれかの通常のMIDIメッセージを送信します。

先程のサンプルコードの全LEDを更新するledRefresh()メソッドを高速モードに書き換えるとこのようになります。

void ofApp::ledRefreshRapid(int data[]) {
  for(int i=0,size=ledWidth*ledHeight; i<size; i++) {
      midiOut.sendNoteOn(3, data[i], data[i+1]);
      i++;
  }
  midiOut.sendNoteOn(1, 127, 0);
}

改良したコードはこちら。
Simple VJ Controller (refine): Resolume + Launchpad + openFrameworks

その他のLaunchpadの機能

LEDの色を変更

パッドの中に赤と緑の2つのLEDが入っており、LEDの強弱を変化させることで色を変更することができます。
各LEDは3段階の輝度が用意されています。

0 Off
1 低輝度
2 中輝度
3 高輝度

各LEDの変更はノートオンのベロシティの5-4ビット目に緑のLEDの輝度、1-0ビット目に赤のLEDの輝度を指定します。
以下はビット演算が苦手な人向けのベロシティ計算式です。

Velocity = (16 x Green) + Red + Flags
Flags
12 通常モード
8 LEDを点滅させる時のフラグ
0 ダブルバッファを使う場合

代表的なカラーサンプルコードです。

sendNoteOn(1, key, 13); // 赤色 低輝度
sendNoteOn(1, key, 15); // 赤色 高輝度
sendNoteOn(1, key, 29); // オレンジ 低輝度
sendNoteOn(1, key, 63); // オレンジ 高輝度
sendNoteOn(1, key, 62); // 黄色 高輝度
sendNoteOn(1, key, 28); // 緑色 低輝度
sendNoteOn(1, key, 60); // 緑色 高輝度

LED点滅

ノートオンのベロシティに点滅させるフラグを立てた場合、そのLEDを点滅させることができます。

sendControlChange(1, 0, 40); // 自動点滅
sendControlChange(1, 0, 32); // 手動点滅(On)
sendControlChange(1, 0, 33); // 手動点滅(Off)

全てのLEDをOff

sendControlChange(1, 0, 0);

その他にもリファレンスマニュアルには、

  • 表と裏のバッファを入れ替えることでLEDの更新を一瞬で行なったように見せるダブルバッファ
  • LEDを高速に明滅させることで中間の明度を表現するDurty Cycle

などが解説されています。

Lauchpad後継機種

現在は初代Lauchpadに代わり、Lauchpad S、Lauchpad Pro、Lauchpad MK2といった後継機種が登場しています。
低速だった初代Lauchpad比べ後継機種ではCPUコアの処理能力が上がり、Lauchpad Sでは40倍高速にMIDIを扱えるようになりました。
また、テキストスクロールなど新しい機能も追加され、Launchpad Proでは赤緑に加えて青色LEDが使えるようになっています。

まとめ

3回に渡ってVJコントローラ作成方法を解説しました。
レイヤーの不透明度を操作するだけの簡易機能ですが、他のOSCアドレスを使えばクリップ選択やエフェクトの操作、BPMと連動したシーケンサーなど多彩な操作が可能になります。
私自身、改良したコントローラを現場で便利に使っています。
今回はResolumeとLaunchpadの組み合わせですが、他のOSC対応ソフトやAKAI APC40などのパッドコントローラでも手法は同じです。
腕に覚えのある方は自作のコントローラを作成してみてはいかがでしょうか。

参考文献


Author

とべっち

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

スポンサーリンク