audio_core: Fix reverb effect causing extreme noise on Windows

Fixed multiple bugs in reverb processing:
- Early gains for stereo channels not being assigned (missing *=)
- Incorrect TapOut pointer arithmetic (extra +1 offset)
- Uninitialized input pointer causing crashes
- Missing state initialization check
- SetDelay not called during parameter updates

Co-authored-by: MaranBr <maranbr@outlook.com>
Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-12-17 16:41:59 +10:00
parent b1192de0c4
commit 5fbfc6693b
2 changed files with 18 additions and 15 deletions

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <numbers>
@@ -101,8 +102,8 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
}
if (params.channel_count == 2) {
state.early_gains[4] * 0.5f;
state.early_gains[5] * 0.5f;
state.early_gains[4] *= 0.5f;
state.early_gains[5] *= 0.5f;
}
auto pre_time{
@@ -116,16 +117,12 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()};
state.fdn_delay_lines[i].sample_count =
std::min(fdn_delay, state.fdn_delay_lines[i].sample_count_max);
state.fdn_delay_lines[i].buffer_end =
&state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
state.fdn_delay_lines[i].SetDelay(
std::min(fdn_delay, state.fdn_delay_lines[i].sample_count_max));
const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()};
state.decay_delay_lines[i].sample_count =
std::min(decay_delay, state.decay_delay_lines[i].sample_count_max);
state.decay_delay_lines[i].buffer_end =
&state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
state.decay_delay_lines[i].SetDelay(
std::min(decay_delay, state.decay_delay_lines[i].sample_count_max));
state.decay_delay_lines[i].decay =
0.5999755859375f * (1.0f - Common::FixedPoint<50, 14>::from_base(params.colouration));
@@ -425,10 +422,12 @@ void ReverbCommand::Process(const AudioRenderer::CommandListProcessor& processor
auto state_{reinterpret_cast<ReverbInfo::State*>(state)};
if (effect_enabled) {
if (parameter.state == ReverbInfo::ParameterState::Updating) {
UpdateReverbEffectParameter(parameter, *state_);
} else if (parameter.state == ReverbInfo::ParameterState::Initialized) {
bool needs_init = state_->pre_delay_line.buffer.empty();
if (needs_init || parameter.state == ReverbInfo::ParameterState::Initialized) {
InitializeReverbEffect(parameter, *state_, workbuffer, long_size_pre_delay_supported);
} else if (parameter.state == ReverbInfo::ParameterState::Updating) {
UpdateReverbEffectParameter(parameter, *state_);
}
}
ApplyReverbEffect(parameter, *state_, effect_enabled, input_buffers, output_buffers,

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -69,6 +70,7 @@ public:
buffer.resize(delay_time + 1, 0);
buffer_end = &buffer[delay_time];
output = &buffer[0];
input = &buffer[0];
decay = decay_rate;
sample_count_max = delay_time;
SetDelay(delay_time);
@@ -79,7 +81,6 @@ public:
return;
}
sample_count = delay_time;
input = &buffer[0];
}
Common::FixedPoint<50, 14> Tick(const Common::FixedPoint<50, 14> sample) {
@@ -107,10 +108,13 @@ public:
}
Common::FixedPoint<50, 14> TapOut(const s32 index) const {
auto out{input - (index + 1)};
const Common::FixedPoint<50, 14>* out{input - index};
if (out < buffer.data()) {
out += sample_count;
}
if (out >= buffer_end) {
out = buffer.data() + ((out - buffer.data()) % (sample_count_max + 1));
}
return *out;
}