Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions core/libs/SceTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,13 @@ struct AudioOutPortState {
std::uint64_t activeState;
};

struct AudioOutSystemState {
float loudness;
std::uint8_t reserved8[4];
std::uint64_t reserved[3];
};
static_assert(sizeof(AudioOutSystemState) == 32);

struct Audio3dOpenParameters {
std::uint64_t size_this;
std::uint32_t granularity;
Expand Down
10 changes: 10 additions & 0 deletions core/libs/prx/libSceAudioOut/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,14 @@ if(BUILD_TESTING)
set_tests_properties(audio_out2_shutdown audio_out2_waiting_push_shutdown audio_out2_advance_shutdown audio_out_shutdown PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceAudioOut>")
endif()

add_test_executable(audio_out_system_state_tests tests/AudioOutSystemState.cpp)
target_include_directories(audio_out_system_state_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(audio_out_system_state_tests PRIVATE libSceAudioOut libc)
configure_windows_unwind(audio_out_system_state_tests)
add_test(NAME audio_out_system_state COMMAND audio_out_system_state_tests)
if(WIN32)
set_tests_properties(audio_out_system_state PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceAudioOut>")
endif()
endif()
9 changes: 9 additions & 0 deletions core/libs/prx/libSceAudioOut/src/AudioOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,4 +714,13 @@ int APS5_VABI sceAudioOutExOpen(int userId, std::uint32_t mode) {
return allocatePort(PORT_TYPE_EX, highRate ? 1024 : 256, highRate ? 192000 : 48000, Format::S16Stereo);
}

int APS5_VABI sceAudioOutGetSystemState(AudioOutSystemState* state) {
if (state == nullptr) {
return -2144993276;
}
*state = {};
state->loudness = 0.0f;
return 0;
}

}
42 changes: 42 additions & 0 deletions core/libs/prx/libSceAudioOut/tests/AudioOutSystemState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "SceTypes.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"

#include <cstdint>
#include <cstdio>
#include <cstdlib>

extern "C" {
int APS5_VABI sceAudioOutGetSystemState(AudioOutSystemState*);
}

static void Require(bool value, const char* message) {
if (value) return;
std::fprintf(stderr, "%s\n", message);
std::abort();
}

namespace {

constexpr int invalidPointer = static_cast<int>(0x80260004);

void TestGetSystemState() {
AudioOutSystemState state{};
state.loudness = -1.0f;
state.reserved8[0] = 0xAA;
state.reserved[2] = ~0ull;
Require(sceAudioOutGetSystemState(&state) == 0, "sceAudioOutGetSystemState must succeed with valid pointer");
Require(state.loudness == 0.0f, "loudness must be reported as 0.0f");
Require(state.reserved8[0] == 0 && state.reserved[2] == 0, "reserved fields must be cleared");
}

void TestInvalidPointer() {
Require(sceAudioOutGetSystemState(nullptr) == invalidPointer, "null pointer must return SCE_AUDIO_OUT_ERROR_INVALID_POINTER");
}

}

int main() {
TestGetSystemState();
TestInvalidPointer();
return 0;
}
1 change: 1 addition & 0 deletions docs/dev/debt/libSceAudioOut.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [sceAudioOut2GetSpeakerArrayCoefficients](../../../core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp) (libSceAudioOut) - validates the handle and the coefficient count like the ambisonics call, then writes the front pair at full gain and silence for every other speaker, ignoring the position, spread, height awareness and downmix spread radius: [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp) and [prosper](https://github.com/mattias800/prosper/blob/main/prosper/src/hle/audio/hle_audio.cpp) both return that pair. The console's VBAP gains over the array's directions are not measured
- [sceAudioOutSetMixLevelPadSpk](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - no source applies the level (shadPS4 only stores it); it is assumed to be a linear gain on the port's own output, and the -9 dB default (11626) is applied to every pad speaker port, including those of titles that never call the function
- [sceAudioOutGetLastOutputTime](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - signature and behaviour taken from the [shadPS4](https://github.com/shadps4-emu/shadPS4) and [fpPS4](https://github.com/red-prig/fpPS4) reimplementations of the PS4 library, not confirmed on a PS5 title: the time is the process time at which `sceAudioOutOutput` or `sceAudioOutOutputs` accepted the port's last block, not the time the block reached the device
- [sceAudioOutGetSystemState](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - the 32-byte layout (`float loudness`, 4 reserved bytes, 3 reserved 64-bit words) follows shadPS4's `OrbisAudioOutSystemState` and SharpProspero's `SceAudioOutSystemState` (`Size = 32`); it is not confirmed on a console. Loudness is reported as a constant 0.0f, although SharpProspero documents it in LKFS, so the value is unconfirmed. shadPS4 returns NOT_INIT before `sceAudioOutInit`; that check is not modelled. Imported by PPSA30528, which fails to load without it
- [sceAudioOutSysOpen, sceAudioOutSysConfigureOutput, sceAudioOutSysClose](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - imported by PPSA99051 and PPSA99997, which fail to load without them; the signatures follow [EVO-PLAYER-PS5](https://github.com/sainsaji/EVO-PLAYER-PS5/blob/da0c0451333bab82e79fffd2de4718e917f9dcb0/projects/evoplayer/core/src/audio/evo_pt.cpp#L24-L29), whose audio code both titles share, and are not confirmed on a console. `sceAudioOutSysOpen(user, mode)` opens a port only for mode 5, the TrueHD MAT route: [the same project's carrier table](https://github.com/sainsaji/EVO-PLAYER-PS5/blob/da0c0451333bab82e79fffd2de4718e917f9dcb0/projects/evoplayer/core/src/audio/iec61937.cpp#L125-L140), read from sceAudioOutExOpen's own tables in firmware 12.70, describes it as a 768 kHz port of 1024 S16 8-channel frames whose 16-byte frames are consumed at 192 kHz; every other mode throws. Audio reaches the host through SDL as PCM and the host has no HDMI bitstream output, so like an Ex port a Sys port has no host device: `sceAudioOutOutput` paces it at its own rate and drops the MAT bursts. `sceAudioOutSysConfigureOutput(type, flags, mode, target, option)` accepts only the observed `(1, 0, 5, 1, 0)` HDMI MAT switch and changes nothing; other arguments throw. `sceAudioOutSysClose` closes a Sys port and throws for any other handle. The restore path EVO-PLAYER-PS5 takes after a Sys port calls `sceAudioOutExConfigureOutput(0, 0, 0xFF, 0xFF, 0)`, so no Sys reset combination is known
- [sceAudioOut2PortCreate](../../../core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp) (libSceAudioOut) - MAIN (type 0) format validation follows PS5 firmware 13.60 measurements: bits 8-11 accept 1, 2, 8 or 12, bits 0-6 accept 0 or 1, bit 7 requires 8 channels, and bits 12-31 do not affect validation. The sample types are still read as float and int16; bit 7's layout, the PCM effect of bits 12-31 and the port `flags` are unverified. Other port types retain unverified format validation, including 6 channels and rejection of bits 12-31
- [sceAudioOut2PortCreate](../../../core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp) (libSceAudioOut) - 12 channels are assumed to be L R C LFE Ls Rs Lb Rb Ltf Rtf Ltb Rtb as in KytyPS5's 12-to-8 fold, and 6 and 8 channels to be its first 6 and 8; no title or SDK header confirms the order
Expand Down
Loading