safely close audio on game exit

This commit is contained in:
Emmanuel Hansen 2023-07-29 12:43:02 +00:00
parent 2999275ed2
commit fb562c8077
4 changed files with 117 additions and 91 deletions

View File

@ -62,11 +62,6 @@ namespace LibRyujinx.Shared.Audio.Oboe
return session; return session;
} }
internal bool Unregister(OboeHardwareDeviceSession session)
{
return _sessions.TryRemove(session, out _);
}
public void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
@ -82,6 +77,8 @@ namespace LibRyujinx.Shared.Audio.Oboe
} }
_pauseEvent.Dispose(); _pauseEvent.Dispose();
_sessions.Clear();
} }
} }

View File

@ -10,6 +10,7 @@ namespace LibRyujinx.Shared.Audio.Oboe
internal class OboeHardwareDeviceSession : HardwareDeviceSessionOutputBase internal class OboeHardwareDeviceSession : HardwareDeviceSessionOutputBase
{ {
private OboeHardwareDeviceDriver _driver; private OboeHardwareDeviceDriver _driver;
private bool _isClosed;
private bool _isWorkerActive; private bool _isWorkerActive;
private Queue<OboeAudioBuffer> _queuedBuffers; private Queue<OboeAudioBuffer> _queuedBuffers;
private bool _isActive; private bool _isActive;
@ -59,6 +60,9 @@ namespace LibRyujinx.Shared.Audio.Oboe
{ {
StartIfNotPlaying(); StartIfNotPlaying();
if (_isClosed)
break;
fixed(byte* ptr = buffer.Data) fixed(byte* ptr = buffer.Data)
OboeInterop.WriteToSession(_session, (ulong)ptr, buffer.SampleCount); OboeInterop.WriteToSession(_session, (ulong)ptr, buffer.SampleCount);
@ -90,18 +94,31 @@ namespace LibRyujinx.Shared.Audio.Oboe
public override void Dispose() public override void Dispose()
{ {
if (_session == 0)
return;
PrepareToClose();
OboeInterop.CloseSession(_session); OboeInterop.CloseSession(_session);
_session = 0;
} }
public override void PrepareToClose() public override void PrepareToClose()
{ {
_isClosed = true;
_isWorkerActive = false; _isWorkerActive = false;
_workerThread.Join(); _workerThread?.Join();
Stop();
} }
private void StartIfNotPlaying() private void StartIfNotPlaying()
{ {
lock (_trackLock) lock (_trackLock)
{ {
if (_isClosed)
return;
if (OboeInterop.IsPlaying(_session) == 0) if (OboeInterop.IsPlaying(_session) == 0)
{ {
Start(); Start();
@ -145,6 +162,9 @@ namespace LibRyujinx.Shared.Audio.Oboe
public override void Start() public override void Start()
{ {
if (_isClosed)
return;
OboeInterop.StartSession(_session); OboeInterop.StartSession(_session);
} }

View File

@ -72,8 +72,6 @@ namespace LibRyujinx
var init = Initialize(path, enableDebugLogs); var init = Initialize(path, enableDebugLogs);
// AudioDriver = new OboeHardwareDeviceDriver();
_surfaceEvent?.Set(); _surfaceEvent?.Set();
_surfaceEvent = new ManualResetEvent(false); _surfaceEvent = new ManualResetEvent(false);
@ -104,6 +102,7 @@ namespace LibRyujinx
JStringLocalRef timeZone, JStringLocalRef timeZone,
JBoolean ignoreMissingServices) JBoolean ignoreMissingServices)
{ {
AudioDriver = new OboeHardwareDeviceDriver();
return InitializeDevice(isHostMapped, return InitializeDevice(isHostMapped,
useNce, useNce,
(SystemLanguage)(int)systemLanguage, (SystemLanguage)(int)systemLanguage,

View File

@ -10,8 +10,11 @@ void AudioSession::initialize() {
} }
void AudioSession::destroy() { void AudioSession::destroy() {
if(stream == nullptr)
return;
stream->close(); stream->close();
delete stream;
stream = nullptr;
} }
void AudioSession::start() { void AudioSession::start() {
@ -44,8 +47,7 @@ jobject instance,
AudioSession *create_session(int sample_format, AudioSession *create_session(int sample_format,
uint sample_rate, uint sample_rate,
uint channel_count) uint channel_count) {
{
using namespace oboe; using namespace oboe;
AudioStreamBuilder builder; AudioStreamBuilder builder;
@ -89,9 +91,9 @@ jobject instance,
->setChannelCount(channel_count) ->setChannelCount(channel_count)
->setSampleRate(sample_rate); ->setSampleRate(sample_rate);
AudioStream *stream; AudioStream *stream;
if(builder.openStream(&stream) != oboe::Result::OK) if (builder.openStream(&stream) != oboe::Result::OK) {
{
delete session; delete session;
session = nullptr;
return nullptr; return nullptr;
} }
session->stream = stream; session->stream = stream;
@ -99,39 +101,47 @@ jobject instance,
return session; return session;
} }
void start_session(AudioSession* session) void start_session(AudioSession *session) {
{ if (session == nullptr)
return;
session->start(); session->start();
} }
void stop_session(AudioSession* session) void stop_session(AudioSession *session) {
{ if (session == nullptr)
return;
session->stop(); session->stop();
} }
void set_session_volume(AudioSession* session, float volume) void set_session_volume(AudioSession *session, float volume) {
{ if (session == nullptr)
return;
session->volume = volume; session->volume = volume;
} }
float get_session_volume(AudioSession* session) float get_session_volume(AudioSession *session) {
{ if (session == nullptr)
return 0;
return session->volume; return session->volume;
} }
void close_session(AudioSession* session) void close_session(AudioSession *session) {
{ if (session == nullptr)
return;
session->destroy(); session->destroy();
delete session; delete session;
} }
bool is_playing(AudioSession *session) { bool is_playing(AudioSession *session) {
if (session == nullptr)
return false;
return session->isStarted; return session->isStarted;
} }
void write_to_session(AudioSession* session, uint64_t data, uint64_t samples) void write_to_session(AudioSession *session, uint64_t data, uint64_t samples) {
{ if (session == nullptr)
return;
session->read(data, samples); session->read(data, samples);
} }
} }