diff --git a/src/audio_core/sdl_audio.cpp b/src/audio_core/sdl_audio.cpp index f544c52f9..5b024850c 100644 --- a/src/audio_core/sdl_audio.cpp +++ b/src/audio_core/sdl_audio.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "sdl_audio.h" - #include "common/assert.h" #include "core/libraries/error_codes.h" @@ -10,7 +9,7 @@ #include #include -#include // std::unique_lock +#include namespace Audio { @@ -18,7 +17,8 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, Libraries::AudioOut::OrbisAudioOutParamFormat format) { using Libraries::AudioOut::OrbisAudioOutParamFormat; std::unique_lock lock{m_mutex}; - for (int id = 0; id < portsOut.size(); id++) { + + for (int id = 0; id < portsOut.size(); ++id) { auto& port = portsOut[id]; if (!port.isOpen) { port.isOpen = true; @@ -26,65 +26,49 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, port.samples_num = samples_num; port.freq = freq; port.format = format; + SDL_AudioFormat sampleFormat; switch (format) { - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO: - sampleFormat = SDL_AUDIO_S16; - port.channels_num = 1; - port.sample_size = 2; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO: - sampleFormat = SDL_AUDIO_F32; - port.channels_num = 1; - port.sample_size = 4; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO: - sampleFormat = SDL_AUDIO_S16; - port.channels_num = 2; - port.sample_size = 2; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO: - sampleFormat = SDL_AUDIO_F32; - port.channels_num = 2; - port.sample_size = 4; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH: - sampleFormat = SDL_AUDIO_S16; - port.channels_num = 8; - port.sample_size = 2; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH: - sampleFormat = SDL_AUDIO_F32; - port.channels_num = 8; - port.sample_size = 4; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD: - sampleFormat = SDL_AUDIO_S16; - port.channels_num = 8; - port.sample_size = 2; - break; - case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD: - sampleFormat = SDL_AUDIO_F32; - port.channels_num = 8; - port.sample_size = 4; - break; - default: - UNREACHABLE_MSG("Unknown format"); + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD: + sampleFormat = SDL_AUDIO_S16; + port.sample_size = 2; + break; + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH: + case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD: + sampleFormat = SDL_AUDIO_F32; + port.sample_size = 4; + break; + default: + UNREACHABLE_MSG("Unknown format"); } - for (int i = 0; i < port.channels_num; i++) { + port.channels_num = (format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO || + format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO) ? 1 : + (format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO || + format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO) ? 2 : 8; + + for (int i = 0; i < port.channels_num; ++i) { port.volume[i] = Libraries::AudioOut::SCE_AUDIO_OUT_VOLUME_0DB; } - SDL_AudioSpec fmt; - SDL_zero(fmt); + SDL_AudioSpec fmt{}; fmt.format = sampleFormat; fmt.channels = port.channels_num; fmt.freq = 48000; - port.stream = - SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, NULL, NULL); - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream)); - return id + 1; + + port.stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, nullptr, nullptr); + if (port.stream != nullptr) { + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream)); + return id + 1; + } + + port.isOpen = false; // Cleanup if stream open fails + return -1; } } @@ -94,16 +78,14 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) { std::shared_lock lock{m_mutex}; auto& port = portsOut[handle - 1]; - if (!port.isOpen) { + + if (!port.isOpen || ptr == nullptr) { return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - if (ptr == nullptr) { - return 0; - } - // TODO mixing channels - int result = SDL_PutAudioStreamData(port.stream, ptr, - port.samples_num * port.sample_size * port.channels_num); - // TODO find a correct value 8192 is estimated + + int result = SDL_PutAudioStreamData(port.stream, ptr, port.samples_num * port.sample_size * port.channels_num); + + // Wait until the buffer has sufficient space while (SDL_GetAudioStreamAvailable(port.stream) > 65536) { SDL_Delay(0); } @@ -115,32 +97,22 @@ bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) { using Libraries::AudioOut::OrbisAudioOutParamFormat; std::shared_lock lock{m_mutex}; auto& port = portsOut[handle - 1]; - if (!port.isOpen) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; - } - for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) { - auto bit = bitflag & 0x1u; - if (bit == 1) { + if (!port.isOpen) { + return false; + } + + for (int i = 0; i < port.channels_num; ++i, bitflag >>= 1u) { + if (bitflag & 0x1u) { int src_index = i; - if (port.format == - OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD || + if (port.format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD || port.format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD) { switch (i) { - case 4: - src_index = 6; - break; - case 5: - src_index = 7; - break; - case 6: - src_index = 4; - break; - case 7: - src_index = 5; - break; - default: - break; + case 4: src_index = 6; break; + case 5: src_index = 7; break; + case 6: src_index = 4; break; + case 7: src_index = 5; break; + default: break; } } port.volume[i] = volume[src_index]; @@ -153,6 +125,11 @@ bool SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) { bool SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) { std::shared_lock lock{m_mutex}; auto& port = portsOut[handle - 1]; + + if (!port.isOpen) { + return false; + } + *type = port.type; *channels_num = port.channels_num;