logue SDKには以前、開発中のWebシミュレータが存在していました。こちらの記事で紹介しています。

その後、この機能はSDK本体に統合されないままになっていたのですが、最近になって新たなWebシミュレータがSDK本体に追加されました。(ただし現在のところ、サポートされているデバイスはNTS-1 mkIIとNTS-3 kaoss padのみとなっています。)
更新版のSDKでは、Makefileにターゲットwasmが追加され、
$ make wasm
でWebシミュレータの必要なファイル一式が生成されるようになっています。
ただしこれに伴い、テンプレートとなるファイル(unit.ccおよびosc.h, modfx.h, delay.h, reverb.h, effect.h)も以前のファイルから若干変更されています。
Webシミュレータをビルドする際には、Webシミュレータのメインファイルであるwasm.ccからosc.h等をインクルードする形になります。そのため、従来のテンプレートを使って作成したユニットをWebシミュレータ対応にするためには、コードの修正が必要になります。(今回はこの修正に関する話は省略します。)
以下、Linux環境でWebシミュレータを作成する方法を簡単に解説します。(私の環境はUbuntu24ですので、それを前提にしています。)
ツールのインストール
まず準備として、emscriptenをインストールする必要があります。
これは
$ cd logue-sdk/
$ git submodule update --init
$ cd tools/emsdk/
$ ./emsdk install latest
$ ./emsdk activate latest
でインストールできます。logue SDKのMakefileを使ってビルドするだけであれば、これでemscriptenの環境が整います。
なお
$ source ./emsdk_env.sh
でemccコマンドがPATHに追加され、利用可能になります。例えばhvccでPure DataパッチをJavaScriptに変換する場合には、これも必要になります。
サンプルのビルド
NTS-1 mkII用のdummy-oscプロジェクトは、最近の更新でサイン波を生成するようになりましたので、このdummy-oscプロジェクトのWebシミュレータをビルドしてみます。
$ cd logue-sdk/platform/nts-1_mkii/dummy-osc
$ make wasm
これでビルドが完了すると、HTTPサーバが起動され、WebブラウザでWebシミュレータのページが開かれます。
もしブラウザとしてchromeが使える状態になっていない場合はエラーになりますが、Makefileの最後の行の
@$(EMCC_BIN_PATH)/emrun --browser chrome --serve_after_close $(WASMDIR)/$(PROJECT).html
の”--browser chrome“を削除すればデフォルトのWebブラウザが利用されます。(なお私のLinux上のFirefoxでは、動作はするものの、音が出力されませんでした。)

ここまででいったん、Webシミュレータとしては完成なのですが、次にこれをWebサーバ上に置くことを検討してみます。
ローカルのサーバに置いてアクセスしてみる
まずサーバに置くファイルですが、Webシミュレータのファイルはディレクトリsim/の下に生成されています。
$ cd sim
$ ls -CFx
bitres_lut.c dummy_osc.html dummy_osc.js dummy_osc.wasm*
fx_api.cpp header.c images/ log_lut.c
midi_to_hz_lut.c osc_api.cpp pow2_lut.c samples/
saturate.c scripts/ sqrtm2log_lut.c tanh_lut.c
tanpi_lut.c unit.cc wasm.cc* waves-a.c
waves-b.c waves-c.c waves-d.c waves-e.c
waves-f.c wavetable_lut.c
ここにはサーバ上に置く必要のないソースコードも含まれています。この中で、Webサーバ上に置く必要があるのは以下のファイルです。
・dummy_osc.html
・dummy_osc.js
・dummy_osc.wasm
・scripts, samples, imagesの各フォルダとその中身(samplesはエフェクトの動作確認用の入力音声)
これらのファイルを置くWebサーバですが、以下の2つの要件があります。
・HTTPSでアクセスできること
・COOP/COEPヘッダを送ること
HTTPSが必要なのは、以前の記事でも書きましたが、ブラウザのセキュリティ制約上、AudioWorkletを使用するにはコンテンツがHTTPSで配信されている(Secure Contextsでの利用である)必要があるためです。
ただし例外があり、localhostはSecureであると見なされます。つまり、http://localhost:port/でのアクセスはOKです。
ちなみに、私はUbuntuをWidnowsをホストにしたVMWare上で利用しています(Widnwosとは別の192.168.x.xのIPアドレスになります)ので、UbuntuをWindowsから見てlocalhostにするには
・Windows(localhost)のポートをUbuntu側にポートフォワーディングする
・Windows側でリバースproxyサーバを動かしてUbuntuのサーバをlocalhost上で動いているように見せる
などの手間をかける必要があります。私はWidnows版nginxを使い、以下のような設定をnginx.confに書いています。(http://192.168.xxx.xxx:8000はサーバを動かすVMware側のIPアドレスおよびポート番号)
http {
server {
listen 8000;
location / {
proxy_pass http://192.168.xxx.xxx:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
次に、COOP/COEPヘッダです。
emscriptenの生成したWASM AudioWorkletはSharedArrayBufferを使った通信を行います。実はCPUの脆弱性のために、この通信は他のスレッドから傍受されるリスクがあります。その対策として、ブラウザはこの通信を行うプロセスを他のプロセスから隔離することができます。COOP/COEPヘッダによって指示されると、ブラウザはこの隔離を行います。
従って、WebサーバからCOOP/COEPヘッダを送る必要があります。このヘッダは通常のWebサーバは送ってくれませんので、公開Webサーバの場合は設定でこのヘッダを送らせる必要があります。
たとえばnginxでは以下のような設定が必要になるようです。
add_header Cross-Origin-Opener-Policy same-origin always;
add_header Cross-Origin-Embedder-Policy require-corp always;
このヘッダの意味合いですが、
COOP:ウィンドウやタブのプロセスを他オリジンのページと分離し、同じブラウザプロセスに混在させない
COEP:埋め込む外部リソースをCORP(サーバが発行)およびCORS(クライアントが要求しサーバが許可)で許可されたものだけに制限する
ことを指定しています。HTMLページがcross-origin isolatedであるためには、この両方を満たす必要があります。cross-origin isolatedでない場合、SharedArrayBufferを使ったEmscriptenの AudioWorkletが動作せず、下図のようにWebシミュレータが正常に動作しません。

テスト目的では、COOP/COEPヘッダを送信するサーバを、Pythonを使って以下のように実装できます。
from http.server import SimpleHTTPRequestHandler, HTTPServer
class COOP_COEP_Handler(SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
super().end_headers()
HTTPServer(("0.0.0.0", 8000), COOP_COEP_Handler).serve_forever()
このサーバをUbuntu上で走らせて、Windows上で稼働するnginxをリバースプロキシとしてこのサーバに向ければ、wasmビルドしたユーザユニットをChrome上で確認することができます。
公開のWebサーバ上に載せるのは、ヘッダの追加が必要になりますのでちょっと敷居が高そうです。


コメント