diff --git a/src/audio_core/sdl_audio.cpp b/src/audio_core/sdl_audio.cpp index 0a5ed4a65..4269b8a60 100644 --- a/src/audio_core/sdl_audio.cpp +++ b/src/audio_core/sdl_audio.cpp @@ -1,9 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include "sdl_audio.h" #include +#include "sdl_audio.h" namespace Audio { @@ -23,21 +22,47 @@ 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 OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO: - case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO: + sampleFormat = SDL_AUDIO_S16; port.channels_num = 1; + port.sample_size = 2; + break; + case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO: + sampleFormat = SDL_AUDIO_F32; + port.channels_num = 1; + port.sample_size = 4; break; case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO: - case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO: + sampleFormat = SDL_AUDIO_S16; port.channels_num = 2; + port.sample_size = 2; + break; + case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO: + sampleFormat = SDL_AUDIO_F32; + port.channels_num = 2; + port.sample_size = 4; break; case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH: - case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH: - case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD: - case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD: + sampleFormat = SDL_AUDIO_S16; port.channels_num = 8; + port.sample_size = 2; + break; + case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH: + sampleFormat = SDL_AUDIO_F32; + port.channels_num = 8; + port.sample_size = 4; + break; + case OrbisAudioOutParam::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD: + sampleFormat = SDL_AUDIO_S16; + port.channels_num = 8; + port.sample_size = 2; + break; + case OrbisAudioOutParam::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"); @@ -46,12 +71,30 @@ int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, 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); + fmt.format = sampleFormat; + fmt.channels = port.channels_num; + fmt.freq = 48000; + port.stream = + SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &fmt, NULL, NULL); + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream)); return id + 1; } - } return -1; // all ports are used } +s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) { + std::scoped_lock lock{m_mutex}; + auto& port = portsOut[handle - 1]; + if (!port.isOpen || ptr == nullptr) + return 0; + + return SDL_PutAudioStreamData(port.stream, ptr, + port.samples_num * port.sample_size * port.channels_num); +} + } // namespace Audio diff --git a/src/audio_core/sdl_audio.h b/src/audio_core/sdl_audio.h index 2cc5e7d06..f1eff066d 100644 --- a/src/audio_core/sdl_audio.h +++ b/src/audio_core/sdl_audio.h @@ -4,9 +4,10 @@ #pragma once #include +#include +#include #include "src/common/types.h" -#include namespace Audio { @@ -16,17 +17,21 @@ public: virtual ~SDLAudio() = default; int AudioInit(); - int AudioOutOpen(int type, u32 samples_num, u32 freq, Libraries::AudioOut::OrbisAudioOutParam format); + int AudioOutOpen(int type, u32 samples_num, u32 freq, + Libraries::AudioOut::OrbisAudioOutParam format); + s32 AudioOutOutput(s32 handle, const void* ptr); private: struct PortOut { bool isOpen = false; int type = 0; u32 samples_num = 0; + u8 sample_size = 0; u32 freq = 0; u32 format = -1; int channels_num = 0; int volume[8] = {}; + SDL_AudioStream* stream = nullptr; }; std::mutex m_mutex; std::array portsOut; // main support up to 8 ports diff --git a/src/core/libraries/libsceaudioout.cpp b/src/core/libraries/libsceaudioout.cpp index 429c28daf..4a48ee8f8 100644 --- a/src/core/libraries/libsceaudioout.cpp +++ b/src/core/libraries/libsceaudioout.cpp @@ -235,7 +235,12 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, "AudioOutOpen id = {} port_type = {} index= {} lenght= {} sample_rate= {} param_type= {}", user_id, GetAudioOutPort(port_type), index, length, sample_rate, GetAudioOutParam(param_type)); - return ORBIS_OK; + int result = audio->AudioOutOpen(port_type, length, sample_rate, param_type); + if (result == -1) { + LOG_ERROR(Lib_AudioOut, "Audio ports are full"); + return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; + } + return result; } int PS4_SYSV_ABI sceAudioOutOpenEx() { @@ -243,9 +248,8 @@ int PS4_SYSV_ABI sceAudioOutOpenEx() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr) { - LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr) { + return audio->AudioOutOutput(handle, ptr); } int PS4_SYSV_ABI sceAudioOutOutputs() {