Z-MUSIC for the Webを使いたくてemsdkの環境をwindows10に入れてみた
もう3年以上前の話ですが、X68ユーザならご存じSION2をブラウザで動作するSION2 HDとして移植された @toyoshim氏がZ-MUSIC for the WebというJavaScriptでZ-MUZICを鳴らしてしまおうというモノを発表されていました。
去年あたりに発見し、これは素晴らしいということで自分でも使ってみたいと試してみたのですがドキュメントの通りJSを書いていても動作しない。。。再生方法が分からず、そのまま放置となってしまっていました。
かくして時は流れ、最近TwitterでMSXPlayというMSXの音源をWebで再生するサイトのシェアをちょいちょい見かけるようになりました。
サイトに記載されている、"C言語版の libkss を Emscripten で JavaScript に変換"というあたりはZ-MUSIC for the Webと同じような技術を使用しているっぽい。
Z-MUSIC for the Webもエディタと組み合わせれば同じようなことができるのかなぁ、羨ましすぎるぞ、MSX勢!ということで、Z-MUSIC for the Webに再度トライしていました。
GitHubの説明を読み返し、zmusic.jsをビルドする必要があるとの事で(後で分かりましたが実は不要だったのですが。。。)以下を試してみました。
git clone https://github.com/toyoshim/z-music.js.git cd z-music.js git submodule update --init --recursive git: 'submodule' is not a git command. See 'git --help'.
なぜかgitにsubmoduleが無いと言われてしまいます。
私の使っているgitはgnupack-pretest_develの2018.11.25に含まれているものでバージョンは2.17.0でした。
apt-cyg install gitとかやってみましたが状況は変わらないので、SourceTreeに内蔵されているgitにパスを通してこちらを使用したところ、無事git submoduleが起動しました。
ちなみにSourceTreeのgitは$USERPROFILE/AppData/Local/Atlassian/SourceTree/git_local/binにありました。
この下にはgitだけでなく、bashやshも含まれているのでcygwinのコマンドのパス(/usr/bin)より前に設定するとapt-cygなどが動作しなくなりました。git submoduleを使用した後は元に戻した方が良いでしょう。
とにかくこれでmakeが実行できるようになりました。
make mkdir -p out emcc -DFNC_TRACE -DENV_FROM_INI -DEMSCRIPTEN_KEEPR -include third_party/run68as/mod/preinc.h -I third_party/run68as/third_party/run68/src -I third_party/X68Sound/X68Sound -I src/compat -Oz -MM third_party/run68as/third_party/run68/src/ansicolor-w32.c third_party/run68as/third_party/run68/src/calc.c third_party/run68as/third_party/run68/src/conditions.c third_party/run68as/third_party/run68/src/disassemble.c third_party/run68as/third_party/run68/src/eaaccess.c third_party/run68as/third_party/run68/src/exec.c third_party/run68as/third_party/run68/src/getini.c third_party/run68as/third_party/run68/src/key.c third_party/run68as/third_party/run68/src/line0.c third_party/run68as/third_party/run68/src/line2.c third_party/run68as/third_party/run68/src/line5.c third_party/run68as/third_party/run68/src/line6.c third_party/run68as/third_party/run68/src/line7.c third_party/run68as/third_party/run68/src/line8.c third_party/run68as/third_party/run68/src/line9.c third_party/run68as/third_party/run68/src/lineb.c third_party/run68as/third_party/run68/src/linec.c third_party/run68as/third_party/run68/src/lined.c third_party/run68as/third_party/run68/src/linee.c third_party/run68as/third_party/run68/src/load.c third_party/run68as/mod/line4.c third_party/run68as/mod/linef.c third_party/run68as/mod/mem.c third_party/run68as/mod/run68.c src/doscall.c src/iocscall.c src/memop.c src/zmusic.cpp src/compat/compat.cpp src/x68sound.cpp> out/depend /bin/sh: emcc: コマンドが見つかりません make: *** 'all' に必要なターゲット 'out/depend' を make するルールがありません. 中止. /bin/sh: emcc: コマンドが見つかりません
が、今度はemccが無いと怒られてしまいます。
どうやらemsdk (Emscripten) の環境も必要という事で、今度はemsdkのリポジトリを覗いてみました。
emsdkとはCやC++のコードをJavaScriptに変換して動作させる為のツール群の様です。
Z-MUSIC for the Webではrun68やx68soundをJavaScriptに変換してさらにエミュレーションを追加して動作させているようです。
まさに超絶技術ですね。
一応Windowsでもビルドできる記述があったのでcygwin上から以下を試しました。
git clone https://github.com/emscripten-core/emsdk.git cd emsdk/ ./emsdk install latest Traceback (most recent call last): File "./emsdk.py", line 3073, in <module> sys.exit(main()) File "./emsdk.py", line 2781, in main load_sdk_manifest() File "./emsdk.py", line 2336, in load_sdk_manifest add_sdk(sdk) File "./emsdk.py", line 1972, in add_sdk raise Exception('Duplicate sdk ' + str(sdk) + '! Existing:\n{' + ', '.join("%s: %s" % item for item in vars(find_sdk(str(sdk))).items()) + '}, New:\n{' + ', '.join("%s: %s" % item for item in vars(sdk).items()) + '}') Exception: Duplicate sdk sdk-upstream-master-64bit! Existing: {version: upstream-master, bitness: 64, uses: ['llvm-git-master-64bit', 'node-12.18.1-64bit', 'python-3.7.4-64bit', 'emscripten-master-64bit', 'binaryen-master-64bit'], os: win, id: sdk, name: sdk-upstream-master-64bit, is_old: False, is_sdk: True}, New: {version: upstream-master, bitness: 64, uses: ['llvm-git-master-64bit', 'node-12.18.1-64bit', 'emscripten-master-64bit', 'binaryen-master-64bit'], os: linux, id: sdk, name: sdk-upstream-master-64bit, is_old: False, is_sdk: True}
Exception: Duplicate sdk sdk-upstream-master-64bit! から察するにpythonが怪しいけどよく分からん。
cygwinのpythonは2.7.14でemsdkの推奨バージョン以上だけど、cygwinで動かすのがそもそもサポートされていないかも。。。
という事で、DOSからemsdk.batを起動するため、まずはDOSを起動してpythonコマンドをたたいてみました。
するとMicrosoftStoreが勝手に起動してPythonをおすすめしてくれたのであまり考えずにインストール。
DOSから再度pythonをたたくと3.7.8がインストールされたので、以下を実行。
> .\emsdk.bat install latest Installing SDK 'sdk-releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'.. Skipped installing node-12.18.1-64bit, already installed. Skipped installing python-3.7.4-pywin32-64bit, already installed. Skipped installing java-8.152-64bit, already installed. Installing tool 'releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'.. Downloading: C:/hoge/emsdk/zips/e7e39da9c81faecd9ecf44065cee864d76e4e34d-wasm-binaries.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/e7e39da9c81faecd9ecf44065cee864d76e4e34d/wasm-binaries.zip, 551241164 Bytes Unpacking 'C:/hoge/emsdk/zips/e7e39da9c81faecd9ecf44065cee864d76e4e34d-wasm-binaries.zip' to 'C:/hoge/emsdk/upstream' Done installing tool 'releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'. Running post-install step: npm ci ... Done running: npm ci Done installing SDK 'sdk-releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit'.
無事インストールできました。次に環境の設定を行うため以下を実行。
> .\emsdk.bat activate latest Setting the following tools as active: node-12.18.1-64bit python-3.7.4-pywin32-64bit java-8.152-64bit releases-upstream-e7e39da9c81faecd9ecf44065cee864d76e4e34d-64bit Adding directories to PATH: PATH += \hoge\emsdk PATH += \hoge\emsdk\node\12.18.1_64bit\bin PATH += \hoge\emsdk\python\3.7.4-pywin32_64bit PATH += \hoge\emsdk\java\8.152_64bit\bin PATH += \hoge\emsdk\upstream\emscripten Setting environment variables: EMSDK = C:/hoge/emsdk EM_CONFIG = \hoge\emsdk\.emscripten EMSDK_NODE = \hoge\emsdk\node\12.18.1_64bit\bin\node.exe EMSDK_PYTHON = \hoge\emsdk\python\3.7.4-pywin32_64bit\python.exe JAVA_HOME = \hoge\emsdk\java\8.152_64bit EM_CACHE = C:/hoge/emsdk/upstream/emscripten\cache The changes made to environment variables only apply to the currently running shell instance. Use the 'emsdk_env.bat' to re-enter this environment later, or if you'd like to permanently register this environment globally to all users in Windows Registry, rerun this command with the option --global.
こちらも無事インストールされました。(のかな?)
これでやっとzmusic.jsがビルドできるようになりましたが、DOSにはmakeの環境が入っていません。
なので、cygwin(bash)の環境に上記のパスや環境変数をセットします。
~/.bash_profileに追記
export EMSDK=/hoge/emsdk export EM_CONFIG=$EMSDK/.emscripten export EMSDK_NODE=$EMSDK/node/12.18.1_64bit/bin/node.exe export EMSDK_PYTHON=$EMSDK/python/3.7.4-pywin32_64bit/python.exe #export JAVA_HOME=$EMSDK/java\8.152_64bit PATH=$EMSDK/:$EMSDK/node/12.18.1_64bit/bin:$EMSDK/python/3.7.4-pywin32_64bit:$EMSDK/upstream/emscripten:$PATH #$EMSDK/java/8.152_64bit/bin
JAVA_HOMEとjavaのパスは既に別のjava1.8がインストールしてあったので、省略しています。
bashを起動し、やっとzmusic.jsのmakeが通りました!
ということで、ディレクトリ配下にできあがったzmusic.jsと以下のファイルを用意し、chromeで表示してみました。
test.zms
(i) (m1,3000)(aFm1,1) (@1,28, 1, 7, 9, 0, 28, 0, 1, 0, 0, 0 30, 1, 8, 10, 0, 1, 0, 1, 0, 0, 0 29, 1, 8, 9, 0, 19, 0, 1, 3, 0, 0 31, 1, 8, 10, 0, 1, 0, 1, 3, 0, 0 4, 7) (o127) (t1) @01o4l8 cdefgab (p)
<html> <head> <!-- <script src="zmusic.asm.js"></script> --> <script src="zmusic.js"></script> <script> // Make XHR to support Promise. function xhr (url) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.addEventListener('load', e => { resolve(xhr.response); xhr.abort(); }, false); xhr.send(); }); } Promise.all([ ZMUSIC.install(), xhr('./test.zms') ]).then(results => { ZMUSIC.play(results[1]); }); </script> </head> </html>
するとブラウザに色々エラーが出てきました。たしか以前もこれで止まってしまっていたのだと思います。
both async and sync fetching of the wasm failed RuntimeError: abort(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info. Access to XMLHttpRequest at 'file:///C:/hoge/test.zms' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
CORSのエラーも出ているので、そもそもWEBサーバ経由で表示しないとだめっぽいです。
WEBサーバ(nginx)のドキュメントルート配下にファイルを置いて、再度アクセス。
上記のエラーは全て解消されましたが、zmusic.wasm 404 (Not Found)のエラーが。
なるほど、z-music.js/dist/の中にzmusic.wasmがありがましたが、こちらも必要だったようです。
あらためてアクセスすると今度は以下のエラーが。
wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.
nginx(多分apacheも同様)のデフォルトのmime-typeにはapplication/wasmが無かったので、追加する必要があります。
/etc/nginx/mime.typesに次の行を追加して、nginxを再起動しました。
application/wasm wasm;
まだエラーが残っていて再生されませんが、最後のエラー
The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page
は、どうやらJSでいきなり音を再生することは許可されていなくて、(ボタンクリックなど)何らかのユーザからのインタラクションが必要な様です。(後で確認したら、Chromeで発生し、Firefoxでは再生されました)
なのでHTMLにbuttonタグを追加し、onclickでZMUSICの処理を起動したところ、遂に再生されました!
長かったですが、やっと再生させることができました。
で、ここまできてそういえばz-music.js/dist/の下に初めからzmusic.jsやzmusic.wasmあったなーと思い返し、一旦z-music.js/dist/の下のファイルを削除、再度リモートからチェックアウトしたファイルで確認したところ、問題無く動作しました。(汗
ということで、emsdkを使用したビルド済みのファイルが初めから提供されていましたというオチですが、emsdkとは何かが分かったし、今後z-music.jsに修正が入っても自分でビルドできるぞという事で、無駄ではなかったかなと思います。
最後に、こんな素晴らしいJSを公開してくださった@toyoshim氏に大変感謝いたします。