summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2020-02-28 16:07:10 -0500
committerGravatar GitHub2020-02-28 16:07:10 -0500
commitca7618684ce4be87673653e31631cafd487d7176 (patch)
tree9bdfe64cea8daf6debcbaee53425e3f07e26502b
parentMerge pull request #3470 from bunnei/fix-smash-srgb (diff)
parentaudio_core: interpolate: Improvements to fix audio crackling. (diff)
downloadyuzu-ca7618684ce4be87673653e31631cafd487d7176.tar.gz
yuzu-ca7618684ce4be87673653e31631cafd487d7176.tar.xz
yuzu-ca7618684ce4be87673653e31631cafd487d7176.zip
Merge pull request #3448 from bunnei/fix-audio-interp-2
audio_core: interpolate: Improvements to fix audio crackling.
Diffstat (limited to '')
-rw-r--r--src/audio_core/algorithm/interpolate.cpp54
-rw-r--r--src/audio_core/algorithm/interpolate.h7
2 files changed, 38 insertions, 23 deletions
diff --git a/src/audio_core/algorithm/interpolate.cpp b/src/audio_core/algorithm/interpolate.cpp
index a58f24169..49ab9d3e1 100644
--- a/src/audio_core/algorithm/interpolate.cpp
+++ b/src/audio_core/algorithm/interpolate.cpp
@@ -8,13 +8,14 @@
8#include <climits> 8#include <climits>
9#include <cmath> 9#include <cmath>
10#include <vector> 10#include <vector>
11
11#include "audio_core/algorithm/interpolate.h" 12#include "audio_core/algorithm/interpolate.h"
12#include "common/common_types.h" 13#include "common/common_types.h"
13#include "common/logging/log.h" 14#include "common/logging/log.h"
14 15
15namespace AudioCore { 16namespace AudioCore {
16 17
17constexpr std::array<s16, 512> curve_lut0 = { 18constexpr std::array<s16, 512> curve_lut0{
18 6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239, 19 6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239,
19 19412, 7093, 22, 6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377, 20 19412, 7093, 22, 6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377,
20 7472, 41, 5773, 19361, 7600, 48, 5659, 19342, 7728, 55, 5546, 19321, 7857, 21 7472, 41, 5773, 19361, 7600, 48, 5659, 19342, 7728, 55, 5546, 19321, 7857,
@@ -56,7 +57,7 @@ constexpr std::array<s16, 512> curve_lut0 = {
56 19403, 6121, 22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 57 19403, 6121, 22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424,
57 6479, 3, 6722, 19426, 6600}; 58 6479, 3, 6722, 19426, 6600};
58 59
59constexpr std::array<s16, 512> curve_lut1 = { 60constexpr std::array<s16, 512> curve_lut1{
60 -68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450, 61 -68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450,
61 32586, 512, -36, -568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454, 62 32586, 512, -36, -568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454,
62 1000, -69, -891, 32393, 1174, -80, -990, 32323, 1352, -92, -1084, 32244, 1536, 63 1000, -69, -891, 32393, 1174, -80, -990, 32323, 1352, -92, -1084, 32244, 1536,
@@ -98,7 +99,7 @@ constexpr std::array<s16, 512> curve_lut1 = {
98 32551, -568, -36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, 99 32551, -568, -36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630,
99 -200, -5, 69, 32639, -68}; 100 -200, -5, 69, 32639, -68};
100 101
101constexpr std::array<s16, 512> curve_lut2 = { 102constexpr std::array<s16, 512> curve_lut2{
102 3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811, 103 3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811,
103 26253, 3751, -42, 2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169, 104 26253, 3751, -42, 2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169,
104 4199, -54, 2338, 26130, 4354, -58, 2227, 26085, 4512, -63, 2120, 26035, 4673, 105 4199, -54, 2338, 26130, 4354, -58, 2227, 26085, 4512, -63, 2120, 26035, 4673,
@@ -146,10 +147,10 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
146 147
147 if (ratio <= 0) { 148 if (ratio <= 0) {
148 LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio); 149 LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
149 ratio = 1.0; 150 return input;
150 } 151 }
151 152
152 const int step = static_cast<int>(ratio * 0x8000); 153 const s32 step{static_cast<s32>(ratio * 0x8000)};
153 const std::array<s16, 512>& lut = [step] { 154 const std::array<s16, 512>& lut = [step] {
154 if (step > 0xaaaa) { 155 if (step > 0xaaaa) {
155 return curve_lut0; 156 return curve_lut0;
@@ -160,28 +161,37 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
160 return curve_lut2; 161 return curve_lut2;
161 }(); 162 }();
162 163
163 std::vector<s16> output(static_cast<std::size_t>(input.size() / ratio)); 164 const std::size_t num_frames{input.size() / 2};
164 int in_offset = 0; 165
165 for (std::size_t out_offset = 0; out_offset < output.size(); out_offset += 2) { 166 std::vector<s16> output;
166 const int lut_index = (state.fraction >> 8) * 4; 167 output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
167 168
168 const int l = input[(in_offset + 0) * 2 + 0] * lut[lut_index + 0] + 169 for (std::size_t frame{}; frame < num_frames; ++frame) {
169 input[(in_offset + 1) * 2 + 0] * lut[lut_index + 1] + 170 const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
170 input[(in_offset + 2) * 2 + 0] * lut[lut_index + 2] +
171 input[(in_offset + 3) * 2 + 0] * lut[lut_index + 3];
172 171
173 const int r = input[(in_offset + 0) * 2 + 1] * lut[lut_index + 0] + 172 std::rotate(state.history.begin(), state.history.end() - 1, state.history.end());
174 input[(in_offset + 1) * 2 + 1] * lut[lut_index + 1] + 173 state.history[0][0] = input[frame * 2 + 0];
175 input[(in_offset + 2) * 2 + 1] * lut[lut_index + 2] + 174 state.history[0][1] = input[frame * 2 + 1];
176 input[(in_offset + 3) * 2 + 1] * lut[lut_index + 3];
177 175
178 const int new_offset = state.fraction + step; 176 while (state.position <= 1.0) {
177 const s32 left{state.history[0][0] * lut[lut_index + 0] +
178 state.history[1][0] * lut[lut_index + 1] +
179 state.history[2][0] * lut[lut_index + 2] +
180 state.history[3][0] * lut[lut_index + 3]};
181 const s32 right{state.history[0][1] * lut[lut_index + 0] +
182 state.history[1][1] * lut[lut_index + 1] +
183 state.history[2][1] * lut[lut_index + 2] +
184 state.history[3][1] * lut[lut_index + 3]};
185 const s32 new_offset{state.fraction + step};
179 186
180 in_offset += new_offset >> 15; 187 state.fraction = new_offset & 0x7fff;
181 state.fraction = new_offset & 0x7fff;
182 188
183 output[out_offset + 0] = static_cast<s16>(std::clamp(l >> 15, SHRT_MIN, SHRT_MAX)); 189 output.emplace_back(static_cast<s16>(std::clamp(left >> 15, SHRT_MIN, SHRT_MAX)));
184 output[out_offset + 1] = static_cast<s16>(std::clamp(r >> 15, SHRT_MIN, SHRT_MAX)); 190 output.emplace_back(static_cast<s16>(std::clamp(right >> 15, SHRT_MIN, SHRT_MAX)));
191
192 state.position += ratio;
193 }
194 state.position -= 1.0;
185 } 195 }
186 196
187 return output; 197 return output;
diff --git a/src/audio_core/algorithm/interpolate.h b/src/audio_core/algorithm/interpolate.h
index 1b9831a75..ab1a31754 100644
--- a/src/audio_core/algorithm/interpolate.h
+++ b/src/audio_core/algorithm/interpolate.h
@@ -6,12 +6,17 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9
9#include "common/common_types.h" 10#include "common/common_types.h"
10 11
11namespace AudioCore { 12namespace AudioCore {
12 13
13struct InterpolationState { 14struct InterpolationState {
14 int fraction = 0; 15 static constexpr std::size_t taps{4};
16 static constexpr std::size_t history_size{taps * 2 - 1};
17 std::array<std::array<s16, 2>, history_size> history{};
18 double position{};
19 s32 fraction{};
15}; 20};
16 21
17/// Interpolates input signal to produce output signal. 22/// Interpolates input signal to produce output signal.