BLOCKSとLittleFootを使ってMIDIコントローラーをつくる


本記事JUCE Advent Calendar 2017の12月12日向けに投稿した記事です。

JUCEに関しては他の参加者の皆さんが書かれているので今日は少し脱線して、JUCEの開発元ROLIが開発・販売しているプログラマブル楽器インターフェースBLOCKSについて書いてみます。
BLOCKSにもLightpad BlockやSeaboard Blockなどありますが、ここではLightpad Blockを扱います。

そもそもBLOCKSって何ができるんだっけ?

  • 圧力などのパラメーターが取れる
  • 光る
  • BLE-MIDIがついてる
  • DNA端子を使ってBLOCKS同士で接続できる
  • Noiseで遊ぶと楽しい

これだけではありません!
BLOCKSはLittleFootというBLOCKS用のプログラミング言語を用いて自分好みのMIDIコントローラーを作ることができます。

余談 ちょうどいいMIDIコントローラーが無い問題

話は変わりますが、私はCycling'74 Max7やAbleton Liveを使用して音や映像などを制御することが多々あります。
Maxをつかってライブパフォーマンスをする人も一度は思ったことがあるんじゃないでしょうか。

ちょうどいいMIDIコントローラーが無い!!

つまみの数やボタンの並び方、大きさや重さなどがバッチリのMIDIコントローラーが無いんです。
機能に対して不必要にボタンやノブが多いと間違いの元になりますし、できれば軽く小さい方がいい。光るなどのフィードバックがあればより分かりやすい。

そう、そこでBLOCKSです!

開発環境

前置きが長かったですが、こんなモチベーションでLittleFootを触り始めました。
開発環境構築についてです。
少し前まではこちらの記事"ROLI BLOCKSプログラミング はじめの一歩"のままで開発できたのですが、現在は少し状況が変わっています。
Blocks DashboardというソフトにLittleFootのエディター機能や簡易的なログ機能がついていましたが、最新(v1.1.1)ではエディターもログ機能も無くなっています。
どうもROLIとしてはBlocks Dashboardを開発者用ではなく一般ユーザーがBlocksの機能を簡単に切り替えられるソフトにしたいようです。LittleFootエディターは別のソフトとして近日リリースするとのことです。
なので現状のLittleFoot開発環境としては、

  • 好きなテキストエディターでLittleFootプログラムを書いてからBlocks Dashboardで読み込む
  • 古いv0.2.3くらいのBlocks Dashboardをどうにかして入手する(ROLIのサイトからはダウンロードできなくなっているようです...)

のどちらかになります。
今回は前者のテキストエディタで開発する方法をとります。
また、その場合はログ機能が使えません。不便なのでなんとかする方法を考えます。

LittleFootを書いてみる

LittleFootについてのリファレンスで一番まとまっているのはこちらだと思います。

私のLittleFoot練習用リポジトリに簡単なコードも載せてます。リポジトリにはLightpad Block用フォルダとDeveloper Control Block用フォルダがありますが、今回はLightpad Blockのみ扱います。
とりあえずXYパッドをつくってみます。
X軸、Y軸、Z軸(プレッシャー)の値をMIDI CCで送信します。
短いコードなので全文のせます。

XYZPad.littlefoot
/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

int ccX;
int ccY;
int ccZ;

void initialise()
{
}

void touchStart (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 5.0);
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchMove (int index, float x, float y, float z, float vz)
{
    addPressurePoint (0xFFFFFFFF, x, y, z * 5.0);
    ccX = int(map(x, 0.07, 1.93, 0.0, 127.0));//X座標のデータ(0.07~1.93)を0~127に変換
    ccY = int(map(y, 0.07, 1.93, 0.0, 127.0));//Y座標のデータ(0.07~1.93)を0~127に変換
    ccZ = int(map(z, 0.0, 1.0, 0.0, 127.0));//Z(プレッシャー)のデータを(0.0~1.0)を0~127に変換
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void touchEnd (int touchIndex, float x, float y, float z, float vz)
{
    ccX = 0;
    ccY = 0;
    ccZ = 0;
    sendCC ((channel - 1), 60, ccX);//X座標 CC60
    sendCC ((channel - 1), 61, ccY);//Y座標 CC61
    sendCC ((channel - 1), 62, ccZ);//プレッシャー  CC62
}

void repaint()
{
    clearDisplay();//前フレームのデータを消して画面をまっさらな状態にする
    drawPressureMap();//指の軌跡を描画する
    fadePressureMap();//古い軌跡から徐々にフェードアウト
    drawNumber(ccX, 0xffff0000, 0, 0);//ccXを赤色で表示
    drawNumber(ccY, 0xff00ff00, 0, 5); //ccYを緑色で表示
    drawNumber(ccZ, 0xff0000ff, 0, 10);//ccZを青色で表示
}

まず冒頭部分

/*
<metadata description="Minimal XYZ Pad" details="XY pad with the addition of pressure (Z), sending out MIDI CC. You can set MIDI channel."
          target="Lightpad" 
          tags="MIDI;Controller;">
    <variables>
        <variable name="channel" displayName="MIDI Channel" type="int" min="1" max="16" value="1" displayMode="stepper" tooltip="The MIDI channel that values are sent on" />
    </variables>
</metadata>
*/

こちらはこのLittleFootプログラムについての基本的な情報を記述やユーザー可変の変数を定義する箇所です。
さきほどのプログラムをBlocks Dashboardで開くとこう見えます。

画面下のチェックが入っているのが読み込んだプログラムXYZPadです。
XYZPadの下に"Minimal XYZ Pad"と書いてあるのが見えます。これは<metadata>タグのdescriptionに対応しています。
detailsに対応しているのは画面左に確認できます。
targetはBLOCKSシリーズの何用のものか(Lightpad Block用やSeaboard Block用など)を指定する箇所です。

  • All
  • Lightpad
  • Seaboard
  • Loop
  • Live

が指定できるようです(他にもあるかもしれません)。
<variables>タグで指定した変数はユーザーがBlocks Dashboardの中で変更できるようになります。
MIDIチャンネルやノートナンバーなどを指定できるようにしておくと便利です。
ここではMIDIチャンネルを指定できるようにしています。

実際のコード部分を見ていきます。
LittleFootは初期化時にinitialise()、タッチイベント時touchStart()/touchMove()/touchEnd()、描画の更新のたびにrepaint()が呼ばれるのが基本です。
描画の更新レートは25fpsくらいだったと記憶してるんですが、ドキュメントの記述が見つかりません(昔どこかでみたと思うんですが...)。
タッチイベント時にグローバル変数ccX,ccY,ccZを座標の値から変更してからsendCC()でCCを送信するようになっています。
また、現在送信しているCCの値をLightpadに表示させています。
これをつかえば一応プリントデバッグ的なことができますね。

実際に動かしてみるとこんな感じになります。

Lightpadの原点は左上です。
表示されている数字は上からX,Y,ZのMIDI CCの値です。
もちろん、BLE-MIDIやUSB-MIDIで接続すればCCを受けることも出来ます。
これを応用していけばとりあえずデバッグもできそうですし、MIDIコントローラーをつくっていけそうです。
ちなみに、さきほどのLittleFoot練習用リポジトリには他にドラムパッドのコードも載せています。

実例 BLOCKSでモジュラーシンセをコントロールする

手前味噌ですが、BLOCKSからCVを出してモジュラーシンセのコントロールをしたりするプロジェクト BLOCKSmodularをやっています。

この記事と同様のアプローチでLittleFootプログラムを書いてMIDIの通信をさせることで実現しています。この動画では、LightpadからのMIDIがMax7で処理されてArduinoからCVを出すようになっています。
オープンソースでやってるので興味があればリポジトリも見てみてください。