Closed6

WebAudioのパフォーマンスを改善するぞ

木瓜丸木瓜丸

実装している物

https://u-gen.site

  • Web上で音楽を作ってあそべる
  • ブラウザ上でオシレーターやサンプルをいじってシンセを作り、それをピアノロールで発声させる機能がある
  • WebAudioのAudioScheduleSourceNodeでは同時発声することができないので、同時に発声する場合には複数個のノードを作成している


現状見つかっている問題点

  • OscillatorNodeをstopした時にノイズが発生する
  • 同時に存在するノード数が一定数を越えると音が止まる(おそらくパフォーマンスの限界がきてる)

今考えている解決策

  • OscillatorNodeとAudioBufferSourceNodeで実現しているものを、すべてAudioWorkletで実装しなおしてみる
    • 現状のように複数個のノードを作成するのではなく、AudioWorklet側でMIDI信号を受けて発声している音階を管理しながら同時発声する
    • これにより、Node数が多すぎることによる問題と、stopを都度実行することによるノイズを同時に解決する
木瓜丸木瓜丸

WASM(Rust) + AudioWorkletでやりたい気持ちもあるが、とりあえず我慢する。
WASMを使うなら次を検証する

  • AudioWorkletのスレッドでWASMを使う場合、インスタンスは同一のものになるのか
  • それぞれのスレッドから同じメモリにアクセスし、波形情報をとったり入れたりできるのか
  • そもそもどのくらいメモリ確保してもいいものなのか(44100Hz x 10s x 2chくらいの音声データを非圧縮で展開して耐えるのか)
木瓜丸木瓜丸

課題

現状エンベロープをつけたり、LFOや別の音源でモジュレーションする機能があり、それをどのように実装するべきか

方針1

いっそエフェクトやモジュレーションも同時にエミュレーションしてしまう

方針2

  • モジュレーションに使うAudioNodeのパラメーターはprocessの第三引数で受ける
  • エンベロープのみエミュレーションする

方針1の方が圧倒的に大変だが、方針2だとそれぞれの音階に対して共通のモジュレーションソースを使うため、表現の幅が落ちるのは確実

木瓜丸木瓜丸

メモ:Rust WASMするくらいなら、OffscreenCanvas使ったほうがいい説
OffscreenCanvasをmessagePortから渡して、その中でthreejsでGPGPUして波形生成する

木瓜丸木瓜丸

とりあえず、全部モジュレーションする方針にしようかな。
オシレーターとサンプルの基本的な発声を作りこんで、LFOとAmplitureEnvelopeがよさげに動いたら各種エフェクトのエミュレーションも実装する形で

このスクラップは2024/01/16にクローズされました