From 55646657e17a99a9ddd3da4b552f3d9ac233037b Mon Sep 17 00:00:00 2001 From: MaranBr Date: Wed, 31 Dec 2025 14:15:06 +0100 Subject: [PATCH] [audio_core] Better biquad filter logic (#3235) This removes all redundant code and improves the logic of the biquad filter. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3235 Reviewed-by: Maufeat Co-authored-by: MaranBr Co-committed-by: MaranBr --- .../renderer/command/command_buffer.cpp | 30 ++++---- .../renderer/command/command_generator.cpp | 70 +++++++------------ 2 files changed, 38 insertions(+), 62 deletions(-) diff --git a/src/audio_core/renderer/command/command_buffer.cpp b/src/audio_core/renderer/command/command_buffer.cpp index 66f78f26b4..ca6a23679f 100644 --- a/src/audio_core/renderer/command/command_buffer.cpp +++ b/src/audio_core/renderer/command/command_buffer.cpp @@ -275,28 +275,24 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas const auto& parameter{ *reinterpret_cast(effect_info.GetParameter())}; - if (parameter.state <= EffectInfoBase::ParameterState::Updated && IsChannelCountValid(parameter.channel_count) && channel >= 0 && channel < parameter.channel_count) { - cmd.input = buffer_offset + parameter.inputs[channel]; - cmd.output = buffer_offset + parameter.outputs[channel]; - - // Convert float coefficients to Q2.14 fixed-point as expected by the legacy DSP path. - cmd.biquad.b[0] = ToQ14Clamped(parameter.b[0]); - cmd.biquad.b[1] = ToQ14Clamped(parameter.b[1]); - cmd.biquad.b[2] = ToQ14Clamped(parameter.b[2]); - cmd.biquad.a[0] = ToQ14Clamped(parameter.a[0]); - cmd.biquad.a[1] = ToQ14Clamped(parameter.a[1]); - } + cmd.input = buffer_offset + parameter.inputs[channel]; + cmd.output = buffer_offset + parameter.outputs[channel]; + + // Convert float coefficients to Q2.14 fixed-point as expected by the legacy DSP path. + cmd.biquad.b[0] = ToQ14Clamped(parameter.b[0]); + cmd.biquad.b[1] = ToQ14Clamped(parameter.b[1]); + cmd.biquad.b[2] = ToQ14Clamped(parameter.b[2]); + cmd.biquad.a[0] = ToQ14Clamped(parameter.a[0]); + cmd.biquad.a[1] = ToQ14Clamped(parameter.a[1]); } else { const auto& parameter{ *reinterpret_cast(effect_info.GetParameter())}; - if (IsChannelCountValid(parameter.channel_count) && channel >= 0 && channel < parameter.channel_count) { - cmd.input = buffer_offset + parameter.inputs[channel]; - cmd.output = buffer_offset + parameter.outputs[channel]; + cmd.input = buffer_offset + parameter.inputs[channel]; + cmd.output = buffer_offset + parameter.outputs[channel]; - cmd.biquad.b = parameter.b; - cmd.biquad.a = parameter.a; - } + cmd.biquad.b = parameter.b; + cmd.biquad.a = parameter.a; } // Effects always use the fixed-point coefficient path on the DSP. diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp index 29d7c11d16..44f2665b35 100644 --- a/src/audio_core/renderer/command/command_generator.cpp +++ b/src/audio_core/renderer/command/command_generator.cpp @@ -370,63 +370,43 @@ void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset if (render_context.behavior->IsEffectInfoVersion2Supported()) { const auto* parameter = reinterpret_cast(effect_info.GetParameter()); - if (!parameter) { - LOG_ERROR(Service_Audio, "Biquad filter parameter is null"); - return; - } - if (parameter->state <= EffectInfoBase::ParameterState::Updated) { - param_state = parameter->state; - channel_count = parameter->channel_count; - } + param_state = parameter->state; + channel_count = parameter->channel_count; } else { const auto* parameter = reinterpret_cast(effect_info.GetParameter()); - if (!parameter) { - LOG_ERROR(Service_Audio, "Biquad filter parameter is null"); - return; - } param_state = parameter->state; channel_count = parameter->channel_count; } - if (channel_count <= 0) { - return; - } + if (channel_count > 0 && param_state <= EffectInfoBase::ParameterState::Updated) { + if (effect_info.IsEnabled()) { + bool needs_init{false}; - if (effect_info.IsEnabled()) { - bool needs_init{false}; - - switch (param_state) { - case EffectInfoBase::ParameterState::Initialized: - needs_init = true; - break; - case EffectInfoBase::ParameterState::Updating: - case EffectInfoBase::ParameterState::Updated: - if (render_context.behavior->IsBiquadFilterEffectStateClearBugFixed()) { + switch (param_state) { + case EffectInfoBase::ParameterState::Initialized: + needs_init = true; + break; + case EffectInfoBase::ParameterState::Updating: + needs_init = !render_context.behavior->IsBiquadFilterEffectStateClearBugFixed(); + break; + case EffectInfoBase::ParameterState::Updated: needs_init = false; - } else { - needs_init = param_state == EffectInfoBase::ParameterState::Updating; + break; } - break; - default: - LOG_ERROR(Service_Audio, - "Invalid biquad parameter state {}, treating as uninitialized", - static_cast(param_state)); - needs_init = true; - break; - } - const bool use_float_processing = - render_context.behavior->UseBiquadFilterFloatProcessing(); + const bool use_float_processing = + render_context.behavior->UseBiquadFilterFloatProcessing(); - for (s8 channel = 0; channel < channel_count; channel++) { - command_buffer.GenerateBiquadFilterCommand(node_id, effect_info, buffer_offset, channel, - needs_init, use_float_processing); - } - } else { - for (s8 channel = 0; channel < channel_count; channel++) { - command_buffer.GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset, - channel); + for (s8 channel = 0; channel < channel_count; channel++) { + command_buffer.GenerateBiquadFilterCommand(node_id, effect_info, buffer_offset, channel, + needs_init, use_float_processing); + } + } else { + for (s8 channel = 0; channel < channel_count; channel++) { + command_buffer.GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset, + channel); + } } } }