From fb562c8077c9e14bde11e673352e83756e081f69 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Sat, 29 Jul 2023 12:43:02 +0000 Subject: [PATCH] safely close audio on game exit --- .../Audio/Oboe/OboeHardwareDeviceDriver.cs | 7 +- .../Audio/Oboe/OboeHardwareDeviceSession.cs | 22 ++- src/LibRyujinx/Android/JniExportedMethods.cs | 3 +- src/RyujinxAndroid/app/src/main/cpp/oboe.cpp | 176 +++++++++--------- 4 files changed, 117 insertions(+), 91 deletions(-) diff --git a/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceDriver.cs b/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceDriver.cs index c56d0fe38..7377b171e 100644 --- a/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceDriver.cs +++ b/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceDriver.cs @@ -62,11 +62,6 @@ namespace LibRyujinx.Shared.Audio.Oboe return session; } - internal bool Unregister(OboeHardwareDeviceSession session) - { - return _sessions.TryRemove(session, out _); - } - public void Dispose() { Dispose(true); @@ -82,6 +77,8 @@ namespace LibRyujinx.Shared.Audio.Oboe } _pauseEvent.Dispose(); + + _sessions.Clear(); } } diff --git a/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceSession.cs b/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceSession.cs index b23426d30..76b41d802 100644 --- a/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceSession.cs +++ b/src/LibRyujinx/Android/Audio/Oboe/OboeHardwareDeviceSession.cs @@ -10,6 +10,7 @@ namespace LibRyujinx.Shared.Audio.Oboe internal class OboeHardwareDeviceSession : HardwareDeviceSessionOutputBase { private OboeHardwareDeviceDriver _driver; + private bool _isClosed; private bool _isWorkerActive; private Queue _queuedBuffers; private bool _isActive; @@ -59,6 +60,9 @@ namespace LibRyujinx.Shared.Audio.Oboe { StartIfNotPlaying(); + if (_isClosed) + break; + fixed(byte* ptr = buffer.Data) OboeInterop.WriteToSession(_session, (ulong)ptr, buffer.SampleCount); @@ -90,18 +94,31 @@ namespace LibRyujinx.Shared.Audio.Oboe public override void Dispose() { + if (_session == 0) + return; + + PrepareToClose(); + OboeInterop.CloseSession(_session); + + _session = 0; } + public override void PrepareToClose() { + _isClosed = true; _isWorkerActive = false; - _workerThread.Join(); + _workerThread?.Join(); + Stop(); } private void StartIfNotPlaying() { lock (_trackLock) { + if (_isClosed) + return; + if (OboeInterop.IsPlaying(_session) == 0) { Start(); @@ -145,6 +162,9 @@ namespace LibRyujinx.Shared.Audio.Oboe public override void Start() { + if (_isClosed) + return; + OboeInterop.StartSession(_session); } diff --git a/src/LibRyujinx/Android/JniExportedMethods.cs b/src/LibRyujinx/Android/JniExportedMethods.cs index f7f04a732..013b9bbec 100644 --- a/src/LibRyujinx/Android/JniExportedMethods.cs +++ b/src/LibRyujinx/Android/JniExportedMethods.cs @@ -72,8 +72,6 @@ namespace LibRyujinx var init = Initialize(path, enableDebugLogs); - // AudioDriver = new OboeHardwareDeviceDriver(); - _surfaceEvent?.Set(); _surfaceEvent = new ManualResetEvent(false); @@ -104,6 +102,7 @@ namespace LibRyujinx JStringLocalRef timeZone, JBoolean ignoreMissingServices) { + AudioDriver = new OboeHardwareDeviceDriver(); return InitializeDevice(isHostMapped, useNce, (SystemLanguage)(int)systemLanguage, diff --git a/src/RyujinxAndroid/app/src/main/cpp/oboe.cpp b/src/RyujinxAndroid/app/src/main/cpp/oboe.cpp index 61b605ab5..f643a4fbe 100644 --- a/src/RyujinxAndroid/app/src/main/cpp/oboe.cpp +++ b/src/RyujinxAndroid/app/src/main/cpp/oboe.cpp @@ -10,8 +10,11 @@ void AudioSession::initialize() { } void AudioSession::destroy() { + if(stream == nullptr) + return; stream->close(); - delete stream; + + stream = nullptr; } void AudioSession::start() { @@ -37,101 +40,108 @@ extern "C" JNIEXPORT void JNICALL Java_org_ryujinx_android_NativeHelpers_setDeviceId( JNIEnv *env, -jobject instance, - jint device_id){ + jobject instance, + jint device_id) { s_device_id = device_id; } - AudioSession* create_session(int sample_format, - uint sample_rate, - uint channel_count) - { - using namespace oboe; +AudioSession *create_session(int sample_format, + uint sample_rate, + uint channel_count) { + using namespace oboe; - AudioStreamBuilder builder; + AudioStreamBuilder builder; - AudioFormat format; + AudioFormat format; - switch (sample_format) { - case 0: - format = AudioFormat::Invalid; - break; - case 1: - case 2: - format = AudioFormat::I16; - break; - case 3: - format = AudioFormat::I24; - break; - case 4: - format = AudioFormat::I32; - break; - case 5: - format = AudioFormat::Float; - break; - default: - std::ostringstream string; - string << "Invalid Format" << sample_format; + switch (sample_format) { + case 0: + format = AudioFormat::Invalid; + break; + case 1: + case 2: + format = AudioFormat::I16; + break; + case 3: + format = AudioFormat::I24; + break; + case 4: + format = AudioFormat::I32; + break; + case 5: + format = AudioFormat::Float; + break; + default: + std::ostringstream string; + string << "Invalid Format" << sample_format; - throw std::runtime_error(string.str()); - } + throw std::runtime_error(string.str()); + } - auto session = new AudioSession(); - session->initialize(); + auto session = new AudioSession(); + session->initialize(); - session->format = format; - session->channelCount = channel_count; + session->format = format; + session->channelCount = channel_count; - builder.setDirection(Direction::Output) + builder.setDirection(Direction::Output) ->setPerformanceMode(PerformanceMode::LowLatency) - ->setSharingMode(SharingMode::Shared) - ->setFormat(format) - ->setChannelCount(channel_count) - ->setSampleRate(sample_rate); - AudioStream* stream; - if(builder.openStream(&stream) != oboe::Result::OK) - { - delete session; - return nullptr; - } - session->stream = stream; - - return session; - } - - void start_session(AudioSession* session) - { - session->start(); - } - - void stop_session(AudioSession* session) - { - session->stop(); - } - - void set_session_volume(AudioSession* session, float volume) - { - session->volume = volume; - } - - float get_session_volume(AudioSession* session) - { - return session->volume; - } - - void close_session(AudioSession* session) - { - session->destroy(); - + ->setSharingMode(SharingMode::Shared) + ->setFormat(format) + ->setChannelCount(channel_count) + ->setSampleRate(sample_rate); + AudioStream *stream; + if (builder.openStream(&stream) != oboe::Result::OK) { delete session; + session = nullptr; + return nullptr; } + session->stream = stream; - bool is_playing(AudioSession* session) { - return session->isStarted; - } + return session; +} - void write_to_session(AudioSession* session, uint64_t data, uint64_t samples) - { - session->read(data, samples); - } +void start_session(AudioSession *session) { + if (session == nullptr) + return; + session->start(); +} + +void stop_session(AudioSession *session) { + if (session == nullptr) + return; + session->stop(); +} + +void set_session_volume(AudioSession *session, float volume) { + if (session == nullptr) + return; + session->volume = volume; +} + +float get_session_volume(AudioSession *session) { + if (session == nullptr) + return 0; + return session->volume; +} + +void close_session(AudioSession *session) { + if (session == nullptr) + return; + session->destroy(); + + delete session; +} + +bool is_playing(AudioSession *session) { + if (session == nullptr) + return false; + return session->isStarted; +} + +void write_to_session(AudioSession *session, uint64_t data, uint64_t samples) { + if (session == nullptr) + return; + session->read(data, samples); +} } \ No newline at end of file