mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
* OrbisAudio3dOpenParameters struct fix Not sure why we have the extra filler, but decomp suggests it shouldn't exist. This fixes stack_chk_fail issues in audio3d using titles. * Bring back filler, only copy 0x20 bytes. The library accepts variations on struct size, with the maximum size being the 0x28 size our current struct has. This fixes the issue without potentially breaking the struct. * Fix memcpy Prevent OOB read
589 lines
22 KiB
C++
589 lines
22 KiB
C++
// 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"
|
|
#include "core/libraries/libs.h"
|
|
|
|
namespace Libraries::Audio3d {
|
|
|
|
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);
|
|
}
|
|
|
|
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,
|
|
"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) {
|
|
auto default_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,
|
|
};
|
|
memcpy(params, &default_params, 0x20);
|
|
}
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
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, parameters->size_this);
|
|
|
|
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,
|
|
"called, port_id = {}, attribute_id = {}, attribute = {}, attribute_size = {}",
|
|
port_id, static_cast<u32>(attribute_id), attribute, attribute_size);
|
|
|
|
if (!state->ports.contains(port_id)) {
|
|
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
|
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
|
}
|
|
|
|
if (!attribute) {
|
|
LOG_ERROR(Lib_Audio3d, "!attribute");
|
|
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// TODO
|
|
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceAudio3dReportRegisterHandler() {
|
|
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() {
|
|
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer() {
|
|
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceAudio3dStrError() {
|
|
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceAudio3dTerminate() {
|
|
LOG_INFO(Lib_Audio3d, "called");
|
|
if (!state) {
|
|
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
|
}
|
|
|
|
AudioOut::sceAudioOutOutput(state->audio_out_handle, nullptr);
|
|
AudioOut::sceAudioOutClose(state->audio_out_handle);
|
|
state.release();
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
|
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dAudioOutClose);
|
|
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dAudioOutOpen);
|
|
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dAudioOutOutput);
|
|
LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dAudioOutOutputs);
|
|
LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dBedWrite);
|
|
LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dBedWrite2);
|
|
LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dCreateSpeakerArray);
|
|
LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dDeleteSpeakerArray);
|
|
LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dGetDefaultOpenParameters);
|
|
LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dGetSpeakerArrayMemorySize);
|
|
LIB_FUNCTION("-R1DukFq7Dk", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dGetSpeakerArrayMixCoefficients);
|
|
LIB_FUNCTION("-Re+pCWvwjQ", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dGetSpeakerArrayMixCoefficients2);
|
|
LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dInitialize);
|
|
LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dObjectReserve);
|
|
LIB_FUNCTION("4uyHN9q4ZeU", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dObjectSetAttributes);
|
|
LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dObjectUnreserve);
|
|
LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortAdvance);
|
|
LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortClose);
|
|
LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortCreate);
|
|
LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortDestroy);
|
|
LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortFlush);
|
|
LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortFreeState);
|
|
LIB_FUNCTION("9ZA23Ia46Po", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dPortGetAttributesSupported);
|
|
LIB_FUNCTION("SEggctIeTcI", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortGetList);
|
|
LIB_FUNCTION("flPcUaXVXcw", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortGetParameters);
|
|
LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortGetQueueLevel);
|
|
LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortGetState);
|
|
LIB_FUNCTION("iRX6GJs9tvE", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortGetStatus);
|
|
LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortOpen);
|
|
LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortPush);
|
|
LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortQueryDebug);
|
|
LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dPortSetAttribute);
|
|
LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dReportRegisterHandler);
|
|
LIB_FUNCTION("psv2gbihC1A", "libSceAudio3d", 1, "libSceAudio3d",
|
|
sceAudio3dReportUnregisterHandler);
|
|
LIB_FUNCTION("yEYXcbAGK14", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dSetGpuRenderer);
|
|
LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dStrError);
|
|
LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", sceAudio3dTerminate);
|
|
};
|
|
|
|
} // namespace Libraries::Audio3d
|