EngineCOMPを沢山使った話

# 結論

EngineCOMPは今年沢山bugfixが入った。
もう安心して使える。


# EngineCOMPを沢山使った話

今年、山口情報芸術センター［YCAM］で現在展示されている「アンラーニング・ランゲージ」という作品のフロントエンド部分制作に参加しました。
アンラーニング・ランゲージは観客体験型のパフォーマンス作品です。観客がAIと対話し、「AIにはない人間の資質とはなにか？」というテーマを探求する作品です。

https://www.ycam.jp/events/2022/unlearning-language/

作品のシステム構成をものすごくざっくり書くと、以下のような構成です。
- `入力（カメラ・マイク）`と`出力（照明・音声・振動子）`をフロントエンドのTouchDesignerが握っている
- 別PC（バックエンド）の中に `AI` と `台本` がある。入力情報をフロントからAIへ逐次渡し、状況を判断したAIが台本を書き換える。書き換わった台本をもとに、フロントへ出力命令を出す



フロント側では一つの.toeファイルで多数のDeviceIOを受け持ち、PC間データやりとりの為に多カメラのテクスチャの事前処理・圧縮・転送を行い、同時に音声パケットも常に送信し、必要に応じて音声合成も行なう為、全てメインスレッドで実装してしまうとフレーム落ちやブロッキング処理が発生してしまいます。これを回避する為に、TDを刻んだり並行処理の実装をする必要があります。

https://qiita.com/kyeshmz/items/fe1e89e1bf046f8e4de1

https://qiita.com/shks/items/656186c5127869bfbe84


そういえばEngineCOMPをExperimental時代に試した時はダメそうだったけど今はどうなってる？と思い使ってみたところ、調子が良かったです。謎のクラッシュは一度も起きませんでした。細かい罠をクリア出来れば、刻み・並列処理より実装が楽だと思われます。

アンラーニングランゲージでは最終的に8つのEngineCOMPを1プロジェクト内で使いました。`TouchDesigner`とは別に`TouchEngine`のインスタンスが走っている事がTask Managerから確認出来ます。
<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/f8a5b5b4-6f77-67b6-947e-421839fc7dc4.png">



## EngineCOMP 使い方
適当なCOMPをtox化し、EngineCOMPに読ませる
![Group 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/cfb09cda-dc26-5cb0-a48b-d6b00ffafaae.png)


## 遅延があるので注意
遅延あります。プロセス間でデータの往復が発生するので絶対遅れます。許容出来る遅延かどうかまず検討が必要です。


#### 遅延計測
IOTestという名前の `in / out しか入ってないtox`を作り、EngineCOMPに刺します。EngineCOMPで読んでいるtoxを走らせる為のClockは `EngineCOMPと同期するSyncronized` と `独立Clockで走るIndependent` の2つがあります。

inTOP, inCHOPにme.time.frameを渡した所、、、

- Synchronized: 3f遅延
- Independent: 6~7f遅延

がある事がわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/c1f8e0e6-f084-997b-d2fc-8f1dc24cafea.png)

このスクショではproject fps = 60 なのですが、これを24に落としてもSyncronizedの遅延は変わらず3fです。Independentの遅延は3fで固定になりました。Independentを選んだ所でメインスレッド側でフレーム落ちが発生したらどの道ダメだろ と思うので、特別な理由がなければSyncronized一択で良いのでは。

## ErrorDATとfps計測を仕込んでおく
制作中、`toxは調子良く動いているけど、そのtoxをEngineCOMPに刺したらエラーが起こる`という事が多分起こります。
EngineCOMPの中身は見れません。
EngineCOMPが調子良く動かない場合、中で何が起こってるのか確認する術がほしいです。
ErrorDATは絶対絶対仕込んでおいたほうが良い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/365d4220-a9a1-0adf-4791-8513ea8c2b86.png)

1. tox内にErrorDAT --> outDAT を置く
1. ErrorDATはEngineCOMP内のエラーだけを吐いてくれる。エラーが起こり続けてるとframe番号がゴリゴリ動くので、frameを見やすいようにしておくと異変に気付きやすい。error出力のframeやmessageを見て、あとは頑張る

fps確認にPerformCHOPを使っても良いんですが、PerformCHOPに整えられていない実測のfps数値を見たいので、後述の MyTemplate 内では `time.perf_counter()` を使っています。細かい揺れが見れてドキドキします


## Pathに注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/687ae56d-e9c5-571e-be53-8dde1e3e9cb1.png)

`my_python_module`を読みに行きたいとします。
EngineCOMPに読ませるtoxは`engine`に入っています。
**EngineのWorking Directoryはtoxが置いてある階層**なので、この場合....

- toe --> my_python_module
    - `my_python_module`
- engine --> my_python_module
    - `../my_python_module`
- engineに刺すtox **開発中** --> my_python_module
    - `my_python_module` (この時点では.toeの階層がworking dirになるので、tox化後EngineCOMPに刺した時にmy_python_moduleとの階層関係が開発時と変わる)
 

とややこしい事になります。
これを回避する為に、EngineCOMPに刺すtoxは↓こんな感じでtoeと同じ階層に置くのが吉かもしれない。前述の`toxは調子良く動いているけど、そのtoxをEngineCOMPに刺したらエラーが起こる` これはパスの問題で起こりがちだと思います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86490/984fca81-9b21-1a7d-8010-fe77f738077d.png)


## Example
ErrorDATとFPS計測を入れたMyTemplate、遅延計測用IOTestが入っている簡素な例
https://drive.google.com/file/d/1uo9tVA-gUqqi-i9D3qHgWRfYymcebW03/view?usp=sharing