ジンジャー研究室

長めのつぶやき。難しいことは書きません。

wasm ターゲットな言語を作って音を鳴らしてみた

前回、 Faust という言語を使って音を鳴らしてみたわけですが、AudioParam を使ったオートメーションに対応していないのでちょっと微妙だなと思いました。まあ Web が唯一のターゲットではないので仕方ない気はしますが。多分これができないと楽譜データからミックスダウンとかもできないはず。

じゃあということで次に試したのが EmscriptenC++ から出力するやつで、まあ動いたんですが、サイズがでかいとか、余計な JS コードがついてくるとか、バインディングを書くのが面倒くさいとか細かいところが色々気になったりしました。他にも Rust とか色々選択肢はあるんですが、どれにしても結局 AudioWorkletProcessor との接続部分は書かないといけないのが面倒で、ああ本当に面倒なのでそれ用の言語が作りたくなりました。

AssemblyScript を調べてたら binaryen.js という Binaryen のラッパーを使ってたので採用。この時点で LLVM が消えてターゲットが wasm のみに。脳みそが狐さん以下なので仕方ないですね。

作ったもの

名前はまだない。 github.com

こういう感じのコードを書くと、wasm モジュールとそれをラップした AudioWorkletProcessor が生成されます。デモはこちら

言語を作ったりするのは初心者もいいところなので、コスト削減のために大幅な割り切りをしています。

  • 動的なメモリの確保はできない
  • 型推論のような贅沢なものはもちろんない
  • 配列とループの長さは 128 決め打ち
  • 新しい型も作れない
  • if もねえ

逆に、あるもの

  • AudioParam 定義用の構文
  • VSCode 拡張

f:id:jinjor:20200415023948p:plain

エディタに色がつくと急にそれっぽい!

感想

wasm の特性なのかは不明ですが、 C っぽい言語が圧倒的に作りやすいというか、普通に普通の文法を動かすのが普通に大変で、それ以上の気の利いた文法とかはもう「動くんだから愚直に書けばいいでしょ」という気分になってきますね。 あと binaryen のレイヤーが高いのか、全然アセンブリ書いてる気がしないというか、結局アセンブリのこと何も分かってないかもしれない。うーん。

反省点としては、自作のパーサーコンビネーターがトークナイズしてないせいでホワイトスペースが至る所に出現してノイズが多いのと、VSCode 拡張(というか Language Server Protocol)で補間とか出そうとするとマメにコンテクストを管理しなきゃいけないなーっていうのに後で気づきました。直すの辛いけどやった方が良さそう。

まあとりあえず動いたので満足です。メンテナンスしたくないので広く公開することは多分ないけど。 早く FM 音源とか作りたい〜!