diff --git a/CMakeLists.txt b/CMakeLists.txt index 3706906f2..8cc319e3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,9 @@ add_subdirectory(externals) add_subdirectory(third-party) include_directories(src) +set(AUDIO_CORE src/audio_core/sdl_audio.cpp + src/audio_core/sdl_audio.h +) set(LIBRARIES src/core/libraries/library_common.h src/core/libraries/error_codes.h src/core/libraries/libscecommondialog.cpp @@ -245,6 +248,7 @@ qt_add_executable(shadps4 ) else() add_executable(shadps4 + ${AUDIO_CORE} ${LIBC_SOURCES} ${PAD_SOURCES} ${FILESYSTEM_SOURCES} diff --git a/src/audio_core/sdl_audio.cpp b/src/audio_core/sdl_audio.cpp new file mode 100644 index 000000000..2e0d37457 --- /dev/null +++ b/src/audio_core/sdl_audio.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "sdl_audio.h" + +int SDLAudio::AudioInit() { + return SDL_InitSubSystem(SDL_INIT_AUDIO); +} + +int SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq, u32 format) { + std::scoped_lock{m_mutex}; + for (int id = 0; id < portsOut.size(); id++) { + auto& port = portsOut[id]; + if (!port.isOpen) { + port.isOpen = true; + port.type = type; + port.samples_num = samples_num; + port.freq = freq; + port.format = format; + } + return id + 1; + } + + return -1; // all ports are used +} diff --git a/src/audio_core/sdl_audio.h b/src/audio_core/sdl_audio.h new file mode 100644 index 000000000..6d06cf6e9 --- /dev/null +++ b/src/audio_core/sdl_audio.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "src/common/types.h" + +class SDLAudio { +public: + SDLAudio() = default; + virtual ~SDLAudio() = default; + + int AudioInit(); + int AudioOutOpen(int type, u32 samples_num, u32 freq, u32 format); + +private: + struct PortOut { + bool isOpen = false; + int type = 0; + u32 samples_num = 0; + u32 freq = 0; + u32 format = -1; + int channels_num = 0; + int volume[8] = {}; + }; + std::mutex m_mutex; + std::array portsOut; // main support up to 8 ports +}; \ No newline at end of file diff --git a/src/core/libraries/libsceaudioout.cpp b/src/core/libraries/libsceaudioout.cpp index ce7a3c17c..b8ea19f02 100644 --- a/src/core/libraries/libsceaudioout.cpp +++ b/src/core/libraries/libsceaudioout.cpp @@ -2,12 +2,57 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Generated By moduleGenerator +#include +#include #include "common/logging/log.h" #include "error_codes.h" #include "libsceaudioout.h" +#include "src/audio_core/sdl_audio.h" namespace Libraries::AudioOut { +static std::string_view GetAudioOutPort(u32 port) { + switch (port) { + case ORBIS_AUDIO_OUT_PORT_TYPE_MAIN: + return "MAIN"; + case ORBIS_AUDIO_OUT_PORT_TYPE_BGM: + return "BGM"; + case ORBIS_AUDIO_OUT_PORT_TYPE_VOICE: + return "VOICE"; + case ORBIS_AUDIO_OUT_PORT_TYPE_PERSONAL: + return "PERSONAL"; + case ORBIS_AUDIO_OUT_PORT_TYPE_PADSPK: + return "PADSPK"; + case ORBIS_AUDIO_OUT_PORT_TYPE_AUX: + return "AUX"; + default: + return "INVALID"; + } +} + +static std::string_view GetAudioOutParam(u32 param) { + switch (param) { + case ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO: + return "S16_MONO"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO: + return "S16_STEREO"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH: + return "S16_8CH"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO: + return "FLOAT_MONO"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO: + return "FLOAT_STEREO"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH: + return "FLOAT_8CH"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD: + return "S16_8CH_STD"; + case ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD: + return "FLOAT_8CH_STD"; + default: + return "INVALID"; + } +} + int PS4_SYSV_ABI sceAudioOutDeviceIdOpen() { LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); return ORBIS_OK; @@ -144,8 +189,10 @@ int PS4_SYSV_ABI sceAudioOutGetSystemState() { } int PS4_SYSV_ABI sceAudioOutInit() { - LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); - return ORBIS_OK; + auto* audio = Common::Singleton::Instance(); + u32 result = audio->AudioInit() == 0 ? ORBIS_OK : ORBIS_AUDIO_OUT_ERROR_NOT_INIT; + LOG_INFO(Lib_AudioOut, "AudioInit returned {}", result); + return result; } int PS4_SYSV_ABI sceAudioOutInitIpmiGetSession() { @@ -178,8 +225,13 @@ int PS4_SYSV_ABI sceAudioOutMbusInit() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAudioOutOpen() { - LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, + OrbisAudioOutPort port_type, s32 index, u32 length, + u32 sample_rate, OrbisAudioOutParam param_type) { + LOG_INFO( + Lib_AudioOut, + "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; } @@ -188,7 +240,7 @@ int PS4_SYSV_ABI sceAudioOutOpenEx() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAudioOutOutput() { +int PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr) { LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); return ORBIS_OK; } diff --git a/src/core/libraries/libsceaudioout.h b/src/core/libraries/libsceaudioout.h index aa0e98303..ebbb2ba88 100644 --- a/src/core/libraries/libsceaudioout.h +++ b/src/core/libraries/libsceaudioout.h @@ -4,9 +4,32 @@ #pragma once #include "library_common.h" +#include "libsceuserservice.h" namespace Libraries::AudioOut { +constexpr int SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value + +enum OrbisAudioOutPort { + ORBIS_AUDIO_OUT_PORT_TYPE_MAIN = 0, + ORBIS_AUDIO_OUT_PORT_TYPE_BGM = 1, + ORBIS_AUDIO_OUT_PORT_TYPE_VOICE = 2, + ORBIS_AUDIO_OUT_PORT_TYPE_PERSONAL = 3, + ORBIS_AUDIO_OUT_PORT_TYPE_PADSPK = 4, + ORBIS_AUDIO_OUT_PORT_TYPE_AUX = 127 +}; + +enum OrbisAudioOutParam { + ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO = 0, + ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO = 1, + ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH = 2, + ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO = 3, + ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO = 4, + ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH = 5, + ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD = 6, + ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD = 7 +}; + int PS4_SYSV_ABI sceAudioOutDeviceIdOpen(); int PS4_SYSV_ABI sceAudioDeviceControlGet(); int PS4_SYSV_ABI sceAudioDeviceControlSet(); @@ -41,9 +64,11 @@ int PS4_SYSV_ABI sceAudioOutMasteringInit(); int PS4_SYSV_ABI sceAudioOutMasteringSetParam(); int PS4_SYSV_ABI sceAudioOutMasteringTerm(); int PS4_SYSV_ABI sceAudioOutMbusInit(); -int PS4_SYSV_ABI sceAudioOutOpen(); +s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, + OrbisAudioOutPort port_type, s32 index, u32 length, + u32 sample_rate, OrbisAudioOutParam param_type); int PS4_SYSV_ABI sceAudioOutOpenEx(); -int PS4_SYSV_ABI sceAudioOutOutput(); +s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, const void* ptr); int PS4_SYSV_ABI sceAudioOutOutputs(); int PS4_SYSV_ABI sceAudioOutPtClose(); int PS4_SYSV_ABI sceAudioOutPtGetLastOutputTime();