diff options
| author | Maufeat <sahyno1996@gmail.com> | 2025-12-13 19:44:41 +0100 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2025-12-13 19:44:41 +0100 |
| commit | 06b83a58a6d60063cd5fad934aa7f3a75f0ce040 (patch) | |
| tree | 21f7d62f6940bd6cfe79ce60504884fb357ff1b6 /src/audio_core/renderer/command | |
| parent | 1e06c6f752c3b257783347a705dbcae293f618db (diff) | |
[audio] correct biquad filter v2 parameters (#3142)
We had the same struct for v1 and v2 - this was tested only with MP4, should output correct sounds now and boot it.
Co-authored-by: MaranBr <maranbr@outlook.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3142
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Maufeat <sahyno1996@gmail.com>
Co-committed-by: Maufeat <sahyno1996@gmail.com>
Diffstat (limited to 'src/audio_core/renderer/command')
| -rw-r--r-- | src/audio_core/renderer/command/command_buffer.cpp | 56 | ||||
| -rw-r--r-- | src/audio_core/renderer/command/command_generator.cpp | 54 |
2 files changed, 92 insertions, 18 deletions
diff --git a/src/audio_core/renderer/command/command_buffer.cpp b/src/audio_core/renderer/command/command_buffer.cpp index a0a574fc64..804aba438d 100644 --- a/src/audio_core/renderer/command/command_buffer.cpp +++ b/src/audio_core/renderer/command/command_buffer.cpp @@ -21,6 +21,15 @@ namespace AudioCore::Renderer { +namespace { +constexpr f32 BiquadParameterFixedScaleQ14 = 16384.0f; // 1 << 14 + +[[nodiscard]] inline s16 ToQ14Clamped(f32 v) { + const f32 scaled = std::clamp(v * BiquadParameterFixedScaleQ14, -32768.0f, 32767.0f); + return static_cast<s16>(scaled); +} +} // namespace + template <typename T, CommandId Id> T& CommandBuffer::GenerateStart(const s32 node_id) { if (size + sizeof(T) >= command_list.size_bytes()) { @@ -259,18 +268,42 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas const bool use_float_processing) { auto& cmd{GenerateStart<BiquadFilterCommand, CommandId::BiquadFilter>(node_id)}; - const auto& parameter{ - *reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())}; const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>( effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))}; - cmd.input = buffer_offset + parameter.inputs[channel]; - cmd.output = buffer_offset + parameter.outputs[channel]; + if (behavior->IsEffectInfoVersion2Supported()) { + const auto& p{ + *reinterpret_cast<BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter())}; - cmd.biquad.b = parameter.b; - cmd.biquad.a = parameter.a; + if (!IsChannelCountValid(p.channel_count) || channel < 0 || channel >= p.channel_count) { + return; + } + + cmd.input = buffer_offset + p.inputs[channel]; + cmd.output = buffer_offset + p.outputs[channel]; + + // Convert float coefficients to Q2.14 fixed-point as expected by the legacy DSP path. + cmd.biquad.b[0] = ToQ14Clamped(p.b[0]); + cmd.biquad.b[1] = ToQ14Clamped(p.b[1]); + cmd.biquad.b[2] = ToQ14Clamped(p.b[2]); + cmd.biquad.a[0] = ToQ14Clamped(p.a[0]); + cmd.biquad.a[1] = ToQ14Clamped(p.a[1]); + } else { + const auto& p{ + *reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())}; - // Effects use legacy fixed-point format + if (!IsChannelCountValid(p.channel_count) || channel < 0 || channel >= p.channel_count) { + return; + } + + cmd.input = buffer_offset + p.inputs[channel]; + cmd.output = buffer_offset + p.outputs[channel]; + + cmd.biquad.b = p.b; + cmd.biquad.a = p.a; + } + + // Effects always use the fixed-point coefficient path on the DSP. cmd.use_float_coefficients = false; cmd.state = memory_pool->Translate(CpuAddr(state), @@ -595,6 +628,15 @@ void CommandBuffer::GenerateCopyMixBufferCommand(const s32 node_id, EffectInfoBa const s16 buffer_offset, const s8 channel) { auto& cmd{GenerateStart<CopyMixBufferCommand, CommandId::CopyMixBuffer>(node_id)}; + if (behavior->IsEffectInfoVersion2Supported()) { + const auto& parameter_v2{ + *reinterpret_cast<BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter())}; + cmd.input_index = buffer_offset + parameter_v2.inputs[channel]; + cmd.output_index = buffer_offset + parameter_v2.outputs[channel]; + GenerateEnd<CopyMixBufferCommand>(cmd); + return; + } + const auto& parameter{ *reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())}; cmd.input_index = buffer_offset + parameter.inputs[channel]; diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp index f97db5899e..bec6abbaf9 100644 --- a/src/audio_core/renderer/command/command_generator.cpp +++ b/src/audio_core/renderer/command/command_generator.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -361,12 +364,37 @@ void CommandGenerator::GenerateAuxCommand(const s16 buffer_offset, EffectInfoBas void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset, EffectInfoBase& effect_info, const s32 node_id) { - const auto& parameter{ - *reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())}; + EffectInfoBase::ParameterState param_state{}; + s8 channel_count = 0; + + if (render_context.behavior->IsEffectInfoVersion2Supported()) { + const auto* parameter = + reinterpret_cast<const BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter()); + if (!parameter) { + LOG_ERROR(Service_Audio, "Biquad filter parameter is null"); + return; + } + param_state = parameter->state; + channel_count = parameter->channel_count; + } else { + const auto* parameter = + reinterpret_cast<const BiquadFilterInfo::ParameterVersion1*>(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 (effect_info.IsEnabled()) { bool needs_init{false}; - switch (parameter.state) { + switch (param_state) { case EffectInfoBase::ParameterState::Initialized: needs_init = true; break; @@ -375,22 +403,26 @@ void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset if (render_context.behavior->IsBiquadFilterEffectStateClearBugFixed()) { needs_init = false; } else { - needs_init = parameter.state == EffectInfoBase::ParameterState::Updating; + needs_init = param_state == EffectInfoBase::ParameterState::Updating; } break; default: - LOG_ERROR(Service_Audio, "Invalid biquad parameter state {}", - static_cast<u32>(parameter.state)); + LOG_ERROR(Service_Audio, + "Invalid biquad parameter state {}, treating as uninitialized", + static_cast<u32>(param_state)); + needs_init = true; break; } - for (s8 channel = 0; channel < parameter.channel_count; channel++) { - command_buffer.GenerateBiquadFilterCommand( - node_id, effect_info, buffer_offset, channel, needs_init, - 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 < parameter.channel_count; channel++) { + for (s8 channel = 0; channel < channel_count; channel++) { command_buffer.GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset, channel); } |
