forked from MeloNX/MeloNX
safely close audio on game exit
This commit is contained in:
parent
2999275ed2
commit
fb562c8077
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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() {
|
||||||
@ -37,101 +40,108 @@ extern "C"
|
|||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_org_ryujinx_android_NativeHelpers_setDeviceId(
|
Java_org_ryujinx_android_NativeHelpers_setDeviceId(
|
||||||
JNIEnv *env,
|
JNIEnv *env,
|
||||||
jobject instance,
|
jobject instance,
|
||||||
jint device_id){
|
jint device_id) {
|
||||||
s_device_id = device_id;
|
s_device_id = device_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
AudioFormat format;
|
AudioFormat format;
|
||||||
|
|
||||||
switch (sample_format) {
|
switch (sample_format) {
|
||||||
case 0:
|
case 0:
|
||||||
format = AudioFormat::Invalid;
|
format = AudioFormat::Invalid;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
format = AudioFormat::I16;
|
format = AudioFormat::I16;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
format = AudioFormat::I24;
|
format = AudioFormat::I24;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
format = AudioFormat::I32;
|
format = AudioFormat::I32;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
format = AudioFormat::Float;
|
format = AudioFormat::Float;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::ostringstream string;
|
std::ostringstream string;
|
||||||
string << "Invalid Format" << sample_format;
|
string << "Invalid Format" << sample_format;
|
||||||
|
|
||||||
throw std::runtime_error(string.str());
|
throw std::runtime_error(string.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto session = new AudioSession();
|
auto session = new AudioSession();
|
||||||
session->initialize();
|
session->initialize();
|
||||||
|
|
||||||
session->format = format;
|
session->format = format;
|
||||||
session->channelCount = channel_count;
|
session->channelCount = channel_count;
|
||||||
|
|
||||||
builder.setDirection(Direction::Output)
|
builder.setDirection(Direction::Output)
|
||||||
->setPerformanceMode(PerformanceMode::LowLatency)
|
->setPerformanceMode(PerformanceMode::LowLatency)
|
||||||
->setSharingMode(SharingMode::Shared)
|
->setSharingMode(SharingMode::Shared)
|
||||||
->setFormat(format)
|
->setFormat(format)
|
||||||
->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;
|
|
||||||
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();
|
|
||||||
|
|
||||||
delete session;
|
delete session;
|
||||||
|
session = nullptr;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
session->stream = stream;
|
||||||
|
|
||||||
bool is_playing(AudioSession* session) {
|
return session;
|
||||||
return session->isStarted;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void write_to_session(AudioSession* session, uint64_t data, uint64_t samples)
|
void start_session(AudioSession *session) {
|
||||||
{
|
if (session == nullptr)
|
||||||
session->read(data, samples);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user