mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 01:01:21 +00:00
ngs2: mix ports without matrix levels with the default matrix
Co-authored-by: Phr3d13 <phr3d13@gmail.com>
This commit is contained in:
1 parent
08a7d7fbed
commit
2f6dccb10b
2 files changed
+48
-1
No files matched your search
+18
-1
@@ -1803,6 +1803,18 @@ static void Ngs2ConsumeSamples(Ngs2VoiceInternal& voice, uint32_t grain) {
|
|||||||
voice.has_samples = output != 0;
|
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,
|
static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2VoiceInternal*>& voices,
|
||||||
uint32_t grain) {
|
uint32_t grain) {
|
||||||
if (voice.rendered) {
|
if (voice.rendered) {
|
||||||
@@ -1851,7 +1863,11 @@ static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2Voic
|
|||||||
EXIT_NOT_IMPLEMENTED(port.input >= voice.rack->NumBuffers());
|
EXIT_NOT_IMPLEMENTED(port.input >= voice.rack->NumBuffers());
|
||||||
const auto* input = source->Buffer(source->rack->PortBufferId(p), grain);
|
const auto* input = source->Buffer(source->rack->PortBufferId(p), grain);
|
||||||
auto* output = voice.Buffer(port.input, 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);
|
const auto* matrix = port.matrix < 0 ? nullptr : &source->matrices.at(port.matrix);
|
||||||
|
if (matrix != nullptr && matrix->empty()) {
|
||||||
|
matrix = nullptr;
|
||||||
|
}
|
||||||
const size_t output_channels =
|
const size_t output_channels =
|
||||||
matrix == nullptr
|
matrix == nullptr
|
||||||
? voice.channels
|
? voice.channels
|
||||||
@@ -1860,7 +1876,8 @@ static void Ngs2RenderVoice(Ngs2VoiceInternal& voice, const std::vector<Ngs2Voic
|
|||||||
for (uint32_t src = 0; src < source->channels; ++src) {
|
for (uint32_t src = 0; src < source->channels; ++src) {
|
||||||
const float level =
|
const float level =
|
||||||
port.volume * (matrix == nullptr
|
port.volume * (matrix == nullptr
|
||||||
? (src == dst ? 1.0f : 0.0f)
|
? Ngs2DefaultMatrixLevel(source->channels, src,
|
||||||
|
voice.channels, dst)
|
||||||
: (*matrix)[dst * source->channels + src]);
|
: (*matrix)[dst * source->channels + src]);
|
||||||
for (uint32_t i = 0; i < grain; ++i) {
|
for (uint32_t i = 0; i < grain; ++i) {
|
||||||
output[dst * grain + i] += input[src * grain + i] * level;
|
output[dst * grain + i] += input[src * grain + i] * level;
|
||||||
|
|||||||
@@ -1096,6 +1096,35 @@ void TestMonoRateAndRouting() {
|
|||||||
"22.05 kHz effect duration was incorrect");
|
"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() {
|
void TestMatrixOutputChannels() {
|
||||||
Fixture f(48000, 2);
|
Fixture f(48000, 2);
|
||||||
Ngs2RackInternal mastering_rack {};
|
Ngs2RackInternal mastering_rack {};
|
||||||
@@ -1933,6 +1962,7 @@ int main() {
|
|||||||
TestPcmSkipAcrossBlocks();
|
TestPcmSkipAcrossBlocks();
|
||||||
TestPcmBlocksEndWithTheirData();
|
TestPcmBlocksEndWithTheirData();
|
||||||
TestMonoRateAndRouting();
|
TestMonoRateAndRouting();
|
||||||
|
TestDefaultMatrix();
|
||||||
TestMatrixOutputChannels();
|
TestMatrixOutputChannels();
|
||||||
TestCustomPcmStillPlays();
|
TestCustomPcmStillPlays();
|
||||||
TestSetupQuery();
|
TestSetupQuery();
|
||||||
|
|||||||
Reference in new issue
Block a user