From 5c53ca8b61667b7fd4c469186abdc59d35dbdca5 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 10 Jul 2025 20:02:22 +0300 Subject: [PATCH] initial implementation --- CMakeLists.txt | 2 + src/core/libraries/audio/audioin.cpp | 21 ++++-- src/core/libraries/audio/audioin.h | 4 +- src/core/libraries/audio/sdl_in.cpp | 97 ++++++++++++++++++++++++++++ src/core/libraries/audio/sdl_in.h | 39 +++++++++++ 5 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 src/core/libraries/audio/sdl_in.cpp create mode 100644 src/core/libraries/audio/sdl_in.h diff --git a/CMakeLists.txt b/CMakeLists.txt index adff454b8..900be80df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,6 +300,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp set(AUDIO_LIB src/core/libraries/audio/audioin.cpp src/core/libraries/audio/audioin.h + src/core/libraries/audio/sdl_in.h + src/core/libraries/audio/sdl_in.cpp src/core/libraries/voice/voice.cpp src/core/libraries/voice/voice.h src/core/libraries/audio/audioout.cpp diff --git a/src/core/libraries/audio/audioin.cpp b/src/core/libraries/audio/audioin.cpp index 0f3ac4a20..93793f5b7 100644 --- a/src/core/libraries/audio/audioin.cpp +++ b/src/core/libraries/audio/audioin.cpp @@ -5,15 +5,20 @@ #include "core/libraries/audio/audioin.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" +#include "core/libraries/audio/sdl_in.h" namespace Libraries::AudioIn { +static std::unique_ptr audio = std::make_unique(); + int PS4_SYSV_ABI sceAudioInChangeAppModuleState() { LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceAudioInClose() { +int PS4_SYSV_ABI sceAudioInClose(s32 handle) + { + audio->AudioInClose(handle); LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); return ORBIS_OK; } @@ -108,9 +113,8 @@ int PS4_SYSV_ABI sceAudioInInit() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAudioInInput() { - LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest) { + return audio->AudioInInput(handle, dest); } int PS4_SYSV_ABI sceAudioInInputs() { @@ -125,8 +129,13 @@ int PS4_SYSV_ABI sceAudioInIsSharedDevice() { int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type, u32 index, u32 len, u32 freq, u32 param) { - LOG_ERROR(Lib_AudioIn, "(DUMMY) called"); - return 0x80260005; // ports are full return + int result = audio->AudioInOpen(type, len, freq, param); + if (result == -1) { + LOG_ERROR(Lib_AudioOut, "Audio ports are full"); + return 0x80260005; + } + return result; + LOG_ERROR(Lib_AudioIn, "called"); } int PS4_SYSV_ABI sceAudioInOpenEx() { diff --git a/src/core/libraries/audio/audioin.h b/src/core/libraries/audio/audioin.h index 96fbc6f3e..596df95fc 100644 --- a/src/core/libraries/audio/audioin.h +++ b/src/core/libraries/audio/audioin.h @@ -17,7 +17,7 @@ enum class OrbisAudioInParamFormat : u32 { S16Mono = 0, S16Stereo = 2 }; enum class OrbisAudioInType : u32 { VoiceChat = 0, General = 1, VoiceRecognition = 5 }; int PS4_SYSV_ABI sceAudioInChangeAppModuleState(); -int PS4_SYSV_ABI sceAudioInClose(); +int PS4_SYSV_ABI sceAudioInClose(s32 handle); int PS4_SYSV_ABI sceAudioInCountPorts(); int PS4_SYSV_ABI sceAudioInDeviceHqOpen(); int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen(); @@ -36,7 +36,7 @@ int PS4_SYSV_ABI sceAudioInGetSilentState(); int PS4_SYSV_ABI sceAudioInHqOpen(); int PS4_SYSV_ABI sceAudioInHqOpenEx(); int PS4_SYSV_ABI sceAudioInInit(); -int PS4_SYSV_ABI sceAudioInInput(); +int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest); int PS4_SYSV_ABI sceAudioInInputs(); int PS4_SYSV_ABI sceAudioInIsSharedDevice(); int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type, diff --git a/src/core/libraries/audio/sdl_in.cpp b/src/core/libraries/audio/sdl_in.cpp new file mode 100644 index 000000000..fb534f0c8 --- /dev/null +++ b/src/core/libraries/audio/sdl_in.cpp @@ -0,0 +1,97 @@ +#include +#include "sdl_in.h" + +int SDLAudioIn::AudioInit() { + return SDL_InitSubSystem(SDL_INIT_AUDIO); +} + +int SDLAudioIn::AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format) { + using Libraries::AudioIn::OrbisAudioInParam; + std::scoped_lock lock{m_mutex}; + + for (int id = 0; id < portsIn.size(); id++) { + auto& port = portsIn[id]; + if (!port.isOpen) { + port.isOpen = true; + port.type = type; + port.samples_num = samples_num; + port.freq = freq; + port.format = format; + + SDL_AudioFormat sampleFormat; + switch (format) { + case 0: + sampleFormat = SDL_AUDIO_S16; + port.channels_num = 1; + port.sample_size = 2; + break; + case 2: + sampleFormat = SDL_AUDIO_S16; + port.channels_num = 2; + port.sample_size = 2; + break; + default: + port.isOpen = false; + return ORBIS_AUDIO_IN_ERROR_INVALID_PORT; + } + + SDL_AudioSpec fmt; + SDL_zero(fmt); + fmt.format = sampleFormat; + fmt.channels = port.channels_num; + fmt.freq = port.freq; + + port.stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_RECORDING, &fmt, + nullptr, nullptr); + if (!port.stream) { + port.isOpen = false; + return -1; + } + + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream)); + return id + 1; + } + } + + return -1; +} + +int SDLAudioIn::AudioInInput(int handle, void* out_buffer) { + std::scoped_lock lock{m_mutex}; + if (handle < 1 || handle > portsIn.size()) + return ORBIS_AUDIO_IN_ERROR_INVALID_PORT; + + auto& port = portsIn[handle - 1]; + if (!port.isOpen || out_buffer == nullptr) { + return ORBIS_AUDIO_IN_ERROR_INVALID_PORT; + } + + const int bytesToRead = port.samples_num * port.sample_size * port.channels_num; + + int attempts = 0; + while (SDL_GetAudioStreamAvailable(port.stream) < bytesToRead) { + SDL_Delay(1); + if (++attempts > 1000) { + return ORBIS_AUDIO_IN_ERROR_TIMEOUT; + } + } + + if (SDL_GetAudioStreamData(port.stream, out_buffer, bytesToRead) != 0) { + return ORBIS_AUDIO_IN_ERROR_STREAM_FAIL; + } + + return bytesToRead; +} + +void SDLAudioIn::AudioInClose(int handle) { + std::scoped_lock lock{m_mutex}; + if (handle < 1 || handle > portsIn.size()) + return; + + auto& port = portsIn[handle - 1]; + if (!port.isOpen) + return; + + SDL_DestroyAudioStream(port.stream); + port.isOpen = false; +} diff --git a/src/core/libraries/audio/sdl_in.h b/src/core/libraries/audio/sdl_in.h new file mode 100644 index 000000000..fca9c8bee --- /dev/null +++ b/src/core/libraries/audio/sdl_in.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace Libraries::AudioIn { +enum OrbisAudioInParam { + ORBIS_AUDIO_IN_PARAM_FORMAT_S16_MONO = 0, + ORBIS_AUDIO_IN_PARAM_FORMAT_S16_STEREO=2 +}; +} + +#define ORBIS_AUDIO_IN_ERROR_INVALID_PORT -1 +#define ORBIS_AUDIO_IN_ERROR_TIMEOUT -2 +#define ORBIS_AUDIO_IN_ERROR_STREAM_FAIL -3 + +class SDLAudioIn { +public: + int AudioInit(); + int AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format); + int AudioInInput(int handle, void* out_buffer); + void AudioInClose(int handle); + +private: + struct AudioInPort { + bool isOpen = false; + int type = 0; + uint32_t samples_num = 0; + uint32_t freq = 0; + int channels_num = 0; + int sample_size = 0; + uint32_t format; + SDL_AudioStream* stream = nullptr; + }; + + std::array portsIn; + std::mutex m_mutex; +}; \ No newline at end of file