mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-19 19:14:48 +00:00
libraries: Initial Audio3d implementation. (#2776)
* feat: Audio3d * feat: Audio3d * audio3d: disable output * audio3d: Implement central Audio3d output. * audio3d: Ignore AudioOut already initialized error. * audio3d: Convert and retain sample buffers when queued. * audio3d: Treat object audio as single channel. * audio3d: Clean up. --------- Co-authored-by: auser1337 <154299690+auser1337@users.noreply.github.com>
This commit is contained in:
parent
fb146f2a20
commit
657073b9e2
8 changed files with 637 additions and 400 deletions
|
@ -450,8 +450,6 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||
src/core/libraries/audio3d/audio3d.cpp
|
||||
src/core/libraries/audio3d/audio3d.h
|
||||
src/core/libraries/audio3d/audio3d_error.h
|
||||
src/core/libraries/audio3d/audio3d_impl.cpp
|
||||
src/core/libraries/audio3d/audio3d_impl.h
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.cpp
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.h
|
||||
src/core/libraries/remote_play/remoteplay.cpp
|
||||
|
|
|
@ -191,6 +191,7 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta
|
|||
case OrbisAudioOutPort::Main:
|
||||
case OrbisAudioOutPort::Bgm:
|
||||
case OrbisAudioOutPort::Voice:
|
||||
case OrbisAudioOutPort::Audio3d:
|
||||
state->output = 1;
|
||||
state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels;
|
||||
break;
|
||||
|
@ -316,7 +317,7 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
|
|||
return ORBIS_AUDIO_OUT_ERROR_NOT_INIT;
|
||||
}
|
||||
if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::Padspk) &&
|
||||
(port_type != OrbisAudioOutPort::Aux)) {
|
||||
(port_type != OrbisAudioOutPort::Audio3d && port_type != OrbisAudioOutPort::Aux)) {
|
||||
LOG_ERROR(Lib_AudioOut, "Invalid port type");
|
||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT_TYPE;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,15 @@ class PortBackend;
|
|||
constexpr s32 SCE_AUDIO_OUT_NUM_PORTS = 22;
|
||||
constexpr s32 SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value
|
||||
|
||||
enum class OrbisAudioOutPort { Main = 0, Bgm = 1, Voice = 2, Personal = 3, Padspk = 4, Aux = 127 };
|
||||
enum class OrbisAudioOutPort {
|
||||
Main = 0,
|
||||
Bgm = 1,
|
||||
Voice = 2,
|
||||
Personal = 3,
|
||||
Padspk = 4,
|
||||
Audio3d = 126,
|
||||
Aux = 127,
|
||||
};
|
||||
|
||||
enum class OrbisAudioOutParamFormat : u32 {
|
||||
S16Mono = 0,
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <SDL3/SDL_audio.h>
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
#include "core/libraries/audio/audioout_error.h"
|
||||
#include "core/libraries/audio3d/audio3d.h"
|
||||
#include "core/libraries/audio3d/audio3d_error.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
@ -10,331 +15,577 @@
|
|||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dInitialize(s64 iReserved) {
|
||||
LOG_INFO(Lib_Audio3d, "iReserved = {}", iReserved);
|
||||
return ORBIS_OK;
|
||||
static constexpr u32 AUDIO3D_SAMPLE_RATE = 48000;
|
||||
|
||||
static constexpr AudioOut::OrbisAudioOutParamFormat AUDIO3D_OUTPUT_FORMAT =
|
||||
AudioOut::OrbisAudioOutParamFormat::S16Stereo;
|
||||
static constexpr u32 AUDIO3D_OUTPUT_NUM_CHANNELS = 2;
|
||||
static constexpr u32 AUDIO3D_OUTPUT_BUFFER_FRAMES = 0x100;
|
||||
|
||||
static std::unique_ptr<Audio3dState> state;
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(const s32 handle) {
|
||||
LOG_INFO(Lib_Audio3d, "called, handle = {}", handle);
|
||||
return AudioOut::sceAudioOutClose(handle);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dTerminate() {
|
||||
// TODO: When not initialized or some ports still open, return ORBIS_AUDIO3D_ERROR_NOT_READY
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* parameters) {
|
||||
if (parameters == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "Invalid OpenParameters ptr");
|
||||
return;
|
||||
}
|
||||
|
||||
parameters->size_this = sizeof(OrbisAudio3dOpenParameters);
|
||||
parameters->granularity = 256;
|
||||
parameters->rate = OrbisAudio3dRate::Rate48000;
|
||||
parameters->max_objects = 512;
|
||||
parameters->queue_depth = 2;
|
||||
parameters->buffer_mode = OrbisAudio3dBufferMode::AdvanceAndPush;
|
||||
parameters->num_beds = 2;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortOpen(OrbisUserServiceUserId iUserId,
|
||||
const OrbisAudio3dOpenParameters* pParameters,
|
||||
OrbisAudio3dPortId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "iUserId = {}", iUserId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortClose(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortSetAttribute(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dAttributeId uiAttributeId,
|
||||
const void* pAttribute, size_t szAttribute) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiAttributeId = {}, szAttribute = {}", uiPortId,
|
||||
uiAttributeId, szAttribute);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortFlush(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortAdvance(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortPush(OrbisAudio3dPortId uiPortId, OrbisAudio3dBlocking eBlocking) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dAttributeId* pCapabilities,
|
||||
u32* pNumCapabilities) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId uiPortId, u32* pQueueLevel,
|
||||
u32* pQueueAvailable) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectReserve(OrbisAudio3dPortId uiPortId, OrbisAudio3dObjectId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectUnreserve(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dObjectId uiObjectId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}", uiPortId, uiObjectId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectSetAttributes(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dObjectId uiObjectId,
|
||||
size_t szNumAttributes,
|
||||
const OrbisAudio3dAttribute* pAttributeArray) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}, szNumAttributes = {}", uiPortId,
|
||||
uiObjectId, szNumAttributes);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dBedWrite(OrbisAudio3dPortId uiPortId, u32 uiNumChannels,
|
||||
OrbisAudio3dFormat eFormat, const void* pBuffer,
|
||||
u32 uiNumSamples) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}", uiPortId,
|
||||
uiNumChannels, uiNumSamples);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dBedWrite2(OrbisAudio3dPortId uiPortId, u32 uiNumChannels,
|
||||
OrbisAudio3dFormat eFormat, const void* pBuffer,
|
||||
u32 uiNumSamples, OrbisAudio3dOutputRoute eOutputRoute,
|
||||
bool bRestricted) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}, bRestricted = {}",
|
||||
uiPortId, uiNumChannels, uiNumSamples, bRestricted);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
size_t PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize(u32 uiNumSpeakers, bool bIs3d) {
|
||||
LOG_INFO(Lib_Audio3d, "uiNumSpeakers = {}, bIs3d = {}", uiNumSpeakers, bIs3d);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI
|
||||
sceAudio3dCreateSpeakerArray(OrbisAudio3dSpeakerArrayHandle* pHandle,
|
||||
const OrbisAudio3dSpeakerArrayParameters* pParameters) {
|
||||
if (pHandle == nullptr || pParameters == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArray parameters");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray(OrbisAudio3dSpeakerArrayHandle handle) {
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients(OrbisAudio3dSpeakerArrayHandle handle,
|
||||
OrbisAudio3dPosition pos, float fSpread,
|
||||
float* pCoefficients,
|
||||
u32 uiNumCoefficients) {
|
||||
LOG_INFO(Lib_Audio3d, "fSpread = {}, uiNumCoefficients = {}", fSpread, uiNumCoefficients);
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2(OrbisAudio3dSpeakerArrayHandle handle,
|
||||
OrbisAudio3dPosition pos, float fSpread,
|
||||
float* pCoefficients,
|
||||
u32 uiNumCoefficients, bool bHeightAware,
|
||||
float fDownmixSpreadRadius) {
|
||||
s32 PS4_SYSV_ABI
|
||||
sceAudio3dAudioOutOpen(const OrbisAudio3dPortId port_id, const OrbisUserServiceUserId user_id,
|
||||
s32 type, const s32 index, const u32 len, const u32 freq,
|
||||
const AudioOut::OrbisAudioOutParamExtendedInformation param) {
|
||||
LOG_INFO(Lib_Audio3d,
|
||||
"fSpread = {}, uiNumCoefficients = {}, bHeightAware = {}, fDownmixSpreadRadius = {}",
|
||||
fSpread, uiNumCoefficients, bHeightAware, fDownmixSpreadRadius);
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
"called, port_id = {}, user_id = {}, type = {}, index = {}, len = {}, freq = {}",
|
||||
port_id, user_id, type, index, len, freq);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (len != state->ports[port_id].parameters.granularity) {
|
||||
LOG_ERROR(Lib_Audio3d, "len != state->ports[port_id].parameters.granularity");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return sceAudioOutOpen(user_id, static_cast<AudioOut::OrbisAudioOutPort>(type), index, len,
|
||||
freq, param);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(const s32 handle, void* ptr) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, handle = {}, ptr = {}", handle, ptr);
|
||||
|
||||
if (!ptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "!ptr");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (handle < 0 || (handle & 0xFFFF) > 25) {
|
||||
LOG_ERROR(Lib_Audio3d, "handle < 0 || (handle & 0xFFFF) > 25");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
return AudioOut::sceAudioOutOutput(handle, ptr);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(AudioOut::OrbisAudioOutOutputParam* param,
|
||||
const u32 num) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, param = {}, num = {}", static_cast<void*>(param), num);
|
||||
|
||||
if (!param || !num) {
|
||||
LOG_ERROR(Lib_Audio3d, "!param || !num");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return AudioOut::sceAudioOutOutputs(param, num);
|
||||
}
|
||||
|
||||
static s32 PortQueueAudio(Port& port, const OrbisAudio3dPcm& pcm, const u32 num_channels) {
|
||||
// Audio3d output is configured for stereo signed 16-bit PCM. Convert the data to match.
|
||||
const SDL_AudioSpec src_spec = {
|
||||
.format = pcm.format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16 ? SDL_AUDIO_S16LE
|
||||
: SDL_AUDIO_F32LE,
|
||||
.channels = static_cast<int>(num_channels),
|
||||
.freq = AUDIO3D_SAMPLE_RATE,
|
||||
};
|
||||
constexpr SDL_AudioSpec dst_spec = {
|
||||
.format = SDL_AUDIO_S16LE,
|
||||
.channels = AUDIO3D_OUTPUT_NUM_CHANNELS,
|
||||
.freq = AUDIO3D_SAMPLE_RATE,
|
||||
};
|
||||
const auto src_size = pcm.num_samples *
|
||||
(pcm.format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16 ? 2 : 4) *
|
||||
num_channels;
|
||||
|
||||
u8* dst_data;
|
||||
int dst_len;
|
||||
if (!SDL_ConvertAudioSamples(&src_spec, static_cast<u8*>(pcm.sample_buffer),
|
||||
static_cast<int>(src_size), &dst_spec, &dst_data, &dst_len)) {
|
||||
LOG_ERROR(Lib_Audio3d, "SDL_ConvertAudioSamples failed: {}", SDL_GetError());
|
||||
return ORBIS_AUDIO3D_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
port.queue.emplace_back(AudioData{
|
||||
.sample_buffer = dst_data,
|
||||
.num_samples = pcm.num_samples,
|
||||
});
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite(const OrbisAudio3dPortId port_id, const u32 num_channels,
|
||||
const OrbisAudio3dFormat format, void* buffer,
|
||||
const u32 num_samples) {
|
||||
return sceAudio3dBedWrite2(port_id, num_channels, format, buffer, num_samples,
|
||||
OrbisAudio3dOutputRoute::ORBIS_AUDIO3D_OUTPUT_BOTH, false);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite2(const OrbisAudio3dPortId port_id, const u32 num_channels,
|
||||
const OrbisAudio3dFormat format, void* buffer,
|
||||
const u32 num_samples,
|
||||
const OrbisAudio3dOutputRoute output_route,
|
||||
const bool restricted) {
|
||||
LOG_DEBUG(
|
||||
Lib_Audio3d,
|
||||
"called, port_id = {}, num_channels = {}, format = {}, num_samples = {}, output_route "
|
||||
"= {}, restricted = {}",
|
||||
port_id, num_channels, magic_enum::enum_name(format), num_samples,
|
||||
magic_enum::enum_name(output_route), restricted);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (output_route > OrbisAudio3dOutputRoute::ORBIS_AUDIO3D_OUTPUT_BOTH) {
|
||||
LOG_ERROR(Lib_Audio3d, "output_route > ORBIS_AUDIO3D_OUTPUT_BOTH");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (format > OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_FLOAT) {
|
||||
LOG_ERROR(Lib_Audio3d, "format > ORBIS_AUDIO3D_FORMAT_FLOAT");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (num_channels != 2 && num_channels != 8) {
|
||||
LOG_ERROR(Lib_Audio3d, "num_channels != 2 && num_channels != 8");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!buffer || !num_samples) {
|
||||
LOG_ERROR(Lib_Audio3d, "!buffer || !num_samples");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_FLOAT) {
|
||||
if ((reinterpret_cast<uintptr_t>(buffer) & 3) != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "buffer & 3 != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
} else if (format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16) {
|
||||
if ((reinterpret_cast<uintptr_t>(buffer) & 1) != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "buffer & 1 != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
return PortQueueAudio(state->ports[port_id],
|
||||
OrbisAudio3dPcm{
|
||||
.format = format,
|
||||
.sample_buffer = buffer,
|
||||
.num_samples = num_samples,
|
||||
},
|
||||
num_channels);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dCreateSpeakerArray() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* params) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called");
|
||||
if (params) {
|
||||
*params = OrbisAudio3dOpenParameters{
|
||||
.size_this = 0x20,
|
||||
.granularity = 0x100,
|
||||
.rate = OrbisAudio3dRate::ORBIS_AUDIO3D_RATE_48000,
|
||||
.max_objects = 512,
|
||||
.queue_depth = 2,
|
||||
.buffer_mode = OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH,
|
||||
};
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOpen(OrbisAudio3dPortId uiPortId, OrbisUserServiceUserId userId,
|
||||
s32 type, s32 index, u32 len, u32 freq, u32 param) {
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dInitialize(const s64 reserved) {
|
||||
LOG_INFO(Lib_Audio3d, "called, reserved = {}", reserved);
|
||||
|
||||
if (reserved != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "reserved != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (state) {
|
||||
LOG_ERROR(Lib_Audio3d, "already initialized");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
state = std::make_unique<Audio3dState>();
|
||||
|
||||
if (const auto init_ret = AudioOut::sceAudioOutInit();
|
||||
init_ret < 0 && init_ret != ORBIS_AUDIO_OUT_ERROR_ALREADY_INIT) {
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
AudioOut::OrbisAudioOutParamExtendedInformation ext_info{};
|
||||
ext_info.data_format.Assign(AUDIO3D_OUTPUT_FORMAT);
|
||||
state->audio_out_handle =
|
||||
AudioOut::sceAudioOutOpen(0xFF, AudioOut::OrbisAudioOutPort::Audio3d, 0,
|
||||
AUDIO3D_OUTPUT_BUFFER_FRAMES, AUDIO3D_SAMPLE_RATE, ext_info);
|
||||
if (state->audio_out_handle < 0) {
|
||||
return state->audio_out_handle;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectReserve(const OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId* object_id) {
|
||||
LOG_INFO(Lib_Audio3d, "called, port_id = {}, object_id = {}", port_id,
|
||||
static_cast<void*>(object_id));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (!object_id) {
|
||||
LOG_ERROR(Lib_Audio3d, "!object_id");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
static int last_id = 0;
|
||||
*object_id = ++last_id;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectSetAttributes(const OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId object_id,
|
||||
const u64 num_attributes,
|
||||
const OrbisAudio3dAttribute* attribute_array) {
|
||||
LOG_DEBUG(Lib_Audio3d,
|
||||
"called, port_id = {}, object_id = {}, num_attributes = {}, attribute_array = {}",
|
||||
port_id, object_id, num_attributes, fmt::ptr(attribute_array));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
auto& port = state->ports[port_id];
|
||||
|
||||
for (u64 i = 0; i < num_attributes; i++) {
|
||||
const auto& attribute = attribute_array[i];
|
||||
|
||||
switch (attribute.attribute_id) {
|
||||
case OrbisAudio3dAttributeId::ORBIS_AUDIO3D_ATTRIBUTE_PCM: {
|
||||
const auto pcm = static_cast<OrbisAudio3dPcm*>(attribute.value);
|
||||
// Object audio has 1 channel.
|
||||
if (const auto ret = PortQueueAudio(port, *pcm, 1); ret != ORBIS_OK) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(Lib_Audio3d, "Unsupported attribute ID: {:#x}",
|
||||
static_cast<u32>(attribute.attribute_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectUnreserve() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortAdvance(const OrbisAudio3dPortId port_id) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}", port_id);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (state->ports[port_id].parameters.buffer_mode ==
|
||||
OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_NO_ADVANCE) {
|
||||
LOG_ERROR(Lib_Audio3d, "port doesn't have advance capability");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
auto& port = state->ports[port_id];
|
||||
if (port.current_buffer.has_value()) {
|
||||
// Free existing buffer before replacing.
|
||||
SDL_free(port.current_buffer->sample_buffer);
|
||||
}
|
||||
|
||||
if (!port.queue.empty()) {
|
||||
port.current_buffer = port.queue.front();
|
||||
port.queue.pop_front();
|
||||
} else {
|
||||
// Nothing to advance to.
|
||||
LOG_DEBUG(Lib_Audio3d, "Port advance with no buffer queued");
|
||||
port.current_buffer = std::nullopt;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortClose() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortCreate() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortDestroy() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFlush() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFreeState() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetList() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetParameters() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(const OrbisAudio3dPortId port_id, u32* queue_level,
|
||||
u32* queue_available) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}, queue_level = {}, queue_available = {}", port_id,
|
||||
static_cast<void*>(queue_level), static_cast<void*>(queue_available));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (!queue_level && !queue_available) {
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto port = state->ports[port_id];
|
||||
const size_t size = port.queue.size();
|
||||
|
||||
if (queue_level) {
|
||||
*queue_level = size;
|
||||
}
|
||||
|
||||
if (queue_available) {
|
||||
*queue_available = port.parameters.queue_depth - size;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetState() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetStatus() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortOpen(const OrbisUserServiceUserId user_id,
|
||||
const OrbisAudio3dOpenParameters* parameters,
|
||||
OrbisAudio3dPortId* port_id) {
|
||||
LOG_INFO(Lib_Audio3d, "called, user_id = {}, parameters = {}, id = {}", user_id,
|
||||
static_cast<const void*>(parameters), static_cast<void*>(port_id));
|
||||
|
||||
if (!state) {
|
||||
LOG_ERROR(Lib_Audio3d, "!initialized");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
if (!parameters || !port_id) {
|
||||
LOG_ERROR(Lib_Audio3d, "!parameters || !id");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const int id = static_cast<int>(state->ports.size()) + 1;
|
||||
|
||||
if (id > 3) {
|
||||
LOG_ERROR(Lib_Audio3d, "id > 3");
|
||||
return ORBIS_AUDIO3D_ERROR_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
*port_id = id;
|
||||
std::memcpy(&state->ports[id].parameters, parameters, sizeof(OrbisAudio3dOpenParameters));
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortPush(const OrbisAudio3dPortId port_id,
|
||||
const OrbisAudio3dBlocking blocking) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}, blocking = {}", port_id,
|
||||
magic_enum::enum_name(blocking));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
const auto& port = state->ports[port_id];
|
||||
if (port.parameters.buffer_mode !=
|
||||
OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH) {
|
||||
LOG_ERROR(Lib_Audio3d, "port doesn't have push capability");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!port.current_buffer.has_value()) {
|
||||
// Nothing to push.
|
||||
LOG_DEBUG(Lib_Audio3d, "Port push with no buffer ready");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// TODO: Implement asynchronous blocking mode.
|
||||
const auto& [sample_buffer, num_samples] = port.current_buffer.value();
|
||||
return AudioOut::sceAudioOutOutput(state->audio_out_handle, sample_buffer);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortQueryDebug() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortSetAttribute(const OrbisAudio3dPortId port_id,
|
||||
const OrbisAudio3dAttributeId attribute_id,
|
||||
void* attribute, const u64 attribute_size) {
|
||||
LOG_INFO(Lib_Audio3d,
|
||||
"uiPortId = {}, userId = {}, type = {}, index = {}, len = {}, freq = {}, param = {}",
|
||||
uiPortId, userId, type, index, len, freq, param);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
"called, port_id = {}, attribute_id = {}, attribute = {}, attribute_size = {}",
|
||||
port_id, static_cast<u32>(attribute_id), attribute, attribute_size);
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(s32 handle) {
|
||||
LOG_INFO(Lib_Audio3d, "handle = {}", handle);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(s32 handle, const void* ptr) {
|
||||
LOG_TRACE(Lib_Audio3d, "handle = {}", handle);
|
||||
if (ptr == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid Output ptr");
|
||||
if (!attribute) {
|
||||
LOG_ERROR(Lib_Audio3d, "!attribute");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(::Libraries::AudioOut::OrbisAudioOutOutputParam* param,
|
||||
s32 num) {
|
||||
LOG_INFO(Lib_Audio3d, "num = {}", num);
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid OutputParam ptr");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortCreate(u32 uiGranularity, OrbisAudio3dRate eRate, s64 iReserved,
|
||||
OrbisAudio3dPortId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiGranularity = {}, iReserved = {}", uiGranularity, iReserved);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortDestroy(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Audio3dPrivate
|
||||
|
||||
const char* PS4_SYSV_ABI sceAudio3dStrError(int iErrorCode) {
|
||||
LOG_ERROR(Lib_Audio3d, "(PRIVATE) called, iErrorCode = {}", iErrorCode);
|
||||
return "NOT_IMPLEMENTED";
|
||||
}
|
||||
|
||||
// Audio3dDebug
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortQueryDebug() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortQueryDebug called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetList() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetList called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetParameters() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetParameters called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetState() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetState called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortFreeState() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortFreeState called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Unknown
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetBufferLevel() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportRegisterHandler() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetStatus() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dReportRegisterHandler() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dStrError() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dSetGpuRenderer() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose);
|
||||
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen);
|
||||
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutput);
|
||||
LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutputs);
|
||||
LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite);
|
||||
LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite2);
|
||||
LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dCreateSpeakerArray);
|
||||
LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dDeleteSpeakerArray);
|
||||
LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetDefaultOpenParameters);
|
||||
LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMemorySize);
|
||||
LIB_FUNCTION("-R1DukFq7Dk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMixCoefficients);
|
||||
LIB_FUNCTION("-Re+pCWvwjQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMixCoefficients2);
|
||||
LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortQueryDebug);
|
||||
LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectUnreserve);
|
||||
LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dInitialize);
|
||||
LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dObjectReserve);
|
||||
LIB_FUNCTION("4uyHN9q4ZeU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectSetAttributes);
|
||||
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutput);
|
||||
LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dDeleteSpeakerArray);
|
||||
LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectUnreserve);
|
||||
LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortAdvance);
|
||||
LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortClose);
|
||||
LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortCreate);
|
||||
LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortDestroy);
|
||||
LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFlush);
|
||||
LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFreeState);
|
||||
LIB_FUNCTION("9ZA23Ia46Po", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetAttributesSupported);
|
||||
LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite);
|
||||
LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dStrError);
|
||||
LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetState);
|
||||
LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutputs);
|
||||
LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetDefaultOpenParameters);
|
||||
LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortDestroy);
|
||||
LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortClose);
|
||||
LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportRegisterHandler);
|
||||
LIB_FUNCTION("QqgTQQdzEMY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetBufferLevel);
|
||||
LIB_FUNCTION("SEggctIeTcI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetList);
|
||||
LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortCreate);
|
||||
LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dInitialize);
|
||||
LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortPush);
|
||||
LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dTerminate);
|
||||
LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortOpen);
|
||||
LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetQueueLevel);
|
||||
LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortSetAttribute);
|
||||
LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFlush);
|
||||
LIB_FUNCTION("flPcUaXVXcw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetParameters);
|
||||
LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetQueueLevel);
|
||||
LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetState);
|
||||
LIB_FUNCTION("iRX6GJs9tvE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetStatus);
|
||||
LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dObjectReserve);
|
||||
LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMemorySize);
|
||||
LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dCreateSpeakerArray);
|
||||
LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortAdvance);
|
||||
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose);
|
||||
LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortOpen);
|
||||
LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortPush);
|
||||
LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortQueryDebug);
|
||||
LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortSetAttribute);
|
||||
LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportRegisterHandler);
|
||||
LIB_FUNCTION("psv2gbihC1A", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportUnregisterHandler);
|
||||
LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFreeState);
|
||||
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen);
|
||||
LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite2);
|
||||
LIB_FUNCTION("yEYXcbAGK14", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dSetGpuRenderer);
|
||||
LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dStrError);
|
||||
LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dTerminate);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Audio3d
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
|
||||
#include <stddef.h>
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
|
@ -13,123 +15,131 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
class Audio3d;
|
||||
|
||||
using OrbisUserServiceUserId = s32;
|
||||
using OrbisAudio3dPortId = u32;
|
||||
using OrbisAudio3dObjectId = u32;
|
||||
using OrbisAudio3dAttributeId = u32;
|
||||
|
||||
enum class OrbisAudio3dFormat {
|
||||
S16 = 0,
|
||||
Float = 1,
|
||||
enum class OrbisAudio3dRate : u32 {
|
||||
ORBIS_AUDIO3D_RATE_48000 = 0,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dRate {
|
||||
Rate48000 = 0,
|
||||
enum class OrbisAudio3dBufferMode : u32 {
|
||||
ORBIS_AUDIO3D_BUFFER_NO_ADVANCE = 0,
|
||||
ORBIS_AUDIO3D_BUFFER_ADVANCE_NO_PUSH = 1,
|
||||
ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dBufferMode { NoAdvance = 0, AdvanceNoPush = 1, AdvanceAndPush = 2 };
|
||||
|
||||
enum class OrbisAudio3dBlocking {
|
||||
Async = 0,
|
||||
Sync = 1,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dPassthrough {
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dOutputRoute {
|
||||
Both = 0,
|
||||
HmuOnly = 1,
|
||||
TvOnly = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dAmbisonics : u32 {
|
||||
None = ~0U,
|
||||
W = 0,
|
||||
X = 1,
|
||||
Y = 2,
|
||||
Z = 3,
|
||||
R = 4,
|
||||
S = 5,
|
||||
T = 6,
|
||||
U = 7,
|
||||
V = 8,
|
||||
K = 9,
|
||||
L = 10,
|
||||
M = 11,
|
||||
N = 12,
|
||||
O = 13,
|
||||
P = 14,
|
||||
Q = 15
|
||||
};
|
||||
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePcm = 0x00000001;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePriority = 0x00000002;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePosition = 0x00000003;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeSpread = 0x00000004;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeGain = 0x00000005;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePassthrough = 0x00000006;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeResetState = 0x00000007;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeApplicationSpecific = 0x00000008;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeAmbisonics = 0x00000009;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeRestricted = 0x0000000A;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeOutputRoute = 0x0000000B;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeLateReverbLevel = 0x00010001;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadRadius = 0x00010002;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadHeightAware = 0x00010003;
|
||||
|
||||
struct OrbisAudio3dSpeakerArray;
|
||||
using OrbisAudio3dSpeakerArrayHandle = OrbisAudio3dSpeakerArray*; // head
|
||||
|
||||
struct OrbisAudio3dOpenParameters {
|
||||
size_t size_this;
|
||||
u64 size_this;
|
||||
u32 granularity;
|
||||
OrbisAudio3dRate rate;
|
||||
u32 max_objects;
|
||||
u32 queue_depth;
|
||||
OrbisAudio3dBufferMode buffer_mode;
|
||||
char padding[32];
|
||||
int : 32;
|
||||
u32 num_beds;
|
||||
};
|
||||
|
||||
struct OrbisAudio3dAttribute {
|
||||
OrbisAudio3dAttributeId attribute_id;
|
||||
char padding[32];
|
||||
const void* p_value;
|
||||
size_t value;
|
||||
enum class OrbisAudio3dFormat : u32 {
|
||||
ORBIS_AUDIO3D_FORMAT_S16 = 0,
|
||||
ORBIS_AUDIO3D_FORMAT_FLOAT = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dPosition {
|
||||
float fX;
|
||||
float fY;
|
||||
float fZ;
|
||||
enum class OrbisAudio3dOutputRoute : u32 {
|
||||
ORBIS_AUDIO3D_OUTPUT_BOTH = 0,
|
||||
ORBIS_AUDIO3D_OUTPUT_HMU_ONLY = 1,
|
||||
ORBIS_AUDIO3D_OUTPUT_TV_ONLY = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dBlocking : u32 {
|
||||
ORBIS_AUDIO3D_BLOCKING_ASYNC = 0,
|
||||
ORBIS_AUDIO3D_BLOCKING_SYNC = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dPcm {
|
||||
OrbisAudio3dFormat format;
|
||||
const void* sample_buffer;
|
||||
void* sample_buffer;
|
||||
u32 num_samples;
|
||||
};
|
||||
|
||||
struct OrbisAudio3dSpeakerArrayParameters {
|
||||
OrbisAudio3dPosition* speaker_position;
|
||||
u32 num_speakers;
|
||||
bool is_3d;
|
||||
void* buffer;
|
||||
size_t size;
|
||||
enum class OrbisAudio3dAttributeId : u32 {
|
||||
ORBIS_AUDIO3D_ATTRIBUTE_PCM = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dApplicationSpecific {
|
||||
size_t size_this;
|
||||
u8 application_specific[32];
|
||||
using OrbisAudio3dPortId = u32;
|
||||
using OrbisAudio3dObjectId = u32;
|
||||
|
||||
struct OrbisAudio3dAttribute {
|
||||
OrbisAudio3dAttributeId attribute_id;
|
||||
int : 32;
|
||||
void* value;
|
||||
u64 value_size;
|
||||
};
|
||||
|
||||
void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* sParameters);
|
||||
struct AudioData {
|
||||
u8* sample_buffer;
|
||||
u32 num_samples;
|
||||
};
|
||||
|
||||
struct Port {
|
||||
OrbisAudio3dOpenParameters parameters{};
|
||||
std::deque<AudioData> queue; // Only stores PCM buffers for now
|
||||
std::optional<AudioData> current_buffer{};
|
||||
};
|
||||
|
||||
struct Audio3dState {
|
||||
std::unordered_map<OrbisAudio3dPortId, Port> ports;
|
||||
s32 audio_out_handle;
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(s32 handle);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOpen(OrbisAudio3dPortId port_id, OrbisUserServiceUserId user_id,
|
||||
s32 type, s32 index, u32 len, u32 freq,
|
||||
AudioOut::OrbisAudioOutParamExtendedInformation param);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(s32 handle, void* ptr);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(AudioOut::OrbisAudioOutOutputParam* param, u32 num);
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite(OrbisAudio3dPortId port_id, u32 num_channels,
|
||||
OrbisAudio3dFormat format, void* buffer, u32 num_samples);
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite2(OrbisAudio3dPortId port_id, u32 num_channels,
|
||||
OrbisAudio3dFormat format, void* buffer, u32 num_samples,
|
||||
OrbisAudio3dOutputRoute output_route, bool restricted);
|
||||
s32 PS4_SYSV_ABI sceAudio3dCreateSpeakerArray();
|
||||
s32 PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* params);
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2();
|
||||
s32 PS4_SYSV_ABI sceAudio3dInitialize(s64 reserved);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectReserve(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId* object_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectSetAttributes(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId object_id, u64 num_attributes,
|
||||
const OrbisAudio3dAttribute* attribute_array);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectUnreserve();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortAdvance(OrbisAudio3dPortId port_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortClose();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortCreate();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortDestroy();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFlush();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFreeState();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetList();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetParameters();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId port_id, u32* queue_level,
|
||||
u32* queue_available);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetState();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetStatus();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortOpen(OrbisUserServiceUserId user_id,
|
||||
const OrbisAudio3dOpenParameters* parameters,
|
||||
OrbisAudio3dPortId* port_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortPush(OrbisAudio3dPortId port_id, OrbisAudio3dBlocking blocking);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortQueryDebug();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortSetAttribute(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dAttributeId attribute_id, void* attribute,
|
||||
u64 attribute_size);
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportRegisterHandler();
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportUnregisterHandler();
|
||||
s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer();
|
||||
s32 PS4_SYSV_ABI sceAudio3dStrError();
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate();
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Audio3d
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_UNKNOWN = 0x80EA0001;
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_INVALID_PORT = 0x80EA0002;
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_INVALID_OBJECT = 0x80EA0003;
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "audio3d_error.h"
|
||||
#include "audio3d_impl.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
|
||||
using namespace Libraries::Kernel;
|
||||
|
||||
namespace Libraries::Audio3d {} // namespace Libraries::Audio3d
|
|
@ -1,16 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "audio3d.h"
|
||||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
class Audio3d {
|
||||
public:
|
||||
private:
|
||||
using OrbisAudio3dPluginId = u32;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Audio3d
|
Loading…
Add table
Reference in a new issue