test(audioout): check pad ports in the main mix without a pad device

With SDL's disk driver no pad audio device is open, so AudioOut2MixPorts
runs with no pad output. A vibration port and a mono pad speaker port
are pushed together: only the speaker's data reaches the main mix, and
a vibration port alone leaves it silent.
This commit is contained in:
Aryan Sharma 2026-10-09 11:22:04 +05:30
parent 34d09b5460
commit e548e594fa
1 changed files with 39 additions and 9 deletions

View File

@ -37,6 +37,8 @@ namespace {
constexpr std::uint32_t grain = 256;
constexpr std::uint32_t frequency = 48000;
constexpr std::uint16_t portTypeMain = 0;
constexpr std::uint16_t portTypePadSpeaker = 0x3;
constexpr std::uint16_t portTypePadVibration = 0x6;
constexpr std::uint32_t attributeData = 0;
constexpr std::uint32_t attributeVolume = 1;
constexpr std::uint32_t formatFloat = 0;
@ -73,9 +75,9 @@ AudioOut2ContextHandle CreateContext() {
return context;
}
int CreatePort(AudioOut2ContextHandle context, std::uint32_t format, AudioOut2PortHandle* port) {
int CreatePort(AudioOut2ContextHandle context, std::uint32_t format, AudioOut2PortHandle* port, std::uint16_t type = portTypeMain) {
AudioOut2PortParam params{};
params.port_type = portTypeMain;
params.port_type = type;
params.data_format = format;
params.sampling_freq = frequency;
return sceAudioOut2PortCreate(context, &params, port);
@ -91,20 +93,31 @@ void SetVolume(AudioOut2PortHandle port, const std::vector<float>& volume) {
Require(sceAudioOut2PortSetAttributes(port, &attribute, 1) == 0);
}
std::vector<float> Play(std::uint32_t format, const void* data, const std::vector<float>& volume) {
struct PortData {
std::uint16_t type;
std::uint32_t format;
const void* data;
std::vector<float> volume;
};
std::vector<float> Play(const std::vector<PortData>& inputs) {
const auto path = std::filesystem::temp_directory_path() / ("anyps5_audio_out2_port_layouts-" + std::to_string(std::random_device{}()) + ".raw");
std::filesystem::remove(path);
SetEnvironment("SDL_DISKAUDIOFILE", path.string());
const auto context = CreateContext();
AudioOut2PortHandle port = 0;
Require(CreatePort(context, format, &port) == 0);
SetVolume(port, volume);
SetData(port, data);
std::vector<AudioOut2PortHandle> ports;
for (const auto& input : inputs) {
AudioOut2PortHandle port = 0;
Require(CreatePort(context, input.format, &port, input.type) == 0);
SetVolume(port, input.volume);
SetData(port, input.data);
ports.push_back(port);
}
Require(sceAudioOut2ContextPush(context, 1) == 0);
SetData(port, nullptr);
for (const auto port : ports) SetData(port, nullptr);
for (std::uint32_t push = 0; push < silentGrains; push++) Require(sceAudioOut2ContextPush(context, 1) == 0);
Require(sceAudioOut2PortDestroy(port) == 0);
for (const auto port : ports) Require(sceAudioOut2PortDestroy(port) == 0);
Require(sceAudioOut2ContextDestroy(context) == 0);
std::ifstream file(path, std::ios::binary);
@ -121,6 +134,10 @@ std::vector<float> Play(std::uint32_t format, const void* data, const std::vecto
return {samples + first, samples + last};
}
std::vector<float> Play(std::uint32_t format, const void* data, const std::vector<float>& volume) {
return Play({{portTypeMain, format, data, volume}});
}
float Sample(std::uint32_t channel, std::uint32_t frame) {
const float sign = frame % 2 == 0 ? 1.0f : -1.0f;
return sign * 0.01f * static_cast<float>(channel + 1) * static_cast<float>(1 + frame % 5);
@ -204,6 +221,18 @@ void TestDroppedLfe() {
RequireFold(Play(Format(surround714.channels, formatFloat), data.data(), volume), surround714, expected, volume, 1.0f);
}
void TestPadPortsWithoutPadDevice() {
const auto speaker = FloatGrain(mono.channels);
std::vector<float> vibration(static_cast<std::size_t>(grain) * stereo.channels, 0.75f);
const std::vector<float> unity{1.0f, 1.0f};
const auto played = Play({
{portTypePadVibration, Format(stereo.channels, formatFloat), vibration.data(), unity},
{portTypePadSpeaker, Format(mono.channels, formatFloat), speaker.data(), {1.0f}},
});
RequireFold(played, mono, speaker, {1.0f}, 1.0f);
Require(Play({{portTypePadVibration, Format(stereo.channels, formatFloat), vibration.data(), unity}}).empty());
}
void TestMeasuredMainPortFormats() {
struct Case {
std::uint32_t format;
@ -270,6 +299,7 @@ int main() {
}
TestHeightChannels();
TestDroppedLfe();
TestPadPortsWithoutPadDevice();
TestMeasuredMainPortFormats();
return 0;
}