aboutsummaryrefslogtreecommitdiff
path: root/src/audio_core/renderer/command/effect/reverb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core/renderer/command/effect/reverb.cpp')
-rw-r--r--src/audio_core/renderer/command/effect/reverb.cpp123
1 files changed, 79 insertions, 44 deletions
diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp
index 87eab1adda..ec3a82802f 100644
--- a/src/audio_core/renderer/command/effect/reverb.cpp
+++ b/src/audio_core/renderer/command/effect/reverb.cpp
@@ -84,6 +84,7 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
const auto pow_10 = [](f32 val) -> f32 {
return (val >= 0.0f) ? 1.0f : (val <= -5.3f) ? 0.0f : std::pow(10.0f, val);
};
+
const auto cos = [](f32 degrees) -> f32 {
return std::cos(degrees * std::numbers::pi_v<f32> / 180.0f);
};
@@ -91,26 +92,39 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
static bool unk_initialized{false};
static Common::FixedPoint<50, 14> unk_value{};
- const auto sample_rate{Common::FixedPoint<50, 14>::from_base(params.sample_rate)};
- const auto pre_delay_time{Common::FixedPoint<50, 14>::from_base(params.pre_delay)};
+ auto sample_rate = Common::FixedPoint<50, 14>::from_base(params.sample_rate);
+ if (sample_rate.to_float() < 1.0f) sample_rate = Common::FixedPoint<50, 14>(1.0f);
+
+ auto pre_delay_time = Common::FixedPoint<50, 14>::from_base(params.pre_delay);
+ if (pre_delay_time.to_float() < 0.0f) pre_delay_time = Common::FixedPoint<50, 14>(0.0f);
for (u32 i = 0; i < ReverbInfo::MaxDelayTaps; i++) {
- auto early_delay{
- ((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int()};
- early_delay = (std::min)(early_delay, state.pre_delay_line.sample_count_max);
- state.early_delay_times[i] = early_delay + 1;
- state.early_gains[i] = Common::FixedPoint<50, 14>::from_base(params.early_gain) *
- EarlyDelayGains[params.early_mode][i];
+ int target_delay = ((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int();
+ if (target_delay < 0) target_delay = 0;
+ if (target_delay > state.pre_delay_line.sample_count_max) target_delay = state.pre_delay_line.sample_count_max;
+
+ int old_delay = state.early_delay_times[i] - 1;
+ int smooth_delay = old_delay + (target_delay - old_delay) / 4;
+ state.early_delay_times[i] = smooth_delay + 1;
+
+ auto target_gain = Common::FixedPoint<50, 14>::from_base(params.early_gain) * EarlyDelayGains[params.early_mode][i];
+ if (target_gain.to_float() < 0.0f) target_gain = Common::FixedPoint<50, 14>(0.0f);
+ if (target_gain.to_float() > 1.0f) target_gain = Common::FixedPoint<50, 14>(1.0f);
+
+ state.early_gains[i] = state.early_gains[i] + (target_gain - state.early_gains[i]) / 4;
}
if (params.channel_count == 2) {
- state.early_gains[4] * 0.5f;
- state.early_gains[5] * 0.5f;
+ state.early_gains[4] *= Common::FixedPoint<50, 14>(0.5f);
+ state.early_gains[5] *= Common::FixedPoint<50, 14>(0.5f);
}
- auto pre_time{
- ((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int()};
- state.pre_delay_time = (std::min)(pre_time, state.pre_delay_line.sample_count_max);
+ int target_pre_time = ((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int();
+ if (target_pre_time < 0) target_pre_time = 0;
+ if (target_pre_time > state.pre_delay_line.sample_count_max) target_pre_time = state.pre_delay_line.sample_count_max;
+
+ int old_pre_time = state.pre_delay_time;
+ state.pre_delay_time = old_pre_time + (target_pre_time - old_pre_time) / 4;
if (!unk_initialized) {
unk_value = cos((1280.0f / sample_rate).to_float());
@@ -118,45 +132,64 @@ 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];
-
- 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].decay =
- 0.5999755859375f * (1.0f - Common::FixedPoint<50, 14>::from_base(params.colouration));
-
- auto a{(Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) +
- state.decay_delay_lines[i].sample_count_max) *
- -3};
- auto b{a / (Common::FixedPoint<50, 14>::from_base(params.decay_time) * sample_rate)};
- Common::FixedPoint<50, 14> c{0.0f};
- Common::FixedPoint<50, 14> d{0.0f};
- auto hf_decay_ratio{Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio)};
-
- if (hf_decay_ratio > 0.99493408203125f) {
+ int target_fdn_delay = (FdnDelayTimes[params.late_mode][i] * sample_rate).to_int();
+ if (target_fdn_delay < 0) target_fdn_delay = 0;
+ if (target_fdn_delay > state.fdn_delay_lines[i].sample_count_max) target_fdn_delay = state.fdn_delay_lines[i].sample_count_max;
+
+ int old_fdn = state.fdn_delay_lines[i].sample_count;
+ state.fdn_delay_lines[i].sample_count = old_fdn + (target_fdn_delay - old_fdn) / 4;
+ state.fdn_delay_lines[i].buffer_end = &state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
+
+ int target_decay_delay = (DecayDelayTimes[params.late_mode][i] * sample_rate).to_int();
+ if (target_decay_delay < 0) target_decay_delay = 0;
+ if (target_decay_delay > state.decay_delay_lines[i].sample_count_max) target_decay_delay = state.decay_delay_lines[i].sample_count_max;
+
+ int old_decay = state.decay_delay_lines[i].sample_count;
+ state.decay_delay_lines[i].sample_count = old_decay + (target_decay_delay - old_decay) / 4;
+ state.decay_delay_lines[i].buffer_end = &state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
+
+ auto colouration = Common::FixedPoint<50, 14>::from_base(params.colouration);
+ if (colouration.to_float() < 0.0f) colouration = Common::FixedPoint<50, 14>(0.0f);
+ if (colouration.to_float() > 1.0f) colouration = Common::FixedPoint<50, 14>(1.0f);
+
+ state.decay_delay_lines[i].decay = state.decay_delay_lines[i].decay + (0.5999755859375f * (1.0f - colouration) - state.decay_delay_lines[i].decay) / 4;
+
+ auto decay_time_fp = Common::FixedPoint<50, 14>::from_base(params.decay_time);
+ if (decay_time_fp.to_float() <= 0.0f) decay_time_fp = Common::FixedPoint<50, 14>(0.0001f);
+
+ auto a = (Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) + state.decay_delay_lines[i].sample_count_max) * -3;
+ auto b = a / (decay_time_fp * sample_rate);
+
+ auto hf_decay_ratio = Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio);
+ if (hf_decay_ratio.to_float() < 0.001f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.001f);
+ if (hf_decay_ratio.to_float() > 0.999f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.999f);
+
+ Common::FixedPoint<50, 14> c{0.0f}, d{0.0f};
+ if (hf_decay_ratio.to_float() > 0.9949f) {
c = 0.0f;
d = 1.0f;
} else {
- const auto e{
- pow_10(((((1.0f / hf_decay_ratio) - 1.0f) * 2) / 100 * (b / 10)).to_float())};
- const auto f{1.0f - e};
- const auto g{2.0f - (unk_value * e * 2)};
- const auto h{std::sqrt(std::pow(g.to_float(), 2.0f) - (std::pow(f, 2.0f) * 4))};
+ auto e = pow_10(((((1.0f / hf_decay_ratio.to_float()) - 1.0f) * 2) / 100 * (b / 10)).to_float());
+ if (e < 0.0001f) e = 0.0001f;
+ if (e > 1.0f) e = 1.0f;
+
+ auto f = 1.0f - e;
+ if (f < 0.0001f) f = 0.0001f;
+
+ auto g = 2.0f - (unk_value.to_float() * e * 2);
+
+ auto h_sq = g * g - f * f * 4;
+ if (h_sq < 0.0f) h_sq = 0.0f;
+
+ auto h = std::sqrt(h_sq);
c = (g - h) / (f * 2.0f);
d = 1.0f - c;
}
- state.hf_decay_prev_gain[i] = c;
- state.hf_decay_gain[i] = pow_10((b / 1000).to_float()) * d * 0.70709228515625f;
+ state.hf_decay_prev_gain[i] = state.hf_decay_prev_gain[i] + (c - state.hf_decay_prev_gain[i]) / 4;
+ state.hf_decay_gain[i] = state.hf_decay_gain[i] + (pow_10((b / 1000).to_float()) * d * 0.70709228515625f - state.hf_decay_gain[i]) / 4;
+
state.prev_feedback_output[i] = 0;
}
}
@@ -191,6 +224,8 @@ static void InitializeReverbEffect(const ReverbInfo::ParameterVersion2& params,
const auto center_delay_time{(5 * delay).to_uint_floor()};
state.center_delay_line.Initialize(center_delay_time, 1.0f);
+ UpdateReverbEffectParameter(params, state);
+
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
std::ranges::fill(state.fdn_delay_lines[i].buffer, 0);
std::ranges::fill(state.decay_delay_lines[i].buffer, 0);