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:
parent
34d09b5460
commit
e548e594fa
|
|
@ -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, ¶ms, 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue