mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 01:01:21 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b65dd18224 | ||
|
|
2f6dccb10b | ||
|
|
08a7d7fbed | ||
|
|
2aa0d58ffb | ||
|
|
9bf311c6c7 | ||
|
|
e66a7f52b5 | ||
|
|
67f8276751 | ||
|
|
3ad21e35cc |
No files matched your search
@@ -1162,6 +1162,8 @@ LIB_DEFINE(InitAudio_1_Ngs2) {
|
||||
LIB_FUNC("AbYvTOZ8Pts", Ngs2::Ngs2VoiceRunCommands);
|
||||
LIB_FUNC("-TOuuAQ-buE", Ngs2::Ngs2VoiceGetState);
|
||||
LIB_FUNC("rEh728kXk3w", Ngs2::Ngs2VoiceGetStateFlags);
|
||||
LIB_FUNC("9eic4AmjGVI", Ngs2::Ngs2VoiceQueryInfo);
|
||||
LIB_FUNC("WCayTgob7-o", Ngs2::Ngs2VoiceGetPortInfo);
|
||||
LIB_FUNC("i0VnXM-C9fc", Ngs2::Ngs2SystemRender);
|
||||
LIB_FUNC("l4Q2dWEH6UM", Ngs2::Ngs2SystemSetGrainSamples);
|
||||
LIB_FUNC("hyVLT2VlOYk", Ngs2::Ngs2ParseWaveformData);
|
||||
|
||||
+121
-7
@@ -568,6 +568,9 @@ struct Ngs2VoiceInternal {
|
||||
std::vector<float> output_matrix;
|
||||
uint32_t channels = 0;
|
||||
uint32_t output_id = 0;
|
||||
float fbw_level = 1.0f;
|
||||
float lfe_level = 1.0f;
|
||||
float dry_level = 0.0f;
|
||||
bool rendering = false;
|
||||
bool rendered = false;
|
||||
bool has_samples = false;
|
||||
@@ -710,10 +713,11 @@ struct Ngs2VoiceInternal {
|
||||
if (count > capacity) {
|
||||
return NGS2_ERROR_INVALID_NUM_WAVEFORM_BLOCKS;
|
||||
}
|
||||
EXIT_NOT_IMPLEMENTED(!accepts_blocks || (flags & ~0x17u) != 0);
|
||||
const bool clear = (flags & 4u) != 0;
|
||||
const bool only_data = (flags & 2u) != 0;
|
||||
const bool join = only_data && (flags & 0x10u) == 0;
|
||||
// CLEAR reopens a list that the previous addition closed.
|
||||
EXIT_NOT_IMPLEMENTED((!accepts_blocks && !clear) || (flags & ~0x17u) != 0);
|
||||
const auto retained = clear ? 0 : blocks.size();
|
||||
Block tail = retained == 0 ? Block {} : blocks.back();
|
||||
std::vector<Block> pending;
|
||||
@@ -1800,6 +1804,18 @@ static void Ngs2ConsumeSamples(Ngs2VoiceInternal& voice, uint32_t grain) {
|
||||
voice.has_samples = output != 0;
|
||||
}
|
||||
|
||||
// Mono and stereo convert at -3 dB, mono feeds the surround front center, others map 1:1.
|
||||
static float Ngs2DefaultMatrixLevel(uint32_t src_channels, uint32_t src, uint32_t dst_channels,
|
||||
size_t dst) {
|
||||
if ((src_channels == 1 && dst_channels == 2) || (src_channels == 2 && dst_channels == 1)) {
|
||||
return std::numbers::sqrt2_v<float> / 2;
|
||||
}
|
||||
if (src_channels == 1 && dst_channels > 2) {
|
||||
return dst == 2 ? 1.0f : 0.0f;
|
||||
}
|
||||
return src == dst ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2VoiceInternal*>& voices,
|
||||
uint32_t grain) {
|
||||
if (voice.rendered) {
|
||||
@@ -1848,7 +1864,11 @@ static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2Voic
|
||||
EXIT_NOT_IMPLEMENTED(port.input >= voice.rack->NumBuffers());
|
||||
const auto* input = source->Buffer(source->rack->PortBufferId(p), grain);
|
||||
auto* output = voice.Buffer(port.input, grain);
|
||||
// A port without a matrix, or whose matrix has no levels, uses the default mix.
|
||||
const auto* matrix = port.matrix < 0 ? nullptr : &source->matrices.at(port.matrix);
|
||||
if (matrix != nullptr && matrix->empty()) {
|
||||
matrix = nullptr;
|
||||
}
|
||||
const size_t output_channels =
|
||||
matrix == nullptr
|
||||
? voice.channels
|
||||
@@ -1857,7 +1877,8 @@ static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2Voic
|
||||
for (uint32_t src = 0; src < source->channels; ++src) {
|
||||
const float level =
|
||||
port.volume * (matrix == nullptr
|
||||
? (src == dst ? 1.0f : 0.0f)
|
||||
? Ngs2DefaultMatrixLevel(source->channels, src,
|
||||
voice.channels, dst)
|
||||
: (*matrix)[dst * source->channels + src]);
|
||||
for (uint32_t i = 0; i < grain; ++i) {
|
||||
output[dst * grain + i] += input[src * grain + i] * level;
|
||||
@@ -1867,6 +1888,11 @@ static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2Voic
|
||||
voice.has_samples = true;
|
||||
}
|
||||
}
|
||||
if (voice.has_samples && voice.rack->type == Ngs2RackType::Reverb) {
|
||||
for (auto& sample: voice.samples) {
|
||||
sample *= voice.dry_level;
|
||||
}
|
||||
}
|
||||
if (voice.has_samples) {
|
||||
const auto& custom = voice.rack->option.custom_sampler.custom_rack_option;
|
||||
const auto rate = voice.rack->ngs->option.sample_rate;
|
||||
@@ -1978,10 +2004,13 @@ int KYTY_SYSV_ABI Ngs2SystemRender(uintptr_t system_handle, const Ngs2RenderBuff
|
||||
pcm = static_cast<float*>(output.buffer);
|
||||
}
|
||||
for (uint32_t dst = 0; dst < output.num_channels; ++dst) {
|
||||
// Output channel 3 is LFE; every other channel is full band.
|
||||
const float gain = dst == 3 ? voice->lfe_level : voice->fbw_level;
|
||||
for (uint32_t src = 0; src < voice->channels; ++src) {
|
||||
const float level = voice->output_matrix.empty()
|
||||
? (src == dst ? 1.0f : 0.0f)
|
||||
: voice->output_matrix.at(src * output.num_channels + dst);
|
||||
const float level =
|
||||
gain * (voice->output_matrix.empty()
|
||||
? static_cast<float>(src == dst)
|
||||
: voice->output_matrix.at(src * output.num_channels + dst));
|
||||
if (level == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
@@ -2339,6 +2368,17 @@ int KYTY_SYSV_ABI Ngs2RackGetVoiceHandle(uintptr_t rack_handle, uint32_t voice_i
|
||||
return OK;
|
||||
}
|
||||
|
||||
// A patch to a rack handle connects to voice #0 of that rack.
|
||||
static Ngs2VoiceInternal* Ngs2FindPatchDestination(uintptr_t handle) {
|
||||
Common::LockGuard racks_lock(g_racks_mutex);
|
||||
for (auto* rack = g_racks_list; rack != nullptr; rack = rack->next) {
|
||||
if (reinterpret_cast<uintptr_t>(rack) == handle) {
|
||||
return reinterpret_cast<Ngs2VoiceInternal*>(rack + 1);
|
||||
}
|
||||
}
|
||||
return reinterpret_cast<Ngs2VoiceInternal*>(handle);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamHeader* param_list) {
|
||||
PRINT_NAME();
|
||||
@@ -2408,7 +2448,7 @@ int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamH
|
||||
const auto* patch = reinterpret_cast<const Ngs2VoicePatchParam*>(param);
|
||||
EXIT_NOT_IMPLEMENTED(patch->port >= voice->ports.size());
|
||||
voice->ports[patch->port].dest =
|
||||
reinterpret_cast<Ngs2VoiceInternal*>(patch->dest_handle);
|
||||
Ngs2FindPatchDestination(patch->dest_handle);
|
||||
voice->ports[patch->port].input = patch->dest_input_id;
|
||||
LOGF("\t connect->port = %u\n"
|
||||
"\t connect->dest_input_id = %u\n"
|
||||
@@ -2456,7 +2496,31 @@ int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamH
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x2001: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Reverb); break;
|
||||
case 0x2001: {
|
||||
EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Reverb);
|
||||
const auto* values = reinterpret_cast<const uint32_t*>(param + 1);
|
||||
switch (param->id & 0xffffu) {
|
||||
case 0:
|
||||
// Input and output channels, flags; channel conversion stays silent.
|
||||
EXIT_NOT_IMPLEMENTED(values[0] == 0 || values[2] != 0);
|
||||
voice->ResetSetupState();
|
||||
voice->channels = values[1] == values[0] ? values[0] : 0;
|
||||
break;
|
||||
case 1: {
|
||||
// The reverb parameters start with the wet and dry levels.
|
||||
const auto* levels = reinterpret_cast<const float*>(values);
|
||||
voice->dry_level = std::clamp(levels[1], 0.0f, 1.0f);
|
||||
|
||||
static std::atomic_bool wet_warned = false;
|
||||
if (levels[0] != 0.0f && !wet_warned.exchange(true)) {
|
||||
Log::WriteToConsoleAndLog("warning: NGS2 reverb wet signal is muted\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: EXIT("unsupported reverb control: 0x%08" PRIx32 "\n", param->id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x3000: {
|
||||
EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Mastering);
|
||||
const auto* values = reinterpret_cast<const uint32_t*>(param + 1);
|
||||
@@ -2470,6 +2534,12 @@ int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamH
|
||||
matrix->levels + matrix->num_levels);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const auto* levels = reinterpret_cast<const float*>(values);
|
||||
voice->fbw_level = std::clamp(levels[0], 0.0f, 4.0f);
|
||||
voice->lfe_level = std::clamp(levels[1], 0.0f, 4.0f);
|
||||
break;
|
||||
}
|
||||
case 5: voice->output_id = values[0]; break;
|
||||
default: EXIT("unsupported mastering control: 0x%08" PRIx32 "\n", param->id);
|
||||
}
|
||||
@@ -2761,6 +2831,50 @@ int KYTY_SYSV_ABI Ngs2VoiceGetStateFlags(uintptr_t voice_handle, uint32_t* state
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Ngs2VoiceQueryInfo(uintptr_t voice_handle, uint32_t query_id, void* info,
|
||||
size_t info_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
struct SetupInfo {
|
||||
uint32_t channels, flags;
|
||||
};
|
||||
EXIT_NOT_IMPLEMENTED(voice_handle == 0 || info == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(query_id != 0x4001 || info_size != sizeof(SetupInfo));
|
||||
|
||||
auto* voice = reinterpret_cast<Ngs2VoiceInternal*>(voice_handle);
|
||||
|
||||
Common::LockGuard lock(voice->rack->ngs->mutex);
|
||||
|
||||
*static_cast<SetupInfo*>(info) = {voice->channels, 0};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetPortInfo(uintptr_t voice_handle, uint32_t port, void* info,
|
||||
size_t info_size) {
|
||||
PRINT_NAME();
|
||||
|
||||
struct PortInfo {
|
||||
int32_t matrix;
|
||||
float volume;
|
||||
uint32_t delay_samples, input;
|
||||
uintptr_t dest;
|
||||
};
|
||||
EXIT_NOT_IMPLEMENTED(voice_handle == 0 || info == nullptr || info_size != sizeof(PortInfo));
|
||||
|
||||
auto* voice = reinterpret_cast<Ngs2VoiceInternal*>(voice_handle);
|
||||
|
||||
Common::LockGuard lock(voice->rack->ngs->mutex);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(port >= voice->ports.size());
|
||||
const auto& p = voice->ports[port];
|
||||
|
||||
*static_cast<PortInfo*>(info) = {p.matrix, p.volume, 0, p.input,
|
||||
reinterpret_cast<uintptr_t>(p.dest)};
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Ngs2SystemLock(uintptr_t system_handle) {
|
||||
PRINT_NAME();
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ int KYTY_SYSV_ABI Ngs2VoiceRunCommands(uintptr_t voice_handle, const void* comma
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* state,
|
||||
size_t state_size);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetStateFlags(uintptr_t voice_handle, uint32_t* state_flags);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceQueryInfo(uintptr_t voice_handle, uint32_t query_id, void* info,
|
||||
size_t info_size);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetPortInfo(uintptr_t voice_handle, uint32_t port, void* info,
|
||||
size_t info_size);
|
||||
int KYTY_SYSV_ABI Ngs2SystemRender(uintptr_t system_handle, const Ngs2RenderBufferInfo* buffer_info,
|
||||
uint32_t num_buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2ParseWaveformData(const void* data, size_t data_size, Ngs2WaveformInfo* info);
|
||||
|
||||
@@ -807,6 +807,76 @@ void TestPcm16RenderOutput() {
|
||||
"PCM16 output retained samples from the previous render");
|
||||
}
|
||||
|
||||
void TestPatchToRackHandle() {
|
||||
Ngs2Internal system;
|
||||
Ngs2RackOptionUnion sampler_option {}, mastering_option {};
|
||||
Ngs2FillDefaultRackOption(0x1000, &sampler_option);
|
||||
Ngs2FillDefaultRackOption(0x3000, &mastering_option);
|
||||
sampler_option.common.max_voices = 1;
|
||||
RenderRack sampler(system, 0x1000, sampler_option.common);
|
||||
RenderRack master(system, 0x3000, mastering_option.common);
|
||||
auto& source = sampler.Voice();
|
||||
Ngs2VoicePatchParam patch {{24, 0, 5}, 0, 0, master.handle};
|
||||
Check(Ngs2VoiceControl(reinterpret_cast<uintptr_t>(&source), &patch.header) == OK &&
|
||||
source.ports[0].dest == &master.Voice(),
|
||||
"patch to a rack handle did not connect to its voice #0");
|
||||
}
|
||||
|
||||
void TestMasteringGain() {
|
||||
Ngs2Internal system;
|
||||
system.option = Ngs2DefaultSystemOption();
|
||||
system.option.num_grain_samples = 1;
|
||||
Ngs2RackOptionUnion sampler_option {}, mastering_option {};
|
||||
Ngs2FillDefaultRackOption(0x1000, &sampler_option);
|
||||
Ngs2FillDefaultRackOption(0x3000, &mastering_option);
|
||||
sampler_option.common.max_voices = 1;
|
||||
RenderRack sampler(system, 0x1000, sampler_option.common);
|
||||
RenderRack master(system, 0x3000, mastering_option.common);
|
||||
auto& source = sampler.Voice();
|
||||
auto& mastering = master.Voice();
|
||||
mastering.channels = 8;
|
||||
mastering.state = Ngs2VoicePlayState::Playing;
|
||||
const int16_t frame[8] = {8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192};
|
||||
source.SetupSampler({0x12, 8, 48000});
|
||||
source.blocks.push_back({reinterpret_cast<const uint8_t*>(frame), {0, sizeof(frame), 0, 0, 1}});
|
||||
source.ports[0].dest = &mastering;
|
||||
source.SetEvent(1);
|
||||
struct {
|
||||
Ngs2VoiceParamHeader header {16, 0, 0x30000004};
|
||||
float fbw = 5.0f, lfe = 0.5f;
|
||||
} gain;
|
||||
float pcm[8] = {};
|
||||
Ngs2RenderBufferInfo output {pcm, sizeof(pcm), 0x18, 8};
|
||||
const float expected[8] = {1.0f, 1.0f, 1.0f, 0.125f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
Check(Ngs2VoiceControl(reinterpret_cast<uintptr_t>(&mastering), &gain.header) == OK &&
|
||||
Ngs2SystemRender(reinterpret_cast<uintptr_t>(&system), &output, 1) == OK &&
|
||||
std::ranges::equal(pcm, expected),
|
||||
"mastering gain was not clamped or applied per full band and LFE channel");
|
||||
}
|
||||
|
||||
void TestReverbDryLevel() {
|
||||
Fixture f(48000);
|
||||
Ngs2RackInternal reverb_rack {};
|
||||
reverb_rack.ngs = &f.system;
|
||||
reverb_rack.type = Ngs2RackType::Reverb;
|
||||
Ngs2VoiceInternal reverb;
|
||||
reverb.rack = &reverb_rack;
|
||||
f.voice.ports.push_back({&reverb, 0, 1.0f, -1});
|
||||
const int16_t pcm = 8192;
|
||||
f.Queue(&pcm, 1, 0);
|
||||
struct {
|
||||
Ngs2VoiceParamHeader header {24, 24, 0x20010000};
|
||||
uint32_t channels[4] = {1, 1, 0, 0};
|
||||
Ngs2VoiceParamHeader levels_header {96, 0, 0x20010001};
|
||||
float levels[22] = {0.6f, 0.4f};
|
||||
} setup;
|
||||
Ngs2VoiceControl(reinterpret_cast<uintptr_t>(&reverb), &setup.header);
|
||||
reverb.SetEvent(1);
|
||||
Ngs2RenderVoice(reverb, {&f.voice, &reverb}, 1);
|
||||
Check(reverb.has_samples && reverb.samples[0] == 0.25f * 0.4f,
|
||||
"reverb did not pass its dry signal");
|
||||
}
|
||||
|
||||
void TestCustomMasteringChannelMixer() {
|
||||
Ngs2Internal system;
|
||||
system.option = Ngs2DefaultSystemOption();
|
||||
@@ -1026,6 +1096,35 @@ void TestMonoRateAndRouting() {
|
||||
"22.05 kHz effect duration was incorrect");
|
||||
}
|
||||
|
||||
void TestDefaultMatrix() {
|
||||
struct Case {
|
||||
uint32_t src_channels;
|
||||
int32_t matrix;
|
||||
uint32_t dst_channels;
|
||||
std::vector<float> expected;
|
||||
};
|
||||
constexpr float minus_3db = std::numbers::sqrt2_v<float> / 2;
|
||||
const int16_t pcm[] = {8192, -16384};
|
||||
for (const auto& c: {Case {1, -1, 2, {0.25f * minus_3db, 0.25f * minus_3db}},
|
||||
Case {1, 0, 2, {0.25f * minus_3db, 0.25f * minus_3db}},
|
||||
Case {2, -1, 1, {0.25f * minus_3db + -0.5f * minus_3db}},
|
||||
Case {1, -1, 6, {0, 0, 0.25f, 0, 0, 0}}}) {
|
||||
Fixture f(48000, c.src_channels);
|
||||
Ngs2RackInternal rack {};
|
||||
rack.ngs = &f.system;
|
||||
rack.type = Ngs2RackType::Mastering;
|
||||
Ngs2VoiceInternal dest;
|
||||
dest.rack = &rack;
|
||||
dest.channels = c.dst_channels;
|
||||
dest.state = Ngs2VoicePlayState::Playing;
|
||||
f.voice.matrices.resize(1);
|
||||
f.voice.ports.push_back({&dest, 0, 1.0f, c.matrix});
|
||||
f.Queue(pcm, 1, 0);
|
||||
Ngs2RenderVoice(dest, {&f.voice, &dest}, 1);
|
||||
Check(dest.samples == c.expected, "default port mix produced the wrong channel levels");
|
||||
}
|
||||
}
|
||||
|
||||
void TestMatrixOutputChannels() {
|
||||
Fixture f(48000, 2);
|
||||
Ngs2RackInternal mastering_rack {};
|
||||
@@ -1111,6 +1210,38 @@ void TestDeferredSamplerSetup() {
|
||||
"sampler did not play after deferred stream setup");
|
||||
}
|
||||
|
||||
void TestClearReopensClosedList() {
|
||||
Fixture f(48000);
|
||||
const int16_t first = 8192, second = -16384;
|
||||
f.Queue(&first, 1, 0);
|
||||
f.Queue(&second, 1, 4);
|
||||
f.Render(1);
|
||||
Check(f.voice.samples[0] == -0.5f, "CLEAR did not reopen a closed waveform list");
|
||||
}
|
||||
|
||||
void TestSetupQuery() {
|
||||
Fixture f(48000, 2);
|
||||
uint32_t info[2] = {99, 99};
|
||||
Ngs2VoiceQueryInfo(reinterpret_cast<uintptr_t>(&f.voice), 0x4001, info, sizeof(info));
|
||||
Check(info[0] == 2 && info[1] == 0, "setup query did not report the voice channels");
|
||||
}
|
||||
|
||||
void TestPortInfo() {
|
||||
Fixture f(48000);
|
||||
Ngs2VoiceInternal dest;
|
||||
f.voice.ports.push_back({&dest, 1, 0.5f, 0});
|
||||
struct {
|
||||
int32_t matrix;
|
||||
float volume;
|
||||
uint32_t delay_samples, input;
|
||||
uintptr_t dest;
|
||||
} info {99, 99, 99, 99, 99};
|
||||
Ngs2VoiceGetPortInfo(reinterpret_cast<uintptr_t>(&f.voice), 0, &info, sizeof(info));
|
||||
Check(info.matrix == 0 && info.volume == 0.5f && info.delay_samples == 0 && info.input == 1 &&
|
||||
info.dest == reinterpret_cast<uintptr_t>(&dest),
|
||||
"port info did not report the port routing and volume");
|
||||
}
|
||||
|
||||
void TestPlayStateBeforeRender() {
|
||||
Fixture f(48000);
|
||||
const int16_t pcm[] = {8192, -16384};
|
||||
@@ -1803,6 +1934,9 @@ int main() {
|
||||
TestAtrac9Vibration();
|
||||
TestAtrac9Discrete();
|
||||
TestPcm16RenderOutput();
|
||||
TestPatchToRackHandle();
|
||||
TestMasteringGain();
|
||||
TestReverbDryLevel();
|
||||
TestCustomMasteringChannelMixer();
|
||||
TestCustomVoiceStateCapacity();
|
||||
TestSubmixerSetupAndRouting();
|
||||
@@ -1837,8 +1971,12 @@ int main() {
|
||||
TestPcmSkipAcrossBlocks();
|
||||
TestPcmBlocksEndWithTheirData();
|
||||
TestMonoRateAndRouting();
|
||||
TestDefaultMatrix();
|
||||
TestMatrixOutputChannels();
|
||||
TestCustomPcmStillPlays();
|
||||
TestClearReopensClosedList();
|
||||
TestSetupQuery();
|
||||
TestPortInfo();
|
||||
TestPlayStateBeforeRender();
|
||||
TestStatePublication();
|
||||
TestStopThenPlayBeforeRender();
|
||||
|
||||
@@ -25,7 +25,7 @@ TestCase TrinityBvhIntersections(bool compressed, bool bary, bool sorted,
|
||||
data[NodeStart + 29] = 9u << 22; // Force opaque and flip facing.
|
||||
data[NodeStart + 30] = 0x98;
|
||||
data[NodeStart + 31] = 0x04123456;
|
||||
const std::array<float, 8> near {5,1,3,7,4,2,6,8};
|
||||
const std::array<float, 8> nearDist {5,1,3,7,4,2,6,8};
|
||||
const std::array<float, 8> length {1,8,3,5,7,2,4,6};
|
||||
const std::array<u32, 8> children {128,138,171,190,256,266,299,318};
|
||||
const auto set_bits = [&](u32 base, u32 offset, u32 count, u32 value) {
|
||||
@@ -43,12 +43,12 @@ TestCase TrinityBvhIntersections(bool compressed, bool bary, bool sorted,
|
||||
const u32 index = slot * 4 + i;
|
||||
if (compressed) {
|
||||
// Exact integer minima; positive maxima round outward within one quantization step.
|
||||
const std::array<u32, 6> planes {0x30000, 0x30000, u32(near[index]) * 8192,
|
||||
0x10000, 0x10000, u32(near[index] + length[index]) * 8192};
|
||||
const std::array<u32, 6> planes {0x30000, 0x30000, u32(nearDist[index]) * 8192,
|
||||
0x10000, 0x10000, u32(nearDist[index] + length[index]) * 8192};
|
||||
for (u32 axis = 0; axis < 6; ++axis) set_bits(base, 80 + i * 108 + axis * 18, 18, planes[axis]);
|
||||
} else {
|
||||
data[base + i] = children[index];
|
||||
const std::array<float, 6> bounds {-1,-1,near[index], 1,1,near[index] + length[index]};
|
||||
const std::array<float, 6> bounds {-1,-1,nearDist[index], 1,1,nearDist[index] + length[index]};
|
||||
for (u32 axis = 0; axis < 6; ++axis) data[base + 4 + i * 6 + axis] = bits(bounds[axis]);
|
||||
}
|
||||
}
|
||||
@@ -126,8 +126,8 @@ TestCase TrinityBvhIntersections(bool compressed, bool bary, bool sorted,
|
||||
const bool xt = (children[x] & 7) < 2, yt = (children[y] & 7) < 2;
|
||||
if (triangles_first && xt != yt) return xt;
|
||||
if (heuristic == 1) return length[x] > length[y];
|
||||
if (heuristic == 2) return 2 * near[x] + length[x] < 2 * near[y] + length[y];
|
||||
return near[x] < near[y];
|
||||
if (heuristic == 2) return 2 * nearDist[x] + length[x] < 2 * nearDist[y] + length[y];
|
||||
return nearDist[x] < nearDist[y];
|
||||
};
|
||||
if (sorted) {
|
||||
if (wide_sort && which == 3) std::stable_sort(order.begin(), order.end(), compare);
|
||||
|
||||
Reference in new issue
Block a user