mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
Merge pull request #1820 from hugodearaujo/fix/audioout2-main-port-formats
fix(audioout2): match measured MAIN port format validation
This commit is contained in:
3 files changed
+68
-31
No files matched your search
@@ -28,6 +28,9 @@ static constexpr std::uint32_t FORMAT_CHANNELS_SHIFT = 8;
|
||||
static constexpr std::uint32_t FORMAT_CHANNELS_MASK = 0xFu;
|
||||
static constexpr std::uint32_t FORMAT_TYPE_MASK = 0x7Fu;
|
||||
static constexpr std::uint32_t FORMAT_FIELDS_MASK = 0xFFFu;
|
||||
static constexpr std::uint16_t PORT_TYPE_MAIN = 0;
|
||||
static constexpr int PORT_ERROR_FORMAT_FLAG_WITHOUT_8_CHANNELS = static_cast<int>(0x80268001);
|
||||
static constexpr int PORT_ERROR_UNSUPPORTED_FORMAT = static_cast<int>(0x8026800E);
|
||||
|
||||
static std::mutex g_portsLock;
|
||||
// Grows on demand: the title opens its bed ports plus max_object_ports object ports at once.
|
||||
@@ -158,6 +161,19 @@ extern "C" {
|
||||
int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params, AudioOut2PortHandle* port) {
|
||||
if (!ctx) return SCE_AUDIO_OUT2_ERROR_INVALID_HANDLE;
|
||||
if (!params || !port) return SCE_AUDIO_OUT2_ERROR_INVALID_ARGUMENT;
|
||||
const auto channels = (params->data_format >> FORMAT_CHANNELS_SHIFT) & FORMAT_CHANNELS_MASK;
|
||||
const auto sampleType = params->data_format & FORMAT_TYPE_MASK;
|
||||
const auto* fold = StereoFoldFor(channels);
|
||||
if (params->port_type == PORT_TYPE_MAIN) {
|
||||
if ((params->data_format & 0x80u) != 0 && channels != 8) {
|
||||
*port = static_cast<AudioOut2PortHandle>(-1);
|
||||
return PORT_ERROR_FORMAT_FLAG_WITHOUT_8_CHANNELS;
|
||||
}
|
||||
if (fold == nullptr || channels == 6 || sampleType > 1) {
|
||||
*port = static_cast<AudioOut2PortHandle>(-1);
|
||||
return PORT_ERROR_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
}
|
||||
std::lock_guard lock(g_portsLock);
|
||||
std::size_t index = 0;
|
||||
while (index < g_ports.size() && g_ports[index].used) index++;
|
||||
@@ -171,10 +187,9 @@ int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2
|
||||
entry.dataFormat = params->data_format;
|
||||
entry.samplingFreq = params->sampling_freq;
|
||||
entry.flags = params->flags;
|
||||
entry.channels = (params->data_format >> FORMAT_CHANNELS_SHIFT) & FORMAT_CHANNELS_MASK;
|
||||
const auto sampleType = params->data_format & FORMAT_TYPE_MASK;
|
||||
entry.fold = StereoFoldFor(entry.channels);
|
||||
if (entry.fold == nullptr || sampleType > 1 || (params->data_format & ~FORMAT_FIELDS_MASK) != 0) {
|
||||
entry.channels = channels;
|
||||
entry.fold = fold;
|
||||
if (entry.fold == nullptr || sampleType > 1 || (params->port_type != PORT_TYPE_MAIN && (params->data_format & ~FORMAT_FIELDS_MASK) != 0)) {
|
||||
entry = AudioOut2Port{};
|
||||
throw std::runtime_error("sceAudioOut2PortCreate: data format 0x" + [&] { char text[16]; std::snprintf(text, sizeof(text), "%x", params->data_format); return std::string(text); }() + " is not implemented");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -33,16 +32,6 @@ static void SetEnvironment(const char* name, const std::string& value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename TFunction>
|
||||
static bool ThrowsRuntimeError(TFunction function) {
|
||||
try {
|
||||
function();
|
||||
} catch (const std::runtime_error&) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::uint32_t grain = 256;
|
||||
@@ -65,7 +54,6 @@ struct Layout {
|
||||
|
||||
const Layout mono{1, {1.0f}, {1.0f}};
|
||||
const Layout stereo{2, {1.0f, 0.0f}, {0.0f, 1.0f}};
|
||||
const Layout surround51{6, {1.0f, 0.0f, fold, 0.0f, fold, 0.0f}, {0.0f, 1.0f, fold, 0.0f, 0.0f, fold}};
|
||||
const Layout surround71{8, {1.0f, 0.0f, fold, 0.0f, fold, 0.0f, fold, 0.0f}, {0.0f, 1.0f, fold, 0.0f, 0.0f, fold, 0.0f, fold}};
|
||||
const Layout surround714{12, {1.0f, 0.0f, fold, 0.0f, fold, 0.0f, fold, 0.0f, fold, 0.0f, fold * fold, 0.0f},
|
||||
{0.0f, 1.0f, fold, 0.0f, 0.0f, fold, 0.0f, fold, 0.0f, fold, 0.0f, fold * fold}};
|
||||
@@ -216,20 +204,49 @@ void TestDroppedLfe() {
|
||||
RequireFold(Play(Format(surround714.channels, formatFloat), data.data(), volume), surround714, expected, volume, 1.0f);
|
||||
}
|
||||
|
||||
void TestRejectedLayouts() {
|
||||
void TestMeasuredMainPortFormats() {
|
||||
struct Case {
|
||||
std::uint32_t format;
|
||||
std::uint32_t result;
|
||||
};
|
||||
constexpr Case cases[] = {
|
||||
{0x000, 0x8026800E}, {0x001, 0x8026800E}, {0x080, 0x80268001},
|
||||
{0x100, 0}, {0x101, 0}, {0x102, 0x8026800E}, {0x17F, 0x8026800E},
|
||||
{0x180, 0x80268001}, {0x181, 0x80268001}, {0x1FF, 0x80268001},
|
||||
{0x200, 0}, {0x201, 0}, {0x202, 0x8026800E}, {0x27F, 0x8026800E},
|
||||
{0x280, 0x80268001}, {0x281, 0x80268001}, {0x2FF, 0x80268001},
|
||||
{0x300, 0x8026800E}, {0x301, 0x8026800E}, {0x380, 0x80268001},
|
||||
{0x400, 0x8026800E}, {0x401, 0x8026800E}, {0x500, 0x8026800E},
|
||||
{0x600, 0x8026800E}, {0x601, 0x8026800E}, {0x680, 0x80268001},
|
||||
{0x700, 0x8026800E}, {0x701, 0x8026800E}, {0x780, 0x80268001},
|
||||
{0x800, 0}, {0x801, 0}, {0x802, 0x8026800E}, {0x87F, 0x8026800E},
|
||||
{0x880, 0}, {0x881, 0}, {0x882, 0x8026800E}, {0x8FF, 0x8026800E},
|
||||
{0x900, 0x8026800E}, {0x901, 0x8026800E}, {0x980, 0x80268001},
|
||||
{0xA00, 0x8026800E}, {0xB00, 0x8026800E}, {0xC00, 0}, {0xC01, 0},
|
||||
{0xC02, 0x8026800E}, {0xC7F, 0x8026800E}, {0xC80, 0x80268001},
|
||||
{0xC81, 0x80268001}, {0xD00, 0x8026800E}, {0xE00, 0x8026800E},
|
||||
{0xF00, 0x8026800E}, {0xFFF, 0x80268001},
|
||||
{0xFFFFF100, 0}, {0xFFFFF201, 0}, {0xFFFFF800, 0}, {0xFFFFFC01, 0},
|
||||
{0xFFFFF600, 0x8026800E}, {0xFFFFF202, 0x8026800E}, {0xFFFFF280, 0x80268001},
|
||||
};
|
||||
const auto context = CreateContext();
|
||||
for (const std::uint32_t channels : {0u, 3u, 4u, 5u, 7u, 9u, 10u, 11u, 13u, 15u}) {
|
||||
AudioOut2PortHandle port = 0;
|
||||
Require(ThrowsRuntimeError([&] { CreatePort(context, Format(channels, formatFloat), &port); }));
|
||||
Require(ThrowsRuntimeError([&] { CreatePort(context, Format(channels, formatS16), &port); }));
|
||||
for (const auto& test : cases) {
|
||||
AudioOut2PortHandle port = 0xAAAAAAAAAAAAAAAAull;
|
||||
Require(static_cast<std::uint32_t>(CreatePort(context, test.format, &port)) == test.result);
|
||||
if (test.result == 0) {
|
||||
Require(port != 0 && port != static_cast<AudioOut2PortHandle>(-1));
|
||||
Require(sceAudioOut2PortDestroy(port) == 0);
|
||||
} else {
|
||||
Require(port == static_cast<AudioOut2PortHandle>(-1));
|
||||
}
|
||||
}
|
||||
for (const std::uint32_t format : {0x100u, 0x201u, 0x800u, 0xC01u}) {
|
||||
for (std::uint32_t bit = 12; bit < 32; bit++) {
|
||||
AudioOut2PortHandle port = 0;
|
||||
Require(CreatePort(context, format | (1u << bit), &port) == 0);
|
||||
Require(sceAudioOut2PortDestroy(port) == 0);
|
||||
}
|
||||
}
|
||||
AudioOut2PortHandle port = 0;
|
||||
Require(ThrowsRuntimeError([&] { CreatePort(context, Format(12, 2), &port); }));
|
||||
Require(ThrowsRuntimeError([&] { CreatePort(context, Format(12, formatFloat) | 0x1000, &port); }));
|
||||
Require(ThrowsRuntimeError([&] { CreatePort(context, Format(12, formatFloat) | 0x10000, &port); }));
|
||||
Require(CreatePort(context, Format(12, formatFloat), &port) == 0);
|
||||
Require(port != 0);
|
||||
Require(sceAudioOut2PortDestroy(port) == 0);
|
||||
Require(sceAudioOut2ContextDestroy(context) == 0);
|
||||
}
|
||||
|
||||
@@ -237,7 +254,7 @@ void TestRejectedLayouts() {
|
||||
|
||||
int main() {
|
||||
SetEnvironment("SDL_AUDIODRIVER", "disk");
|
||||
for (const Layout* layout : {&mono, &stereo, &surround51, &surround71, &surround714}) {
|
||||
for (const Layout* layout : {&mono, &stereo, &surround71, &surround714}) {
|
||||
TestFloatLayout(*layout);
|
||||
TestS16Layout(*layout);
|
||||
}
|
||||
@@ -246,8 +263,13 @@ int main() {
|
||||
const auto volume = Volume(8);
|
||||
RequireFold(Play(Format(8, formatFloat) | 0x80, data.data(), volume), surround71, data, volume, 1.0f);
|
||||
}
|
||||
{
|
||||
const auto data = FloatGrain(2);
|
||||
const auto volume = Volume(2);
|
||||
RequireFold(Play(0xFFFFF200u, data.data(), volume), stereo, data, volume, 1.0f);
|
||||
}
|
||||
TestHeightChannels();
|
||||
TestDroppedLfe();
|
||||
TestRejectedLayouts();
|
||||
TestMeasuredMainPortFormats();
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user