mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 02:33:32 +00:00
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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user