Hello,
I’m currently porting a old game engine to libretro and I’m having some problems to understand how a core is supposed to use the audio callback. The main issue is how to cleanly shut down the core’s audio without knowing when the audio callback thread has stopped.
This is what is going on on a high level:
main thread:
- initialize game
- spawn audio mixer thread
- register audio callback via
environment_cb(RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK)
- render frames repatedly in
retro_run
audio mixer thread:
- mix audio into a back buffer
- wait for a front audio buffer currently being played to be finished playing
- swap front and back buffers and repeat
(frontent)audio callback thread:
- wait for a buffer swap from the audio mixer thread
- upload the new front buffer to the frontend using
audio_batch_cb
- signal the audio mixer thread that the buffer has been uploaded
- repeat
This runs quite well until I want to unload the game. I have no idea inside of the core what the state of the audio callback thread is. In an older version of retroarch (v1.7.3) it seemed like this thread was torn down before unloading the core. But the most recent version from github seems to have changed. The audio callback thread keeps running until the retro_unload_game
completed.
What should a core do in this case? I tried deregistering the audio callback at the beginning of retro_unload_game
but then again the core has no idead when the audio callback thread is actually stopped. I tried signalling my code running in the audio callback to stop waiting for a buffer swap and stop accessing any datastructures from the audio mixer thread. But the audio callback thread might actually be blocked inside audio_batch_cb
where I have no control over when this will return. Actually I don’t even know if the audio callback thread is actually still runnning as other frontends might treat this differently.
The only thing that could work in my mind is keeping my audio thread around until after retro_unload_game
returns and clean it up later in retro_deinit
. But even this is making assumptions when the audio callback thread is being stopped. I didn’t find anything mentioned regarding this in the docs or elsewhere. Also in my case the game code will create the audio thread after loading content which defines properties like sample rate and the mixer buffer size use by the mixer thread. So keeping it around until after retro_unload_game
is cumbersome as it actually means I cannot unload the game really as this would tear down the audio subsystem inside of it hosting
I hope I’m missing something really abvious. Is there a way to handle this situatiuon gracefully? Should I simply not use the audio callback?
Thanks in advance!