Browse Source

fix for older games, use correct struct

pull/3142/head
Maufeat 1 week ago
parent
commit
d54d0e5f35
  1. 64
      src/audio_core/renderer/command/command_buffer.cpp
  2. 55
      src/audio_core/renderer/command/command_generator.cpp
  3. 20
      src/audio_core/renderer/effect/biquad_filter.cpp
  4. 14
      src/audio_core/renderer/effect/biquad_filter.h

64
src/audio_core/renderer/command/command_buffer.cpp

@ -21,6 +21,15 @@
namespace AudioCore::Renderer { 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> template <typename T, CommandId Id>
T& CommandBuffer::GenerateStart(const s32 node_id) { T& CommandBuffer::GenerateStart(const s32 node_id) {
if (size + sizeof(T) >= command_list.size_bytes()) { if (size + sizeof(T) >= command_list.size_bytes()) {
@ -257,49 +266,44 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas
const s16 buffer_offset, const s8 channel, const s16 buffer_offset, const s8 channel,
const bool needs_init, const bool needs_init,
const bool use_float_processing) { const bool use_float_processing) {
if (behavior->IsEffectInfoVersion2Supported()) {
auto& cmd{GenerateStart<BiquadFilterCommand, CommandId::BiquadFilter>(node_id)}; auto& cmd{GenerateStart<BiquadFilterCommand, CommandId::BiquadFilter>(node_id)};
const auto& parameter_v2{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter())};
if (!IsChannelCountValid(parameter_v2.channel_count) || channel < 0 ||
channel >= parameter_v2.channel_count) {
return;
}
if (!parameter_v2.enable) {
// Effect disabled at parameter level: copy input -> output for this channel
GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset, channel);
return;
}
const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>( const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(
effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))}; effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))};
cmd.input = buffer_offset + parameter_v2.inputs[channel];
cmd.output = buffer_offset + parameter_v2.outputs[channel];
cmd.biquad_float.numerator = parameter_v2.b;
cmd.biquad_float.denominator = parameter_v2.a;
cmd.use_float_coefficients = true;
cmd.state = memory_pool->Translate(CpuAddr(state), sizeof(VoiceState::BiquadFilterState));
cmd.needs_init = needs_init;
cmd.use_float_processing = use_float_processing;
if (behavior->IsEffectInfoVersion2Supported()) {
const auto& p{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter())};
GenerateEnd<BiquadFilterCommand>(cmd);
if (!IsChannelCountValid(p.channel_count) || channel < 0 || channel >= p.channel_count) {
return; return;
} }
auto& cmd{GenerateStart<BiquadFilterCommand, CommandId::BiquadFilter>(node_id)};
cmd.input = buffer_offset + p.inputs[channel];
cmd.output = buffer_offset + p.outputs[channel];
const auto& parameter{
// 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())}; *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 (!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 = parameter.b;
cmd.biquad.a = parameter.a;
cmd.biquad.b = p.b;
cmd.biquad.a = p.a;
}
// Effects use legacy fixed-point format
// Effects always use the fixed-point coefficient path on the DSP.
cmd.use_float_coefficients = false; cmd.use_float_coefficients = false;
cmd.state = memory_pool->Translate(CpuAddr(state), cmd.state = memory_pool->Translate(CpuAddr(state),

55
src/audio_core/renderer/command/command_generator.cpp

@ -364,32 +364,37 @@ void CommandGenerator::GenerateAuxCommand(const s16 buffer_offset, EffectInfoBas
void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset, void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset,
EffectInfoBase& effect_info, EffectInfoBase& effect_info,
const s32 node_id) { const s32 node_id) {
EffectInfoBase::ParameterState param_state{};
s8 channel_count = 0;
if (render_context.behavior->IsEffectInfoVersion2Supported()) { if (render_context.behavior->IsEffectInfoVersion2Supported()) {
const auto& parameter_v2{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion2*>(effect_info.GetParameter())};
const bool needs_init = false;
const bool use_float_processing = render_context.behavior->UseBiquadFilterFloatProcessing();
const s8 channels = parameter_v2.channel_count > 0 ? parameter_v2.channel_count : 2;
if (effect_info.IsEnabled()) {
for (s8 channel = 0; channel < channels; channel++) {
command_buffer.GenerateBiquadFilterCommand(
node_id, effect_info, buffer_offset, channel, needs_init, use_float_processing);
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 { } else {
for (s8 channel = 0; channel < channels; channel++) {
command_buffer.GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset,
channel);
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; return;
} }
const auto& parameter{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())};
if (effect_info.IsEnabled()) { if (effect_info.IsEnabled()) {
bool needs_init{false}; bool needs_init{false};
switch (parameter.state) {
switch (param_state) {
case EffectInfoBase::ParameterState::Initialized: case EffectInfoBase::ParameterState::Initialized:
needs_init = true; needs_init = true;
break; break;
@ -398,22 +403,26 @@ void CommandGenerator::GenerateBiquadFilterEffectCommand(const s16 buffer_offset
if (render_context.behavior->IsBiquadFilterEffectStateClearBugFixed()) { if (render_context.behavior->IsBiquadFilterEffectStateClearBugFixed()) {
needs_init = false; needs_init = false;
} else { } else {
needs_init = parameter.state == EffectInfoBase::ParameterState::Updating;
needs_init = param_state == EffectInfoBase::ParameterState::Updating;
} }
break; break;
default: 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; 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 { } 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, command_buffer.GenerateCopyMixBufferCommand(node_id, effect_info, buffer_offset,
channel); channel);
} }

20
src/audio_core/renderer/effect/biquad_filter.cpp

@ -34,14 +34,22 @@ void BiquadFilterInfo::Update(BehaviorInfo::ErrorInfo& error_info,
} }
void BiquadFilterInfo::UpdateForCommandGeneration() { void BiquadFilterInfo::UpdateForCommandGeneration() {
if (enabled) {
usage_state = UsageState::Enabled;
usage_state = enabled ? UsageState::Enabled : UsageState::Disabled;
auto* params_v1 = reinterpret_cast<ParameterVersion1*>(parameter.data());
auto* params_v2 = reinterpret_cast<ParameterVersion2*>(parameter.data());
const auto raw_state_v1 = static_cast<u8>(params_v1->state);
const auto raw_state_v2 = static_cast<u8>(params_v2->state);
if (raw_state_v1 <= static_cast<u8>(ParameterState::Updated)) {
params_v1->state = ParameterState::Updated;
} else if (raw_state_v2 <= static_cast<u8>(ParameterState::Updated)) {
params_v2->state = ParameterState::Updated;
} else { } else {
usage_state = UsageState::Disabled;
params_v1->state = ParameterState::Updated;
params_v2->state = ParameterState::Updated;
} }
auto params{reinterpret_cast<ParameterVersion1*>(parameter.data())};
params->state = ParameterState::Updated;
} }
void BiquadFilterInfo::InitializeResultState(EffectResultState& result_state) {} void BiquadFilterInfo::InitializeResultState(EffectResultState& result_state) {}

14
src/audio_core/renderer/effect/biquad_filter.h

@ -28,12 +28,14 @@ public:
"BiquadFilterInfo::ParameterVersion1 has the wrong size!"); "BiquadFilterInfo::ParameterVersion1 has the wrong size!");
struct ParameterVersion2 { struct ParameterVersion2 {
bool enable;
s8 channel_count;
s8 inputs[MaxChannels];
s8 outputs[MaxChannels];
std::array<f32, 3> b;
std::array<f32, 2> a;
/* 0x00 */ std::array<s8, MaxChannels> inputs;
/* 0x06 */ std::array<s8, MaxChannels> outputs;
/* 0x0C */ u32 padding;
/* 0x10 */ std::array<f32, 3> b;
/* 0x1C */ std::array<f32, 2> a;
/* 0x24 */ s8 channel_count;
/* 0x25 */ ParameterState state;
/* 0x26 */ u16 reserved;
}; };
static_assert(sizeof(ParameterVersion2) <= sizeof(EffectInfoBase::InParameterVersion2), static_assert(sizeof(ParameterVersion2) <= sizeof(EffectInfoBase::InParameterVersion2),
"BiquadFilterInfo::ParameterVersion2 has the wrong size!"); "BiquadFilterInfo::ParameterVersion2 has the wrong size!");

Loading…
Cancel
Save