[Astro] #177 監視室のモニタ壁で MSX・動画・SID を動かす — Quest 3 の VR で、壁がそのままメニューになる

[Astro] #177 監視室のモニタ壁で MSX・動画・SID を動かす — Quest 3 の VR で、壁がそのままメニューになる

はじめに

前回は、3D Gaussian Splatting のビューアでした。

今回は、サイトの 3D 空間のほうです。監視室の GLB を使って、モニタがずらっと並んだ壁に、今まで作ったものを映しました。MSX のゲーム、MP4 の動画、SID の曲、の 3 つです。

壁のモニタには、映すだけでなく、メニューの役目もさせました。VR では、コントローラーから出るレーザーで、壁のモニタを押して操作します。

ターミナルで monitor と打つと、入れます。

画面

監視モニタのGLB

監視室のモニタ 監視室のモニタ

操作パネル UI

一番下のモニタでモード選択

シングルモニタ、マルチモニタにタイル表示、手前に大きなモニタ

下から二番目のモニタで各モードの選択

操作パネル UI

上のモニタ

上部のモニタにファイルリストと情報パネル

操作パネル UI

VIDEO

ビデオモードでは、事前に読み込んだMP4ファイルを再生。

BIGモード

VIDEOモード

タイルモード

VIDEOモード

GAME

過去に制作したMSX emulatorを起動。

VIDEOモード VIDEOモード VIDEOモード

SOUNDモード

SID PLAERを簡易移植。

SIDファイルの再生及び波形の表示。 SID の曲を再生している画面です。3 つのボイスの波形と、その下のスペクトラムを、壁のモニタを重ねた 1 枚の大きな画面に出しています。

監視室のモニタ壁に、SID の 3 ボイスの波形とスペクトラムが映っている画面

動画(WebXR)

WebVRに対応しています。 ファイルは事前にQuestブラウザで表示されてるFILEから読み込み。

作ったもの

全体

  • 監視室の GLB(Draco 圧縮で約 1.4 MB)を読み込みます
  • モニタの部分を、1 枚ずつ別のメッシュに分けて、28 枚にしました。それぞれのモニタに、平らな UV を張っています
  • 表示は、SINGLE(1 枚の画面を壁全体に出す)と TILE(1 つの画像を、壁のモニタに分けて出す)を選べます
  • 映すものは、VIDEO(MP4)、GAME(MSX)、SOUND(SID)です
  • BIG は、壁のモニタが手前に飛び出して、すきまなく 1 枚の大画面になります。もう一度押すと、壁に戻ります

壁がメニュー

右の列の、4 枚のモニタが、メニューです。

モニタ役目
MODELAYOUT(SINGLE / TILE / BIG)と、SOURCE(VIDEO / GAME / SOUND)の切り替え
一覧GAME なら ROM、VIDEO なら MP4、SOUND なら SID の曲
オプションGAME ならマッパー選択と RESET、VIDEO なら再生・ミュート、SOUND なら再生・前後の曲
STATUS状態の表示と EXIT

左右で分けたのは、LAYOUT と SOURCE が、まったく別の機能だからです。最初は 1 つの列に混ぜていて、「2 つ選ばれているのに、何が何だかわからない」という状態になっていました。

メニューの絵は、Canvas に描いて、モニタのテクスチャにしています。ボタンの位置は、押された UV から、当たったボタンを判定します。

GAME(MSX)

以前に作った、Z80 / MSX1 のエミュレーターを、壁に映しました。キーボードの入力は、GAME のときだけ拾います。VR では、コントローラーのスティックを十字キーに、トリガーをスペースに割り当てました。

ROM は、ファイルを追加したあと、端末内の IndexedDB に保存されます。ROM ごとに、マッパーも覚えます。

VIDEO

MP4 を、壁に映します。ファイルを追加すれば、一覧から選べます。ほかの画面に切り替えたときは、動画の再生を止めて、負荷を減らします。

SOUND(SID)

SOUND は、SID の曲を再生して、波形を出します。最初に、MP3 を再生してスペクトラムを出すものを作ってしまいましたが、これは、頼んだものとは違いました(あとの節に書きます)。

SID:既存のプレイヤーをそのまま使う

SID は、以前に作った SID Player があります。reSID と fake6502 を WASM にしたもので、AudioWorklet で鳴らしています。これを、コピーせずに、同じファイルを読み込んで使いました。

  • /sid/sid_core.wasm と、/sid/sid-processor.js の組み合わせです
  • 曲の読み込み(load)は、worklet にメッセージを送るだけです。WASM は worklet の側で動きます
  • 壁の側では、SidPlayer.ts という小さなファイルで、再生と、波形の描画だけをします。EQ や、鍵盤、プレイリストは、入れていません

波形が、めちゃくちゃになった

最初に出した波形は、縦の縞だらけで、使えるものではありませんでした。原因は、2 つあります。

  1. 大きさの自動調整が、ありませんでした。 元のプレイヤーは、波形の最大値に合わせて、大きさを自動で変えています。生の値は大きいので、枠からはみ出していました
  2. 断片を、つなげていました。 元の worklet は、23 回に 1 回だけ、128 サンプル(約 3 ms)の断片を送ってきます。それを 16 個つなげて、2048 サンプルの波形にしていたので、つなぎ目で線が上下に跳んでいました

最新の 128 サンプルだけを描くと、波形はきれいになりました。ただ、約 3 ms では短くて、すぐ消えてしまいます。

波形を、もう少し長く

壁用の worklet を、1 つ追加しました。sid-processor-wave.js です。元の sid-processor.js のコピーで、違うのは、波形の送り方だけです。連続した 512 サンプルを溜めて、まとめて送ります。壁の側では、それを 2048 サンプル(約 46 ms)の窓にして描いています。

元の sid-processor.js と、SID Player のページは、触っていません。共有しているファイルを、壁のために書き換えたくなかったからです。

その代わり、音が速いので、波形は、画面の上で、かなり細かく見えます。見た目は、3 ms のときよりは広がりましたが、劇的に変わったわけではありません。

スペクトラム

波形の下に、スペクトラムを 40 本、出しました。再生している音そのもの(ミックス)を、AnalyserNode に通して、低音側が広く見えるように、周波数を対数に近い形でまとめています。

詰まったこと

Quest で、重くて、レーザーも出なくなった

壁をメニューにしたところで、2D のブラウザは動いたのに、Quest の VR に入ると、カクカクで、レーザーも出ませんでした。

原因は、レイキャスト(当たり判定)でした。React Three Fiber の <primitive> に、クリックの処理をつけると、XR のポインターが、GLB の全部のメッシュを調べてしまいます。壁の全部が、毎フレーム、当たり判定の対象になっていました。

直し方は、次のとおりです。

  • メニューのモニタ以外のメッシュは、raycast を何もしない関数にします
  • ルートに、当たり判定の対象を、メニューのモニタだけだと伝えます

レーザーは、「クリックの処理をもつ物」に当たったときにしか出ません。そのため、メニューのモニタ以外では、レーザーが出ません。これは、不具合ではなく、そういう動きです。

余計なものを、足してしまった

壁をメニューにする作業の途中で、頼まれていない機能(SOUND など)を、一緒に作ってしまいました。そして、Quest で動かなくなったときに、原因が、どの変更なのか、切り分けられなくなりました。1 つずつ作って、実機で確かめるべきでした。

SOUND の意味を、取り違えた

SOUND は、最初から、SID の再生のことでした。それなのに、普通の MP3 を再生して、スペクトラムを出すものを作ってしまいました。MP3 だけなら、いらない機能でした。取り違えに気づいてからは、MP3 の再生を外して、SID に置き換えました。

調整した値を、上書きしてしまった

ファイルを差し替えたときに、手元の古い版で、BIG の距離や幅など、調整済みの値を戻してしまいました。調整は、作った側のリポジトリが正で、こちらの手元のコピーが古いことがあります。値を持つファイルを渡す前には、現行の値を確認することにしました。

ファイルを追加する

ROM、MP4、SID は、ADD FILES と ADD FOLDER のボタンで追加します。拡張子で、自動的に振り分けます。追加したファイルは、端末内の IndexedDB に残ります。サーバーには、上げません。

注意が、1 つあります。VR の中では、ファイル選択のダイアログが開きません。 ファイルの追加は、VR に入る前に、2D の画面でしておきます。

確認できたこと

  • PC のブラウザで、壁のメニューが動く(SINGLE / TILE / BIG、VIDEO / GAME / SOUND の切り替え)
  • Meta Quest 3 の VR で、壁のメニューをレーザーで選べる。GAME と VIDEO の切り替え、BIG が、すべての表示で動く(Quest で実機確認)
  • PC のブラウザで、SID の曲を再生して、3 ボイスの波形とスペクトラムが出る

未確認のこと・未対応のこと

  • SOUND(SID)を、Quest の VR では、まだ確かめていません。 PC のブラウザでだけ、動作を確認しました
  • VR での FPS は、測っていません。画面の右下に FPS などを出していますが、記事に載せられるほどの計測は、していません
  • SID の、1 曲(Nemesis_MSX_OST.sid)で、再生の途中で、波形が平らになり、音が止まったことがありました。コンソールには、IRQ count=0 と出ていました。原因は、わかっていません。元の SID Player でも同じかどうかを、確かめていません。SID Player は、もともと、一部の曲に対応していません
  • SID の曲番号は、先頭の曲だけです。サブ曲の切り替えは、ありません
  • ファイルを、VR の中から追加することはできません。VR の中でファイルを選べないためです。LAN 経由で取り込む案がありますが、試していません
  • 表示のボタンを、見た目だけ小さくして、押せる範囲は大きいままにする、という調整は、まだです

おわりに

壁のモニタを、映すだけでなく、操作する場所にしたことで、VR の中で、ほとんどの操作が、レーザーだけでできるようになりました。

今回は、動いたものを、また壊して、また直す、ということを、何度もしました。1 つずつ作って、実機で確かめる。当たり前のことですが、これが、一番、速いと思いました。

今は、v1 です。SID の曲が止まる件や、Quest での SOUND の確認は、次に、やります。