initial implementation

This commit is contained in:
georgemoralis 2025-07-10 20:02:22 +03:00
parent 9bece01cc7
commit 5c53ca8b61
5 changed files with 155 additions and 8 deletions

View File

@ -300,6 +300,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
src/core/libraries/audio/audioin.h 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.cpp
src/core/libraries/voice/voice.h src/core/libraries/voice/voice.h
src/core/libraries/audio/audioout.cpp src/core/libraries/audio/audioout.cpp

View File

@ -5,15 +5,20 @@
#include "core/libraries/audio/audioin.h" #include "core/libraries/audio/audioin.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/audio/sdl_in.h"
namespace Libraries::AudioIn { namespace Libraries::AudioIn {
static std::unique_ptr<SDLAudioIn> audio = std::make_unique<SDLAudioIn>();
int PS4_SYSV_ABI sceAudioInChangeAppModuleState() { int PS4_SYSV_ABI sceAudioInChangeAppModuleState() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInClose() { int PS4_SYSV_ABI sceAudioInClose(s32 handle)
{
audio->AudioInClose(handle);
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }
@ -108,9 +113,8 @@ int PS4_SYSV_ABI sceAudioInInit() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInInput() { int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest) {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); return audio->AudioInInput(handle, dest);
return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInInputs() { 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, int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param) { u32 index, u32 len, u32 freq, u32 param) {
LOG_ERROR(Lib_AudioIn, "(DUMMY) called"); int result = audio->AudioInOpen(type, len, freq, param);
return 0x80260005; // ports are full return 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() { int PS4_SYSV_ABI sceAudioInOpenEx() {

View File

@ -17,7 +17,7 @@ enum class OrbisAudioInParamFormat : u32 { S16Mono = 0, S16Stereo = 2 };
enum class OrbisAudioInType : u32 { VoiceChat = 0, General = 1, VoiceRecognition = 5 }; enum class OrbisAudioInType : u32 { VoiceChat = 0, General = 1, VoiceRecognition = 5 };
int PS4_SYSV_ABI sceAudioInChangeAppModuleState(); 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 sceAudioInCountPorts();
int PS4_SYSV_ABI sceAudioInDeviceHqOpen(); int PS4_SYSV_ABI sceAudioInDeviceHqOpen();
int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen(); int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen();
@ -36,7 +36,7 @@ int PS4_SYSV_ABI sceAudioInGetSilentState();
int PS4_SYSV_ABI sceAudioInHqOpen(); int PS4_SYSV_ABI sceAudioInHqOpen();
int PS4_SYSV_ABI sceAudioInHqOpenEx(); int PS4_SYSV_ABI sceAudioInHqOpenEx();
int PS4_SYSV_ABI sceAudioInInit(); 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 sceAudioInInputs();
int PS4_SYSV_ABI sceAudioInIsSharedDevice(); int PS4_SYSV_ABI sceAudioInIsSharedDevice();
int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type, int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,

View File

@ -0,0 +1,97 @@
#include <cstring>
#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;
}

View File

@ -0,0 +1,39 @@
#pragma once
#include <array>
#include <mutex>
#include <SDL3/SDL.h>
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<AudioInPort, 8> portsIn;
std::mutex m_mutex;
};