Pure DataからReaperを制御する(1) OSCの基本

とある案件で、Pure Data (Pd)からReaperを制御してポン出ししたくなりました。ポン出しは、演劇やイベントなどで効果音や音楽をスピーカから出力することです。場面に合わせてオペレータが手動で(ボタンをポンと押して)音を出すことが多いので「ポン出し」なのではないかと思います。ポン出しはプロ・アマ問わず需要があるので専用アプリもありますし、そちらのほうが良い場面は多々あるでしょう。

www.dtmstation.com

ただ、20~30台のスピーカへ出力したいとか、一つのファイルの異なる部分から再生したいとか、センサーからの入力に対応してアルゴリズミックに制御したいとか、やや特殊な用途に使いたいときには自作するしかありません。自分の場合も「音を聞いたときに感じる“音の○○感”を回答させる」というのを目標に、PureData側でポン出しボタンと回答のためのスライダを一つのGUIに同居させ、音はReaperから再生させる特殊な用途を考えています。それはそもそもポン出しじゃないか。

PdとReaperはどちらも標準でOpen Sound Control (OSC)に対応しているので、PdからReaperに信号を送信して操作することを目標に進めていきます。ただし今回はPure Dataだけしか使いません。Pdの中でOSCメッセージがどのように扱われているか、どのように送受信するかを見ていきます。使ったPure Dataのバージョンは現時点で最新の0.56-1です。

Pure DataでのOSCメッセージ

OSCで送受信されるメッセージは「アドレス」「データ型」「データ本体」から成ります。アドレスはスラッシュ区切りの階層構造になっていて、たとえば/reverb/wetなどとします。スラッシュ記号で区切ることによって、/reverb/dry/reverb/predelayといったreverbに関連するパラメータ (wet, dry, predelay, ...) を階層構造として指定することができるようになっているわけです。アドレスという呼び名は、受け手側のどの部分がデータを受け取ればよいかを示すために使われることに起因するのでしょう。/reverb/wetなら、DAWのリバーブプラグインのウェット量としてデータを受け取ればいいことになります。もちろん、そのためには受け手側のDAWやプラグインがあらかじめ想定しているアドレスを指定しなければなりません。

データ型は整数 (i)、浮動小数点数 (f)、文字列 (s)、バイト列 (b) が使えます。なので、「リバーブのウェット量を50%にしたい」という内容を送りたければ/reverb/wet f 0.5というメッセージになるかと思います。

こういった内容をPdでOSCメッセージ化するには[oscformat]を使います。下のパッチで[oscformat hoge]とあるのが、インレットから入ってきた情報をOSCメッセージにエンコードする部分です。hogeはデフォルトで指定するアドレスです。

(1)のメッセージボックスにはlist nani ka message 1 2 3.4が入っています。ボックスを叩くとPdウィンドウにOSC1: 47 104 111 103 101 0 0 0 44 115 115 115 102 102 102 0 110 97 110 105 0 0 0 0 107 97 0 0 109 101 115 115 97 103 101 0 63 128 0 0 64 0 0 0 64 89 153 154が出力されます。

ASCIIコード表を見ながら解読していくと、47は/、104はh、111はo、101はg……となっています。0はnull文字で、アドレスやデータが32ビット(4バイト)単位になるよう埋めるために使われています。nullをピリオド (.) で書くと、先頭から/hoge...,sssfff.nani....ka..message.と読めます。hogeというアドレスに対して、文字列3つ (sss) と浮動小数点数3つ (fff) を送りますよ、そして文字列はnanikamessageですよ、となります。途中のnullが文字列の切れ目になっています。nani....なんかはnaniだけでぴったり4バイトですが、次の文字列との切れ目を作るために....が入っているんですね。

続く63 128 0 0(十六進数だと0x3F800000)などはIEEE 754浮動小数点数 (big-endian) でエンコードしてあり、人間が読める十進数にすると1となります。同様に64 0 0 0 (0x40000000) は2、64 89 153 154 (0x4059999A)は3.4です。ここではデータ型を指定していなかったので、数値は浮動小数点数になっていましたが、整数型を指定することもできます(ただし[oscformat]/[oscparse]は浮動小数点数と整数を区別できないようです)

さて、PdウィンドウにはOSC2: list hoge nani ka message 1 2 3.4という出力もあります。これは、流れてきたOSCメッセージを[oscparse]でデコードした結果です。"nani ka message 1 2 3.4" をリストにして、OSCメッセージとしてパッチ内を流すことができました。

(2)のメッセージボックスの1 2 3.4を流すとOSC1: 47 104 111 103 101 0 0 0 44 102 102 102 0 0 0 0 63 128 0 0 64 0 0 0 64 89 153 154となります。解読すると/hoge...,fff....数値の列となっていますね。(1)から文字列の部分がなくなったものです。

(3)のkore wa dame 1 2 3.4を叩くとPdウィンドウに "oscformat: no method for 'kore'" というエラーが表示されます。どうやら[oscformat]にメッセージを入れたときに「先頭が数あるいはlistだったらリストとして扱ってOSCメッセージ作る」「setやformatの場合は……(後述)」「それ以外が入ってくるとエラー」という挙動になっているようです。(3)は「その他の場合」としてはじかれるのですね。Pdのソースコードのうちx_misc.cに該当の記述が見られます。

setとformat

(4a)のset reverb wetは、OSCメッセージのアドレスを/reverb/wetに設定するのに使います。(4a)を叩いてから(2)を叩くと、PdウィンドウにはOSC2: list reverb wet 1 2 3.4と表示されます。さきほどはOSC2: list hoge 1 2 3.4だったので、[oscformat]のデフォルト指定したhogeを書き換えたようです。このように、アドレスを変えることができます。(4b)のナンバーボックスに値を入れると、OSC2: list reverb wet 42のようにアドレスと値が送られるのが分かります。

画像にはありませんが、format ifsのようなメッセージを[oscformat]に送ると、「次からやってくるデータは整数 (i)、浮動小数点数 (f)、文字列 (s) だよ」という指定になります。[oscformat -f ifs hoge]と、oscformat生成時に指定することも可能です。とはいっても、整数と浮動小数点数は区別されないようですし、バイト列 (blob) はちょっと奇妙な動きをするので(挙動はドキュメントに書かれています)、注意しないといけないこともあります。

Pure Data内でのやりとり

OSCメッセージにエンコードでき、そのデコードができれば、あとはメッセージをネット越しにやり取りするだけです。Pdでは[netsend]と[netreceive]が使えます。

図の左側が送信部、右側が受信部です。送信部の[netsend -u -b]で、UDPを使ってバイナリで送信するように指定します。[netsend]の上にあるconnect 127.0.0.1 8000メッセージは、IPアドレス127.0.0.1(ローカルホスト)のポート8000番に接続するための指令です。受信側は、ポート8000に送られてくるメッセージを受け取りたいのでlisten 8000を[netreceive]につなげています([netreceive]生成時に指定もしてありますね)。

送信部では[oscformat]に対してset synth volumeとして、/synth/volumeアドレスにデータを送る準備をします。ナンバーボックス内の値(図では36)を変更すると、次々とOSCメッセージが送られていきます。

受信部の[oscparse]ではlist synth volume 36というメッセージをリストとして受け取ります(OSCメッセージっぽく書くと/synth/volume 36です)。先頭のlistを外すために[list trim]、その後、アドレスによって受信側の動作を変えたいので[route synth]でsynth階層の判定、[route volume]でvolume階層の判定をして、残った36がPdウィンドウにOSC3: 36と表示されることになります。

ここまでで、Pure Dataを使ったOSC通信の概要を説明しました。今回は送受信どちらもPdでしたが、片方がProcessingだったりReaperだったりしても、OSC通信をすることができます。次回はReaperのOSC対応を調べてみましょう。