mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +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 2022 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
@@ -101,8 +102,8 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (params.channel_count == 2) {
|
if (params.channel_count == 2) {
|
||||||
state.early_gains[4] * 0.5f;
|
state.early_gains[4] *= 0.5f;
|
||||||
state.early_gains[5] * 0.5f;
|
state.early_gains[5] *= 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pre_time{
|
auto pre_time{
|
||||||
@@ -116,16 +117,12 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
|
|||||||
|
|
||||||
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
|
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
|
||||||
const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
||||||
state.fdn_delay_lines[i].sample_count =
|
state.fdn_delay_lines[i].SetDelay(
|
||||||
std::min(fdn_delay, state.fdn_delay_lines[i].sample_count_max);
|
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];
|
|
||||||
|
|
||||||
const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()};
|
||||||
state.decay_delay_lines[i].sample_count =
|
state.decay_delay_lines[i].SetDelay(
|
||||||
std::min(decay_delay, state.decay_delay_lines[i].sample_count_max);
|
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].decay =
|
state.decay_delay_lines[i].decay =
|
||||||
0.5999755859375f * (1.0f - Common::FixedPoint<50, 14>::from_base(params.colouration));
|
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)};
|
auto state_{reinterpret_cast<ReverbInfo::State*>(state)};
|
||||||
|
|
||||||
if (effect_enabled) {
|
if (effect_enabled) {
|
||||||
if (parameter.state == ReverbInfo::ParameterState::Updating) {
|
bool needs_init = state_->pre_delay_line.buffer.empty();
|
||||||
UpdateReverbEffectParameter(parameter, *state_);
|
|
||||||
} else if (parameter.state == ReverbInfo::ParameterState::Initialized) {
|
if (needs_init || parameter.state == ReverbInfo::ParameterState::Initialized) {
|
||||||
InitializeReverbEffect(parameter, *state_, workbuffer, long_size_pre_delay_supported);
|
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,
|
ApplyReverbEffect(parameter, *state_, effect_enabled, input_buffers, output_buffers,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -69,6 +70,7 @@ public:
|
|||||||
buffer.resize(delay_time + 1, 0);
|
buffer.resize(delay_time + 1, 0);
|
||||||
buffer_end = &buffer[delay_time];
|
buffer_end = &buffer[delay_time];
|
||||||
output = &buffer[0];
|
output = &buffer[0];
|
||||||
|
input = &buffer[0];
|
||||||
decay = decay_rate;
|
decay = decay_rate;
|
||||||
sample_count_max = delay_time;
|
sample_count_max = delay_time;
|
||||||
SetDelay(delay_time);
|
SetDelay(delay_time);
|
||||||
@@ -79,7 +81,6 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sample_count = delay_time;
|
sample_count = delay_time;
|
||||||
input = &buffer[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::FixedPoint<50, 14> Tick(const Common::FixedPoint<50, 14> sample) {
|
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 {
|
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()) {
|
if (out < buffer.data()) {
|
||||||
out += sample_count;
|
out += sample_count;
|
||||||
}
|
}
|
||||||
|
if (out >= buffer_end) {
|
||||||
|
out = buffer.data() + ((out - buffer.data()) % (sample_count_max + 1));
|
||||||
|
}
|
||||||
return *out;
|
return *out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user