OSC通信とは
Open Sound Controlと呼ばれる通信プロトコルです。
主に外部アプリケーションやデバイスとの信号のやりとりに使用されます。
通信基盤にTCP/IPまたはUDP、UDTを使用します。
プロトコルとは通信を行う際のルールのようなもので、
こういうデータの形で渡してくれるとこっちでも解釈できるよーというフォーマットを定めたものです。
TCP/IPは、送信側が受信側に信号伝達が完了したかどうかの確認を行い、欠損があった場合に再送信する機能があります。
UDPは受信確認を行わないため情報が欠落する場合がありますが、通信効率が良いためリアルタイムアプリケーションの通信によく使用されます。
UDTは受信側が利用できる帯域幅を測定し、算出されたパケット数を送信側に伝えるプロセスを挟みますが、通信自体はUDPを用います。
各通信プロトコルについては以下の記事がわかりやすかったためリンクを貼っておきます。
TouchDesignerでのOSC通信は、UDPまたはUDT経由をサポートしています。
OSC通信のフォーマット
OSC通信は、
/rgba 255 255 10 0.4
のように、
(アドレスパターン) (引数) (引数) ・・・
というメッセージによって構成されます。
アドレスパターンはスラッシュ区切りで階層構造を持たせることができ、引数にはint32, float32, string値などが使用可能です。
ただし、TouchDesignerでは階層構造をうまく扱えない為、単一の階層にしたほうが良いでしょう。
TouchDesignerでは、OSC In/Out CHOP、OSC In/Out DATを経由してOSC信号の送受信を行うことができます。
TouchDesignerでのOSC通信 - CHOP編
**CHOPでのOSC送信では、構造上一つのアドレスパターンにつき1つの引数しかとることができません。**受信はできます。
複数の引数を送信したい場合はDATでのOSC通信を利用してください。
送受信されているデータがどのようにフォーマットされているかを確認するために、外部ソフト「Processing」を使用します。
OSC In CHOP
ネットワークからOSC信号を受信し、CHOPチャンネル値に変換します。
パラメーターには信号受信の際に開放するポート番号を指定します。
/from/processing 10.1209
これを、OSC In CHOPで受け取ると以下のようになります。
この例でみられるように、信号は届いていますが、アドレスパターンの階層構造はうまく扱ってくれず、2つ目以降のスラッシュは単に文字として認識されています。
また、小数第3位で切り捨てが発生しています。
1つのアドレスパターンに対して複数の引数を受信した場合は、アドレスパターンに数字のサフィックスが付加されます。
OSC Out CHOP
接続されたCHOPのチャンネル値をOSC信号に変換して送信します。
このとき、CHOPのチャンネル名がアドレスパターン、チャンネル値が引数となります。
パラメーターには送信先のIPアドレスとポート番号を指定します。
今回は自分のPCへ信号を送信するため、ネットワーク(IP)アドレスをlocalhostに設定していますが、一般的なIPアドレスの確認は以下で可能です。
コマンドプロンプト -> 「ipconfig」と入力してエンター -> IPv4アドレス ???.???.???.???
以下実際に使用した画像です。
(画像左: TouchDesigner OSC送信画面、画像右: Processing OSC受信画面)
アドレスパターン: /h, /s, /v
型: f, f, f
引数: 180, 100, 255
受信側では、上記のようにフォーマットされていることがわかりました。
TouchDesignerでのOSC通信 - DAT編
OSC In DAT
CHOPと同様パラメータに受信ポートを指定します。
CHOPとは異なり、通信した値の履歴が残るような仕組みとなっています。
また、アドレスパターンでフィルターを掛けることも可能です。
OSC Out DAT
こちらについてはドキュメンテーションを読んでも正しい使い方がよくわからなかったのですが、自分なりの使用方法を考えてみました。
OSC Out DATクラスにはsendOSC()メンバ関数があり、こちらの引数にアドレスパターンのString値とOSC引数のリストを渡すことで信号の送信が可能なようです。
アドレスパターンについてはスラッシュを記述しなければ怒られます。
sendOSC()関数の呼び出しは、Execute DAT内の毎フレーム実行されるframeStart()関数内で行うことにします。
def frameStart(frame):
arg_list = [10, 100, 255, 0.7] // make an OSC arguments list
op('oscout1').sendOSC("/rgba", arg_list) // call sendOSC() member method of oscOutDat_class
return