Open4

pthread emscriptenでもSDL2のオーディオ出力したい

okuokuokuoku

問題

問題は、SDL2の実装手法の都合でオーディオコールバックは常にメインスレッドから呼ばれるという点がある。SDL2は(既にdeprecatedだけど)Web Audioの ScriptProcessorNode を使用して、そこからのコールバックにPCMデータを埋めさせるという手法を使っている。ここでは、ほぼそのまま SDL_OpenAudio APIに渡したコールバックが呼ばれることになる。

https://github.com/libsdl-org/SDL/blob/38619bb28db83bc5844d13d99b3072496adcd498/src/audio/emscripten/SDL_emscriptenaudio.c#L334-L344

今回、blockingなAPIを自由に使いたいがためにプログラム全体をサブスレッドで動かすという方法を取っているが、この ScriptProcessorNode に渡したコールバックはworkerではなくメインスレッドに無ければならない。

okuokuokuoku

手動で PROXY_TO_PTHREAD する

https://github.com/okuoku/dosbox-x/commit/256e1664de9f6de6e2fe53c4ffd6c742eca8b7c8

やることは簡単で、

https://github.com/okuoku/dosbox-x/blob/e62e75849ece9964ef248ad8f9d27926410b1204/src/gui/sdlmain.cpp#L7594-L7597

main を別名に置き換えてしまい、自分でmainを pthread_createしたスレッドから呼出すようなコードを実装する。

SDL_OpenAudio も置き換えておき、メインスレッドでは毎フレーム置き換えた SDL_OpenAudio が呼出されていないか監視し、必要に応じて実際の SDL_OpenAudio 呼出しを行う。

https://github.com/okuoku/dosbox-x/blob/emscripten-build-fix/src/gui/sdlmain.cpp#L9811-L9823

元々、SDLのオーディオコールバックは別スレッドから呼ばれる可能性があるものなので、コールバックだけメインスレッドから呼ぶ形にしても特に問題はない。