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;
}
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();
}
}

View File

@ -10,6 +10,7 @@ namespace LibRyujinx.Shared.Audio.Oboe
internal class OboeHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
private OboeHardwareDeviceDriver _driver;
private bool _isClosed;
private bool _isWorkerActive;
private Queue<OboeAudioBuffer> _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);
}

View File

@ -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,

View File

@ -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;
}
void write_to_session(AudioSession* session, uint64_t data, uint64_t samples)
{
session->read(data, samples);
}
return session;
}
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);
}
}