この記事はドワンゴ Advent Calendar 2017 2日目の記事です。
ドワンゴ Advent Calendar 2016の記事
PSVR「Rez Infinite」を全身で体感するシナスタジアスーツを5740円で自作する
ドワンゴ Advent Calendar 2015の記事
THETA S長時間稼働ジャケットで長時間全天球ライブストリーミング
ドワンゴ Advent Calendar 2014の記事
リアルロボットバトル バトロイド視覚システム解説(Oculus Riftで2mサイズの戦闘ロボットを操縦してみた)
みなさんUnity使ってますか!?
Unityはゲームエンジンといいながらも映像製作や舞台演出、VJなどノンゲームジャンルのリアルタイム映像生成にもかなり広く使われつつあります。というか、私もよくそういう業務で使っています。
で。
そういう「イベント現場」のような場面でUnityを使っていると、Unityで生成する映像をほかの機材や演出と同期したくなるんですよね。ちょっとした同期なら「タイミングをあわせてスタートボタンをポチッとする」だけでいいんですが、本当にフレーム単位の同期をがっつりやろうとするとアレッ、どうしよう!?ってなってしまう。
業務用の映像機器の世界では、そんなときのために「タイムコード」があります。映像などのタイミングを厳密に測定・調整・同期するために、映像1フレームごとに番号を振って信号として埋め込み・送出することができるようになっているわけです。
この「タイムコード」。よく使われるものに「LTC(Linear timecode)」と「MTC(MIDI timecode)」があります。とはいってもタイムコードを扱う機材ってなかなか個人では触れることがありませんし、慣れていないとすごい謎の技術っぽい感じがしますよね。が…実は、LTCはただの「音」で、MTCは「MIDI信号」でありどちらも処理するのは意外とかんたんだったりします。
というわけで今回は、このうち「LTC」を実際にUnityでデコードしてみることにしましょう。
今回はテストするためにタイムコードを生成する機械をそのままザクッとオーディオインターフェースに接続しました。録音レベルがあわせられれば受信側は別にPCのマイク端子やオーディオ入力端子そのままでも良いと思います。
レベルがあっていれば音の入力が入りっぱなしになるはず。(聞くとギャーーーという感じの機械音が鳴りっぱなしになってます)
波形を見るとこんなかんじ。これがどういう形でデータになっているのか、は、SMPTE timecode(Wikipedia)や、Linear timecode(Wikipedia)に書いてあります。わりとシンプルで、波形の幅が短いものが1、長いものが0…という感じでデコードしていけばいいのです。
ね、かんたんでしょ!
というわけで、さっくりとUnityでデコードしてみましょう…!
コードはとても簡単で、Unityのマイク入力から音声サンプルを取得、そこから波形の反転を検出してパルスの幅を数え、パルスの大小からビット列を生成していくという流れです。
このスクリプトをなにか空のGameObjectに貼り付ければマイク入力からLTCタイムコードを受信してこんな表示が出てくるはず。あとはこのタイムコードをTime値に変換してアニメーションを同期するもよし、規定の時間になったらイベント発射するもよし、です。
一応補足しておくとタイムコード自体は歴史的経緯で非常にめんどくさい種類があるため本気で真面目に「タイムコードを」処理するのはかなりめんどくさいです(※加算減算・タイムコードから実時間への変換などはタイムコードがどの体系なのかによって処理が変わってしまう)。でも自分で(特定の環境で)使うだけならこんなんでも充分です。けっこう簡単にできちゃうんですねえ…!