初VJ後記

はじめに

CHANNEL#23にてumio(https://twitter.com/umio0o)さんのVJを担当しました。さいな(https://twitter.com/SainaKey)さんと二人で20分ずつ、私は後半部分の映像をやりました。人生初VJでしたが、何とか乗り切れてよかったです。

↑メチャカッコよく撮ってくださっていた

設計思想

今回のVJを行うに当たり私の能力上どうしようもないいくつかの制約として、次がありました。

  • 極度の運動音痴、あらゆるボールは俺の顔面が大好きで、机に置いてあるコーヒーはいつも俺にこぼされることを望んでいる。
  • VJ初挑戦 なーんもわからん!

俺VJ向いてなくない?至極当然の話として、初めての行為にパニクった運動音痴にボタンなんか触らせてはダメなんですよね。VJの話が回ってきた時点で最悪僕はブースで突っ立ってても動くものを作るつもりでした。ついでに使い慣れていないmidiコンも捨てて、本番はキーボードとマウスのみを持ち込むことにします。

また、VJによくあるわけわかんないなるくらいバキバキの演出とかも僕はあまり得意ではないです。

そもそも意味から離れたものを作るのが苦手なんですよね、根本となる部分がある程度ロジックに則ってないと可能でないと全く手が動かない…*1。 というわけで、今回のVJではオーディオリアクティブをベースとした創発的なプロセスに頼ることにしました。そこで今回提案したのが音声波形データを受けて創発的にビジュアルを生成するmodule-basedなVJシステムとなります。

コンセプト

モジュラーシンセ、神経回路*2、CPPN*3みたいな。簡易な信号処理モジュールの結合によって多様性のある画を出しましょう的なやつです。

基本的な構成を説明すると

  • モジュール群…任意の入出力系と内部状態を持つモジュールの集合
  • 入力モジュール…対応する周波数(入力音声波形をフーリエ変換したもの)の活性化(後述)を監視し、結線されたモジュールに信号を送る
  • 変調モジュール…入力信号を「加工」して次のモジュールに渡す
  • 出力モジュール…ビジュアライズをしたり、ポストプロセスのパラメータを変化させる
  • ケーブル群…任意のモジュールの出入力間で信号を受け渡す。光る。

みたいなモジュールが2次元グリッド上に配置されており、各モジュールの通信の様子に加えて、「ケーブル」経由で

Spectrum→入力モジュール→変調モジュール→出力モジュール→ポストプロセス

みたいな感じで処理・伝送された信号をパラメータとしたポストプロセスが加えられて画面が生成されている、といった感じになっています。

構成メモ

途中チャネルロゴをグチャグチャにグリッチさせてたんですが、あれはモジュール群の計算によって生じたエフェクトだったわけですね。モジュールの種類と接続の方法によって無限種類・把握不可能なエフェクトが生まれるはずで、このモジュール群を一定時間ごとに分布を変えてランダムに繋ぎ変えることで、全体の画を変化させる、というのが今回制作したプロトタイプの内容でした。

モジュールの分布A「ポルカドット」
モジュールの分布B「カラフル」
ちなみに左上に出てたパラメータも各モジュールの座標や機能を紹介しているものだったりします。

オタクに媚びるオタク

画づくり

Unity URPを使いました。最近はGPGPUレンダリング部分をVFXGraphで済ませるのが気に入ってます。VFXGraphはGraphicsBufferをSet出来るので複雑なGPU処理をする場合でも、レンダリングだけVFXGraph採用する、みたいなことが容易に出来て嬉しいです。GPGPU周りのコード量が6割ぐらいになったイメージ。

VFX全体像
GraphicsBufferのサンプリング部分
ケーブルのヒューズ表現はVFX GraphのGPUEventで前日にサッと作ったもの

シーケンスは5つ用意したのですが、20分持たせるのが本当に大変でした。

さいなさんとの合わせのために作ったCubeシーケンス 実はモジュール同士がちょっとめり込んでる

白砂さんがあのクオリティでアホみたいな量のシーン作ってたのが怖かったです。

波形データの事後処理

一般のオーディオビジュアライザと同様に、今回のソフトウェアも入力された音声波形データを短時間フーリエ変換*4したスペクトラムを元に映像表現を生成します。ただ、抽出されたスペクトラムはどうしてもガッタガタで、そのままビジュアライズすると映像もガタガタになってしまうという問題があります。

今回は各周波数の対数パワーの指数平滑移動平均を内部的な状態として保持し、各フレームの入力がそれに比べて一定の閾値倍を超えた時に活性化(Activation)が起こる、と定め、それを基準に様々なアクションが起こるとしました。また、活性化の後には一定の不応期を設け、極端にガタガタな波形に対し過剰な反応をしないように定めました。要するに、

  • 急に音量がデカくなったらそこを音のインパクトであるとし、ビジュアライザの各要素を起動
  • 一度起動した要素は一定時間応答しない

という特性を持たせるようにしています。

上から順に生の正規化済みスペクトラム、平滑化済みスペクトラム、Activation、ActivationColor(Activationの度に生成される乱数)
Activationの概念図
一応気持ち的には神経科学の事を考えながらこの辺実装していますが、あんまりつながりはないです。

今回のVJではカメラアングルの変化等についてもオーディオリアクティブにやっていたのですが、カメラのように画に大きく影響を与える一部のエフェクトに関してはUIからどのスペクトルを対象とするか決定出来るようにしていました(上図の緑)。今回はFFTの周波数方向の解像度は512としていましたが、周波数方向に鋭い音は拾いきれない等、ちょっと使いづらい感があったので、重要な動きに関しては多分max-poolingとかでダウンサンプリングしたほうが良いです。正直32ぐらい解像度があれば困らないんじゃないかな… また、ビジュアライズに使いたい音って基本的に低音域に集中しているので、今回の例では高音域をクリッピングしている(上図の青で区切られた範囲)のですが、そういう細かい前処理みたいなものが気持ちの良いリアクティブには不可欠であると考えています。

FFTGPUで行われている場合、CPUへのReadBackもあんまり早くない等の問題もあり、この辺は工夫の余地が無限にありそうです。

今回出来なかったこと

正直実装は全然間に合っていない

フィードバック的機構の実装

個人的には信号処理とか制御論の真髄て結局のところフィードバック機構にあると思っていて、その辺詳しくない人もある信号を次の単位時間に持ち込むことで自由度とか表現の幅はグッと増えるというのは、glslとかでbackBuffer使ったことがあれば経験的に感じているかと思います。

フィードバック機構自体の実装は全く難しくないというか、ランダムに入出力をつなげる今回のシステムだとむしろ勝手に生えてしまうのですが、今回は生成するモジュールの入出力系を絞ることで意図的にフィードバック機構の出現を抑制しています。真面目にアルゴリズムを練る時間的余裕が無くて(古典制御で言う)安定性を保証する仕組みの実装が出来なかったからです。

マイクとスピーカーを近くに置くとワンワンと唸りを上げて音が際限なく大きくなっていく「ハウリング」を皆さんも一度は経験したことのあると思いますが、あれが古典制御で言う不安定なフィードバックです。

N年前の講義ノートから持ってきたマイクとスピーカによる「悪い」フィードバックの一例 A倍されたスピーカの音声が1フレーム後にマイクに入る

より正確にはBIBO(有界入力有界出力)安定と呼ばれる安定性の規範があって、これは有限の大きさ*5を持つ入力 xを与えた時、その出力 yもまた有限となるというものです。詳しくはどっかの大学の制御論のレジュメでも見てください。

何が言いたかったかというと、場に存在する全てのモジュールの閉ループ系に対してBIBO安定を保証しないと、何か入力された時に信号が勝手に増幅されてビジュアライザがブッ壊れる可能性があるため、フィードバックの出現を絞らなきゃいけなかったという話です*6。BIBO安定自体は様々な判別法が知られているので、多分真面目にグラフ書いて解析すればある程度解決可能である気がしてます。まぁ目で見て壊れてたらリセットすればいいだけなんだけど

創発的仕草

今回だとモジュール群の表現力と、出力系の表現力の兼ね合いで「オ、創発をしとるな」というレベルの面白い画は出ませんでした。ちゃんと作ればスイッチングすら不要で無限の画が出力されるタイプの設計なはずなので、まだまだだなぁという感じですね。この辺はFuture workです。

ユークリッド空間

今回普通にユークリッド空間をベースに処理を進めてしまったのですが、その一方で最近は割とユークリッド空間は食傷気味だろ、という気持ちもあり、グリッド、立方体、矩形、そればっかじゃんお前、みたいな。とはいえ込み入ったトンチキな空間を採用しても伝わらない感じになっちゃうのはわかりきってるので、なんかガラの良い3次元空間への埋め込みが出来る多様体を探していきたいですよね。

オーディオの特徴量抽出

やっぱりFFTを後処理するだけのオーディオリアクティブだと結構限界があるのかなみたいなことを考えています。正直リアクティブさせたい対象って別に「ある周波数帯のパワーの動き」じゃなくて「kickの音」とかになるはずなので、理想としては一旦フィルタ通した波形からトラック分離してインパルス列に戻せると嬉しいですよね。そろそろこの辺をディープでポンするリサーチをしても良いよな、みたいな気持ちはあります。多分流転光速のブレイクビートパートみたいなことが出来ると嬉しい。

youtu.be 足立レイすき

この辺のトピックで言うとDJの展開をEmbeddingするとか、waveform2midiみたいなのを作ってみたい気持ちはあって、なんか適当なアノテーション付きのDJ音声波形データセットみたいなのがあればTransformerとかに食わせて特徴ベクトルを抽出出来たりしねぇかな*7みたいな、深層学習モデルのinferenceがフェイクドロップに引っかかったらウケるなみたいな。これもFuture workです。

まとめ

お疲れ様でした。まだプロトタイプというか、構想のPoCをやったみたいな段階なので、今度はこれを踏まえて更に面白いことを考えていこうと思います。

さいなさんには機材選定から本番の準備まで色々やってもらって感謝です、VJの手元見れて嬉しかったです。umioさんもリハで丁寧に切り替えの相談に乗ってくれて、本当に助かりました。ありがとうございます。

*1:これって結構致命的な気がしていて、プリレンダの映像とかは、高解像度の画面に対する情報量を充填するために論理とかじゃなくエフェクトを突っ込むみたいなのも割とあって、そういう「意味はないけど気持ち良い」、みたいな仕草が出来ないのはおそらく結構まずいんですが、それは別の課題。

*2:あんまり関係ないんだけど神経科学のテキストだとJuliaで学ぶ計算論的神経科学 — Juliaで学ぶ計算論的神経科学が丁寧ですきです

*3:Stanley, K. (2007). Compositional Pattern Producing Networks: A Novel Abstraction of Development. Genetic Programming and Evolvable Machines, 8(2), 131–162.

*4:Keijiro神のhttps://github.com/keijiro/Laspを使用

*5:ここでいう大きさは信号全体のパワーを積分したもの

*6:例えば、「2個の入力を合計して出力に流すノード」が存在するだけでももうダメ

*7:音「声」系の界隈は信号列と離散的なトークン列・特徴量の相互変換みたいなタスクを一生やっているのでこの辺と相性良さそう