Maxでの照明プログラミング(poly~を使う編)

## はじめに
以前、Maxで照明を制御する際に[MaxでDMXを[Art-Netに乗せて]制御する記事](https://qiita.com/LUDO/items/d9f534ef81f917a90d56)を投稿しました。
このときは、DMX信号をArt-Netに乗せることをメインに説明していましたので、Maxでの具体的なパッチについてはあまり深く触れませんでした。
しかし、前回の記事で触れられていないMaxで照明制御をするメリットがあります！
今回はそれを紹介し、実際にパッチ内でどのように使うのかを説明したいと思います。
(わかりやすさを優先させたいため、語弊を招く表現があるかもしれません。
また、あくまで僕個人の考えです。様々なご意見・ご指摘をお待ちしております！)

サンプルパッチは[こちら](https://github.com/LUDO-TAKEBE/poly-_DMX)から。

## Maxを使うメリット
Maxには"poly~"というオブジェクトがあります。
このオブジェクトの詳しい説明は[こちらの記事](https://leico.github.io/TechnicalNote/Max/poly-summary)をご覧ください。
これを使うとどんなメリットがあるのかというと
 <b>照明の灯体ごとにインスタンスをつくり、マルチスレッド処理を行える</b>
ことになります。
照明卓でいう*fixture*の割り当ての概念に近いです。
詳しく解説します。

## 照明卓での制御について
この章は照明卓での照明制御の経験の少ない方向けです。読み飛ばしても大丈夫です。

まず、ムービングヘッドやLEDの灯体には、ひとつの灯体に対して、いくつかDMX信号を入力することがほとんどです。
灯体の種類によって変わりますが、例えば
ch1 : R
ch2 : B
ch3 : G
ch4 : Dimmer
のように4チャンネルを使用する灯体があるとします。
この灯体のDMXスタートアドレスが1の場合は、そのユニバースのDMX1~4に信号を送ることで、このLEDを制御することができるでしょう。
この、灯体ごとに設定されているDMXの使用チャンネル情報を*fixture parameter*と呼んだりします。

次に照明制御卓ですが、照明卓にもいくつか種類やグレードがあります。
一般的なparライトなどの制御とムービング系の灯体を制御する卓は分かれていることが多いです。
プロ仕様のものだと何百万円もしますが、そういった高級な照明卓には大手の照明機材メーカーの製品である灯体の情報(*fixture parameter*)があらかじめ入っています。
このため、同じ種類の灯体をいくつも使用する際には

* 各灯体の種類
* 各灯体の*start address*

の２つを指定して、楽にサブマスターのパッチが組めるようになります。

上の例で言うと、*fixture*を選択すると

* 4ch使用する
* 各チャンネルにどの信号与えるか

を照明卓が理解し、*start address*の1を指定すると設定完了です。
これで、照明を制御するときは<b>「DMXの何chに~の信号を送って...」</b>という考えではなく、<b>「この灯体は赤にして...」</b>のような指定の仕方を照明卓に対して行うことができるようになります。

 *事前準備さえすれば、制御自体は直感的に行えるようになる、ということですね！*

## ということで
今回は、この機能をMaxで実装しよう、というのが目標です。
もちろん*fixture parameter*はMaxに入っていませんので、自分でつくることになります。
しかし、一台分の情報をまとめれば、同じ灯体をいくつも使う際にとても楽になります。
また、マルチスレッドを指定すれば並列処理も行ってくれるので、おすすめです。
特に、チャンネル数の多い<b>ムービングヘッド</b>や最終的なチャンネル数の多くなる<b>NeoPixelなどのテープLED</b>などにはかなり有効だと思います。
以前、esp32というマイコンにWi-fi経由(Art-net)でDMX信号を送り、esp32がDMXを変換してテープLEDに信号を送る、ということをしました。(電車の中で)
このときもpoly~で各LEDのインスタンスをつくったのですが、結構良い感じでした。

↓マイコン側のプログラムを担当してくれた方のツイートより↓
<blockquote class="twitter-tweet"><p lang="es" dir="ltr">Max+esp32+neopixel test <a href="https://t.co/inEY3Cgq2u">pic.twitter.com/inEY3Cgq2u</a></p>&mdash; ハ バ タ ユ ウ ト (@haaaaaa_ta) <a href="https://twitter.com/haaaaaa_ta/status/1215231832637067264?ref_src=twsrc%5Etfw">January 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

では、やっていきましょ〜。

## 準備するもの
- PC(Macbook pro)
- Max8(ver:8.1.3)
- 照明を出力すためのインターフェース
- DMX制御できる照明灯体

特別なものはありません。
MaxのバージョンやPCは特に重要ではないと思います。
インターフェースや灯体もDMX制御できればなんでも大丈夫です。
マイコン->テープLEDとかでももちろん大丈夫です。(マイコン以降の変換は頑張ってください。)

今回は
ch1 : R dimmer
ch2 : B dimmer
ch3 : G dimmer
という3ch使用のLEDを4台制御する場合を考えます。

## サブパッチ(fixture)の作成
poly~オブジェクトは、サブパッチを基に複数の実体をつくります。
このサブパッチが、各*fixture*に当てはまります。
ということで、サブパッチをつくりましょう。
ここでは、

* 色情報のlistを各パラメータに分ける
* *dimmer*(各チャンネル、マスター)の信号を受けて反映する

を実装したいと思います。

さっそくですが、出来上がりはこちらです。


<b>RGB_p.maxpat<b/>
<img width="599" alt="スクリーンショット 2020-04-23 15.28.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474709/5b9ed483-c8fe-0d99-f8ff-b772a812b0f5.png">
解説します。(poly~の詳しい使い方は上で紹介した記事をご参照ください。)

まず、今回は色の情報がlistの状態でin1に入力されます。
これを各チャンネルに分解し、出力します。
右上のパートでは、スタートアドレスを入力して、それをもとに各チャンネルのDMX番号を計算しています。
計算結果は左側のパートの下のintオブジェクトに入力されます。

右下のパートでは、入力された各灯体に対する*dimmer*信号を0~1で受けています。
これを左側のパートの上の方で掛け合わせています。
左側のパートの中間あたりでは、*master dimmer*を受信して同様に掛け合わせています。

サブパッチの概要は以上です。
すこし<b>大事なところ</b>をピックアップします。
色をつけている*send, receive*のオブジェクトについてです。
*master dimmer*は全インスタンスで共通の値になるため、#0表記をせずに*receive*しています。
逆に、その他の*send,receive*は各インスタンス内で情報をやりとりしたいため#0を頭につけています。

ちなみに、あまり処理が重くなるようなものは避けた方が良いです。
このサブパッチ内で作られているものがインスタンスとして大量に複製されるため、１つのオブジェクトではあまり負担でなくても、全体では相当な負荷がかかることが考えられます。
なるべくUIオブジェクトを入れたり表示させたりしないようにしましょう。


## メインパッチの作成
このパッチでは、先ほどつくったサブパッチをpoly~オブジェクトで実体化します。
今回はLEDが4台あると仮定します。
その後、灯体を選択して色を選択するという部分の実装を行います。

それでは、こちらも全体のパッチです。


<b>LED_main.maxpat<b/>
<img width="847" alt="スクリーンショット 2020-04-23 15.35.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474709/3361992a-75d1-37a7-9871-77805fe24397.png">
ごちゃついてますが、操作するときは必要なものだけを表示させます。
<img width="614" alt="スクリーンショット 2020-04-23 15.36.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474709/2bdc02ae-f780-1ee0-2599-22b3e86dc3ab.png">

さて、解説です。
今回はArt-netでの出力を考えているため、最終的な出力は一番下の *imp.artnet.controller* に入れます。
一番上の *imp.artnet.node* はその出力したものを受け取ってビジュアライズするために使用しています。

poly~オブジェクトを見てみましょう。
まず、上でつくったサブパッチ(*RGB_p*)を呼び出し、数を指定します。
このインスタンスの数は*attrui*の*voices*からも指定することが可能です。
また、<b>*attrui*にて*parallel*をon</b>にして、<b>*"threadcount OO"*</b>も設定してあげましょう。
こうすることで並列処理をしてくれるようになります。 
次に、*poly~*の第２インレットに初期設定でスタートアドレスを入力します。
これは、後から個別にスタートアドレスを変更しやすいように、このパッチで設定しています。

上の部分は照明を制御するためのパッチ部分です。実際に操作するときは、この上半分をプレゼンテーションモードに追加して、触ると良いと思います。

*poly~*オブジェクトに入力する際は、
*poly~*の第1インレットに*"target OO"*のようにインスタンス番号を指定
→各インレットに入力したい値を入力
します。
こうすることで、各インスタンスを個別に指定して値を送信することができます。
例えばこのパッチでは、"*select fixture*"とコメントされている四角をタップするとその番号が"target OO"のように入力され(左の方の*send/receive poly_target*経由)、*color picker*にて指定した色の情報をRGBのlistで第一インレットに(*send/receive color*経由で)入力しています。
*selected ch dimmer*も同様で、最後に選択した四角に対してのdimmerを制御します。
*master dimmer*は、各インスタンスに対して値を直接送信しているため、すべてのインスタンスで並列して処理されます。*target*指定は必要ありません。

## 操作してみる
↓こんな感じです。(制御操作をみても、特に何もないですが...)↓
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Test &quot;DMX&quot; using &quot;poly~&quot; (in Max)<a href="https://twitter.com/hashtag/Max8?src=hash&amp;ref_src=twsrc%5Etfw">#Max8</a>  <a href="https://twitter.com/hashtag/DMX?src=hash&amp;ref_src=twsrc%5Etfw">#DMX</a> <a href="https://t.co/oEkPKNHdY3">pic.twitter.com/oEkPKNHdY3</a></p>&mdash; LUDO TAKEBE (@for_LUDO) <a href="https://twitter.com/for_LUDO/status/1253216385926221824?ref_src=twsrc%5Etfw">April 23, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

サンプルパッチは[こちら](https://github.com/LUDO-TAKEBE/poly-_DMX)です。

--追記--
オンラインイベントにて、このシステムを用いて照明制御をした際のアーカイブ動画です。
ぜひご覧ください！(画像をクリックすると、youtubeに遷移します。)
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/JDBE57k5XGo/0.jpg)](http://www.youtube.com/watch?v=JDBE57k5XGo)


## むすび
実際に使うときはもう少し複雑なパッチになるかと思いますが、少しでもpoly~オブジェクトを用いた照明プログラムの参考になればと思います。
さらに灯体の数を増やしたりチャンネル数が増えると、よりその魅力を感じられるものと思います。
また、このサブパッチ(*fixture parameter*)は<b>現場を重ねるたびに使いまわして増えて</b>いきます。
どんどん楽になります。

照明制御に興味をもってくださる方が増えることを願っています。
また、普段から照明を扱っている方が、自作のプログラムを組んでみることに挑戦されることも期待しています。
エンタメ・メディアアート、どちらも厳しい時代ですが、この現場で活動できない時間に普段やっていなかったことに挑戦してみるのはいかがでしょうか？
プログラムの勉強は人と直接合わなくてもできます！！
その知識が必ず武器となる時がくるはずです。(自分に言い聞かせています。)

サンプルプログラムの不具合や、よくわからない点、説明不足な点など、あるかと思います。
どんどんお寄せください!
よろしくお願いいたします。