Notchスタンドアロンでレイヤー（ジェネVJ）のスイッチング制御を構築してみた話

#動機

Notchはメディアサーバー経由による**「NotchBlocks」(.dfxdll形式)**の制御が最も主流です。
その他にリアルタイムツールのTouchDesigner、SmodeでもNotchBocksが読み込めるようになりました。
しかしながら、メディアサーバーは非常に高価ですしツールが増えれば複雑さが増し学習コストが高くなります。
Notchは感覚的な絵作りとレイヤー量産が容易ですが、**"リアルタイムジェネ + スタンドアロンで自由に切り替え混ぜる"**ということを想定した機能はありません。
理想はResolumeやVDMXなどのVJソフトのようなイメージ。
与えられた機能でなんとかそれっぽいものを構築した話を備忘録的にまとめておきます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Notchスタンドアロン単体でレイヤー（リアルタイムジェネ）のスイッチング制御するシステム組んでみた<br><br>素材数はたぶん無限<br>混ぜられるチャンネル数は3ch（マシンスペックに依存）<br>容量は20個くらいジェネ突っ込んで71Mb<br>外部ソフト、メディアサーバー必要なし<a href="https://twitter.com/hashtag/madewithnotch?src=hash&amp;ref_src=twsrc%5Etfw">#madewithnotch</a>　<a href="https://twitter.com/hashtag/%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%AC%E3%83%B3%E3%83%80?src=hash&amp;ref_src=twsrc%5Etfw">#リアルタイムレンダ</a> <a href="https://t.co/rf7aTkfbGh">pic.twitter.com/rf7aTkfbGh</a></p>&mdash; Shuhei Maeta (@shu1053) <a href="https://twitter.com/shu1053/status/1269449279451459586?ref_src=twsrc%5Etfw">June 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#試したこと その①「OSC Transport Control」（伏線1）

###「OSC Transport Control」・・・吐いたOSCをセルフで受け取りタイムライン制御
OSCの値を時間に変換するコマンドを使います。
5分,10分おきのように多少長めに素材を配置し**時間ベースで素材を切り替えます。**
カンパケ映像のメロやサビの区切りで制御する分には非常に有効な方法だと思います。

やり方はこちらに詳しくまとまっているので割愛します。（以下参照）
http://manual.notch.one/0.9.23/en/topic/osc
https://qiita.com/yasuhiro_chida/items/e7006d806710d147ad6e
https://qiita.com/fmwads8492/items/c516f192270a2131d78b

デメリット
・タイムラインが非常に長くなる
・2つ以上のレイヤーを別々に混ぜられない
・映像を出す前に絵を確認する術がない
・遷移した瞬間に落ちるケースがあり不安定（原因不明）

#試したこと その②「Layer Precomp」（伏線2）

###「Layer Precomp」・・・別のレイヤーから映像を引っ張ってくる
まず目をつけたのがこのノードです。
プルダウンから**引っ張る映像（レイヤー）を自由に選択**できます。
「これだけで行けるんじゃないか」そう思いましたが無理でした。
プルダウンの部分にModifierを繋ぐことはできません。
外部からの制御はできないということです。
Layer Precompが使えないなら厳しいなと思い一回諦めました。
↓
（この間半年）
↓
#試したこと その③「Layer Precomp+Select Input」（成功）
###「Select Input」・・・複数のノードを繋いだ後、数値でアクティブを切り替える
このノードを発見しました。
いろいろな種類のノードを数値によってスイッチングできるという万能型ノード。
Layer Precomp自体は切り替えられないがLayer Precompを複数用意し、スイッチングすることは可能だと気付きました。

###手順① ベースとなるフォーマットを作ってみる
####Composite Image ← Select Input ← Layer Precomp x n個
![VJ-2 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/9c5654bb-3c74-9099-3df5-2f23bf4b453a.jpeg)

###手順② VJ素材を割り当てる
タイムラインモード（F2）にあらかじめジェネっておいた素材を並べます。
オンにする必要はありません。横に並べる必要もありません。
![VJ2 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/56f0c6f0-1a59-ff93-6c40-57a595f27b9d.jpeg)

ノードグラフ（F1）に戻り、各Layer Precompの「Source Layer」からレイヤー選択
![VJ3 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/41dff868-a0db-2807-d91a-abeaeae99f57.jpeg)


###手順③ Select InputとMidiを繋ぐ

**＜フェーダー系、つまみ系のMidiで制御したい場合＞**
0~1で入ってくる値を「Range Remap」で0~(素材数-1)へ変換する
↓
Select Input内の「Input Node Index」へ繋ぐ
![VJ4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/1a6b6589-85ac-1027-77c8-400b054af9c2.jpeg)

####＜ボタン系、PAD系のMidiで制御したい場合＞
**「押すと1、離すと0になるMidi」**のケースです。自分はAPC40 mk2のpadでやりました。
ここでの問題は離すと0に戻りレイヤー選択が解除されてしまうことです。
単純に繋げるだけでは機能しません。
そこで一番最初に試した**「セルフOSC」**を使います。
OSC Outputノードには**「Send Active」**というパラメータがあり、押した瞬間のみ数値を飛ばすことが可能です。（離した瞬間に0が飛ばない）

まずProject Setting内のOSC　RecvとSendポートを同じ値に設定します。
![VJ5 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/e8833b1e-08db-4c85-bea0-186df651b5e9.jpeg)

Midi Modifierを素材の数だけ配置していきScale値を0,1,2,3,4,5・・・と設定します。
Scale 0のPadを叩くと一個目、Scale 1のPadを叩くと2個目の素材が出るようにしていきます。
これらを一度Envelopeにまとめた後、OSC Outputへ繋ぎます。

上記の設定をまるごとコピペしScaleを全て1にします。こっちはEnvelopeから「Send Active」へ繋ぎます。
Padを押した瞬間のみOSC Outputがアクティブになり値が飛ばされます。
![VJ6 (0-00-14-17).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/de1bab2f-101f-f036-b7d3-64ab62ce2752.jpeg)


OSC ModifierでOutputした数値をセルフで受け取る。
そしてSelect Input内の「Input Node Index」へ繋ぐ
![VJ8 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/fce5f243-b5d1-8fc9-732e-254fe35c2ef6.jpeg)

###手順④ 処理負荷問題への対処

素材レイヤーの数が増えれば増えるほど重くなり、これはリアルタイムジェネVJにおいて致命的と言えます。
どうやら**Select Inputではアクティブでないレイヤーを完全にオフにすることができない**ようです。
対処法としてLayer Precompの中にある**「Update Active」**を利用します。
これが0の時、処理は完全に止まります。
最初からこれで制御できたのではと思われるかもしれませんがこれはあくまでアップデートのオンオフなのでオフにした瞬間絵が固まり事故ったみたいになります。Select Inputと組み合わせるのは必須かなと思います。

**該当するPadを押している時Update Activeが1になり、それ以外のPadを押した時は全て0になればいい。**
これはCondition Modifierで解決できます。
####「Condition Modifier」・・・入力値が一定のトリガー条件を満たすと設定値を出力する
OSC Modifier → Condition Modifier → Layer Precomp「Update Active」
![VJ9 (0-00-00-00).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/aa2c662c-3c21-7253-d1f1-d01d140eb25c.jpeg)

これで処理負荷の問題は解決です。
出ている映像のみ処理され、素材をいくら増やしても問題なく高fpsが出せると思います。

###手順⑤ スタンドアロンアプリの動作問題への対処
Exeアプリとして書き出したもので動作確認をしてみると1つ目の素材以外映像が出ません。
最初に一度でもレイヤーを参照しないとLayer Precompで映像が生成されないという問題。予想外
どうしていいかわからないので力業で解決します。いい方法あればどなたか教えてほしいです。

RenderLayer → Image Plane ← Layer Precomp　と繋ぎます。
**MidiやSelect Inputを全部いったん忘れて**直接Image Planeで全レイヤー描画します。
あくまでも中身の処理を呼び出す用途でしかないのでVisible、Seen by Rays、fpsを0にしておきます。
Envelopeで一括0にしておくと楽。
これでまた処理が重くなったらどうしようと思いましたが問題なさそう。
![VJ10 (0-00-10-05).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/427ad380-a52c-4b71-9646-a884b0126e26.jpeg)

###手順⑥　同じ方法で2Chを構成+OSC問題の対処
1Ch用に構築したノード群をコピペし改変することで2Ch側の構成を作ります。

ただここでもう一つ問題が発生。
2ch用に新しくMidi Padの割り当てを作ったもののOSCで1Chと一緒に数値が飛んでしまう問題。
2ch用のPad叩くと1Chが止まる。
1Chのみなら問題ありませんが2つ以上混ぜるにはこれをどうにかして解決する必要があります。
OSC Modifier内に**「Ch」**というパラメータがありこれで分けられるかと思いましたがうまくいかず。。。
OSC Outputのほうには「Ch」など存在しないため。
本家FacebookのNotchグループに質問するも1件も回答なし。。。

と諦めかけていましたがなんとか解決しました！

####＜解決策＞
**2ch用 OSC Output & OSC Modifierを作り、Adressを1Chと違うアドレスに変える。**
これ僕はIp Adressに関する知識がないのでどういう仕組みかよく理解していません。
が、なんか変えてみたら別々に独立してセルフOSC作用している！よくわからないけど動いてるからいいかっていう感じです。

###完成！！！
![2020-06-07 10-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243114/188930ac-8cf5-973e-a98d-3ab11ee540f5.gif)


#終わりに
以上無理やりVJシステムっぽいものを構築した話でした。
Layoutの構成を練ればUIっぽくもできると思うのでそこは今後進めていきたいと思います。
Layer Precompで構成する場合問題だらけで後半特に力業になってしまっているのでもっといい改善策が見つかればよいなあと思っています。
というか公式でそれっぽいことできる機能がほしいところ。

まだまだ発展途上ですが読んでいただきありがとうございました。



Notchの情報共有はこちらのグループで行っているのでぜひ参加してみてください。
Facebookグループ : https://www.facebook.com/groups/notchusergroupjapan/
Line オープンチャット : https://line.me/ti/g2/kJYmLLsvS2zNfR9PEiknMg

質問等あればお答えしますのでお気軽に
Twitter : https://twitter.com/shu1053
FB : https://www.facebook.com/profile.php?id=100009103327410