summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar liamwhite2023-02-11 10:28:42 -0500
committerGravatar GitHub2023-02-11 10:28:42 -0500
commit89c09d639ae92d0df40c68a962fe0683f1a1cd21 (patch)
tree8bcaac4af953518fd3a72c6c07b3048ec884ba13
parentMerge pull request #9744 from behunin/quick-release (diff)
parentbiquad_filter: Clamp f64 in ApplyBiquadFilterFloat (diff)
downloadyuzu-89c09d639ae92d0df40c68a962fe0683f1a1cd21.tar.gz
yuzu-89c09d639ae92d0df40c68a962fe0683f1a1cd21.tar.xz
yuzu-89c09d639ae92d0df40c68a962fe0683f1a1cd21.zip
Merge pull request #9768 from merryhime/biquad-rounding
biquad_filter: Fix rounding in ApplyBiquadFilterInt
-rw-r--r--src/audio_core/renderer/command/effect/biquad_filter.cpp38
-rw-r--r--src/audio_core/renderer/voice/voice_state.h8
2 files changed, 19 insertions, 27 deletions
diff --git a/src/audio_core/renderer/command/effect/biquad_filter.cpp b/src/audio_core/renderer/command/effect/biquad_filter.cpp
index edb30ce72..dea6423dc 100644
--- a/src/audio_core/renderer/command/effect/biquad_filter.cpp
+++ b/src/audio_core/renderer/command/effect/biquad_filter.cpp
@@ -4,6 +4,7 @@
4#include "audio_core/renderer/adsp/command_list_processor.h" 4#include "audio_core/renderer/adsp/command_list_processor.h"
5#include "audio_core/renderer/command/effect/biquad_filter.h" 5#include "audio_core/renderer/command/effect/biquad_filter.h"
6#include "audio_core/renderer/voice/voice_state.h" 6#include "audio_core/renderer/voice/voice_state.h"
7#include "common/bit_cast.h"
7 8
8namespace AudioCore::AudioRenderer { 9namespace AudioCore::AudioRenderer {
9/** 10/**
@@ -19,21 +20,21 @@ namespace AudioCore::AudioRenderer {
19void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input, 20void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
20 std::array<s16, 3>& b_, std::array<s16, 2>& a_, 21 std::array<s16, 3>& b_, std::array<s16, 2>& a_,
21 VoiceState::BiquadFilterState& state, const u32 sample_count) { 22 VoiceState::BiquadFilterState& state, const u32 sample_count) {
22 constexpr s64 min{std::numeric_limits<s32>::min()}; 23 constexpr f64 min{std::numeric_limits<s32>::min()};
23 constexpr s64 max{std::numeric_limits<s32>::max()}; 24 constexpr f64 max{std::numeric_limits<s32>::max()};
24 std::array<f64, 3> b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(), 25 std::array<f64, 3> b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(),
25 Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(), 26 Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(),
26 Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()}; 27 Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()};
27 std::array<f64, 2> a{Common::FixedPoint<50, 14>::from_base(a_[0]).to_double(), 28 std::array<f64, 2> a{Common::FixedPoint<50, 14>::from_base(a_[0]).to_double(),
28 Common::FixedPoint<50, 14>::from_base(a_[1]).to_double()}; 29 Common::FixedPoint<50, 14>::from_base(a_[1]).to_double()};
29 std::array<f64, 4> s{state.s0.to_double(), state.s1.to_double(), state.s2.to_double(), 30 std::array<f64, 4> s{Common::BitCast<f64>(state.s0), Common::BitCast<f64>(state.s1),
30 state.s3.to_double()}; 31 Common::BitCast<f64>(state.s2), Common::BitCast<f64>(state.s3)};
31 32
32 for (u32 i = 0; i < sample_count; i++) { 33 for (u32 i = 0; i < sample_count; i++) {
33 f64 in_sample{static_cast<f64>(input[i])}; 34 f64 in_sample{static_cast<f64>(input[i])};
34 auto sample{in_sample * b[0] + s[0] * b[1] + s[1] * b[2] + s[2] * a[0] + s[3] * a[1]}; 35 auto sample{in_sample * b[0] + s[0] * b[1] + s[1] * b[2] + s[2] * a[0] + s[3] * a[1]};
35 36
36 output[i] = static_cast<s32>(std::clamp(static_cast<s64>(sample), min, max)); 37 output[i] = static_cast<s32>(std::clamp(sample, min, max));
37 38
38 s[1] = s[0]; 39 s[1] = s[0];
39 s[0] = in_sample; 40 s[0] = in_sample;
@@ -41,10 +42,10 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
41 s[2] = sample; 42 s[2] = sample;
42 } 43 }
43 44
44 state.s0 = s[0]; 45 state.s0 = Common::BitCast<s64>(s[0]);
45 state.s1 = s[1]; 46 state.s1 = Common::BitCast<s64>(s[1]);
46 state.s2 = s[2]; 47 state.s2 = Common::BitCast<s64>(s[2]);
47 state.s3 = s[3]; 48 state.s3 = Common::BitCast<s64>(s[3]);
48} 49}
49 50
50/** 51/**
@@ -58,29 +59,20 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
58 * @param sample_count - Number of samples to process. 59 * @param sample_count - Number of samples to process.
59 */ 60 */
60static void ApplyBiquadFilterInt(std::span<s32> output, std::span<const s32> input, 61static void ApplyBiquadFilterInt(std::span<s32> output, std::span<const s32> input,
61 std::array<s16, 3>& b_, std::array<s16, 2>& a_, 62 std::array<s16, 3>& b, std::array<s16, 2>& a,
62 VoiceState::BiquadFilterState& state, const u32 sample_count) { 63 VoiceState::BiquadFilterState& state, const u32 sample_count) {
63 constexpr s64 min{std::numeric_limits<s32>::min()}; 64 constexpr s64 min{std::numeric_limits<s32>::min()};
64 constexpr s64 max{std::numeric_limits<s32>::max()}; 65 constexpr s64 max{std::numeric_limits<s32>::max()};
65 std::array<Common::FixedPoint<50, 14>, 3> b{
66 Common::FixedPoint<50, 14>::from_base(b_[0]),
67 Common::FixedPoint<50, 14>::from_base(b_[1]),
68 Common::FixedPoint<50, 14>::from_base(b_[2]),
69 };
70 std::array<Common::FixedPoint<50, 14>, 3> a{
71 Common::FixedPoint<50, 14>::from_base(a_[0]),
72 Common::FixedPoint<50, 14>::from_base(a_[1]),
73 };
74 66
75 for (u32 i = 0; i < sample_count; i++) { 67 for (u32 i = 0; i < sample_count; i++) {
76 s64 in_sample{input[i]}; 68 const s64 in_sample{input[i]};
77 auto sample{in_sample * b[0] + state.s0}; 69 const s64 sample{in_sample * b[0] + state.s0};
78 const auto out_sample{std::clamp(sample.to_long(), min, max)}; 70 const s64 out_sample{std::clamp<s64>((sample + (1 << 13)) >> 14, min, max)};
79 71
80 output[i] = static_cast<s32>(out_sample); 72 output[i] = static_cast<s32>(out_sample);
81 73
82 state.s0 = state.s1 + b[1] * in_sample + a[0] * out_sample; 74 state.s0 = state.s1 + b[1] * in_sample + a[0] * out_sample;
83 state.s1 = 0 + b[2] * in_sample + a[1] * out_sample; 75 state.s1 = b[2] * in_sample + a[1] * out_sample;
84 } 76 }
85} 77}
86 78
diff --git a/src/audio_core/renderer/voice/voice_state.h b/src/audio_core/renderer/voice/voice_state.h
index d5497e2fb..ce947233f 100644
--- a/src/audio_core/renderer/voice/voice_state.h
+++ b/src/audio_core/renderer/voice/voice_state.h
@@ -19,10 +19,10 @@ struct VoiceState {
19 * State of the voice's biquad filter. 19 * State of the voice's biquad filter.
20 */ 20 */
21 struct BiquadFilterState { 21 struct BiquadFilterState {
22 Common::FixedPoint<50, 14> s0; 22 s64 s0;
23 Common::FixedPoint<50, 14> s1; 23 s64 s1;
24 Common::FixedPoint<50, 14> s2; 24 s64 s2;
25 Common::FixedPoint<50, 14> s3; 25 s64 s3;
26 }; 26 };
27 27
28 /** 28 /**