diff options
| -rw-r--r-- | src/audio_core/algorithm/interpolate.cpp | 54 | ||||
| -rw-r--r-- | src/audio_core/algorithm/interpolate.h | 7 |
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 | ||
| 15 | namespace AudioCore { | 16 | namespace AudioCore { |
| 16 | 17 | ||
| 17 | constexpr std::array<s16, 512> curve_lut0 = { | 18 | constexpr 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 | ||
| 59 | constexpr std::array<s16, 512> curve_lut1 = { | 60 | constexpr 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 | ||
| 101 | constexpr std::array<s16, 512> curve_lut2 = { | 102 | constexpr 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 | ||
| 11 | namespace AudioCore { | 12 | namespace AudioCore { |
| 12 | 13 | ||
| 13 | struct InterpolationState { | 14 | struct 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. |