diff options
| author | 2017-08-03 12:22:51 +0100 | |
|---|---|---|
| committer | 2017-08-28 10:54:41 +0100 | |
| commit | 933508e2a2f7923cebc15d679b78933df8fb9ee5 (patch) | |
| tree | e49faeb30929c03c5490d8ae507ec907060c1068 /src/audio_core/interpolate.cpp | |
| parent | Merge pull request #2850 from j-selby/fix_invalid_paths (diff) | |
| download | yuzu-933508e2a2f7923cebc15d679b78933df8fb9ee5.tar.gz yuzu-933508e2a2f7923cebc15d679b78933df8fb9ee5.tar.xz yuzu-933508e2a2f7923cebc15d679b78933df8fb9ee5.zip | |
interpolate: Interpolate on a frame-by-frame basis
Diffstat (limited to 'src/audio_core/interpolate.cpp')
| -rw-r--r-- | src/audio_core/interpolate.cpp | 86 |
1 files changed, 38 insertions, 48 deletions
diff --git a/src/audio_core/interpolate.cpp b/src/audio_core/interpolate.cpp index 8a5d4181a..16e68bc5c 100644 --- a/src/audio_core/interpolate.cpp +++ b/src/audio_core/interpolate.cpp | |||
| @@ -13,74 +13,64 @@ namespace AudioInterp { | |||
| 13 | constexpr u64 scale_factor = 1 << 24; | 13 | constexpr u64 scale_factor = 1 << 24; |
| 14 | constexpr u64 scale_mask = scale_factor - 1; | 14 | constexpr u64 scale_mask = scale_factor - 1; |
| 15 | 15 | ||
| 16 | /// Here we step over the input in steps of rate_multiplier, until we consume all of the input. | 16 | /// Here we step over the input in steps of rate, until we consume all of the input. |
| 17 | /// Three adjacent samples are passed to fn each step. | 17 | /// Three adjacent samples are passed to fn each step. |
| 18 | template <typename Function> | 18 | template <typename Function> |
| 19 | static StereoBuffer16 StepOverSamples(State& state, const StereoBuffer16& input, | 19 | static void StepOverSamples(State& state, StereoBuffer16& input, float rate, |
| 20 | float rate_multiplier, Function fn) { | 20 | DSP::HLE::StereoFrame16& output, size_t& outputi, Function fn) { |
| 21 | ASSERT(rate_multiplier > 0); | 21 | ASSERT(rate > 0); |
| 22 | 22 | ||
| 23 | if (input.size() < 2) | 23 | if (input.empty()) |
| 24 | return {}; | 24 | return; |
| 25 | 25 | ||
| 26 | StereoBuffer16 output; | 26 | input.insert(input.begin(), {state.xn2, state.xn1}); |
| 27 | output.reserve(static_cast<size_t>(input.size() / rate_multiplier)); | ||
| 28 | 27 | ||
| 29 | u64 step_size = static_cast<u64>(rate_multiplier * scale_factor); | 28 | const u64 step_size = static_cast<u64>(rate * scale_factor); |
| 29 | u64 fposition = state.fposition; | ||
| 30 | size_t inputi = 0; | ||
| 30 | 31 | ||
| 31 | u64 fposition = 0; | 32 | while (outputi < output.size()) { |
| 32 | const u64 max_fposition = input.size() * scale_factor; | 33 | inputi = static_cast<size_t>(fposition / scale_factor); |
| 33 | 34 | ||
| 34 | while (fposition < 1 * scale_factor) { | 35 | if (inputi + 2 >= input.size()) { |
| 35 | u64 fraction = fposition & scale_mask; | 36 | inputi = input.size() - 2; |
| 36 | 37 | break; | |
| 37 | output.push_back(fn(fraction, state.xn2, state.xn1, input[0])); | 38 | } |
| 38 | |||
| 39 | fposition += step_size; | ||
| 40 | } | ||
| 41 | |||
| 42 | while (fposition < 2 * scale_factor) { | ||
| 43 | u64 fraction = fposition & scale_mask; | ||
| 44 | |||
| 45 | output.push_back(fn(fraction, state.xn1, input[0], input[1])); | ||
| 46 | |||
| 47 | fposition += step_size; | ||
| 48 | } | ||
| 49 | 39 | ||
| 50 | while (fposition < max_fposition) { | ||
| 51 | u64 fraction = fposition & scale_mask; | 40 | u64 fraction = fposition & scale_mask; |
| 52 | 41 | output[outputi++] = fn(fraction, input[inputi], input[inputi + 1], input[inputi + 2]); | |
| 53 | size_t index = static_cast<size_t>(fposition / scale_factor); | ||
| 54 | output.push_back(fn(fraction, input[index - 2], input[index - 1], input[index])); | ||
| 55 | 42 | ||
| 56 | fposition += step_size; | 43 | fposition += step_size; |
| 57 | } | 44 | } |
| 58 | 45 | ||
| 59 | state.xn2 = input[input.size() - 2]; | 46 | state.xn2 = input[inputi]; |
| 60 | state.xn1 = input[input.size() - 1]; | 47 | state.xn1 = input[inputi + 1]; |
| 48 | state.fposition = fposition - inputi * scale_factor; | ||
| 61 | 49 | ||
| 62 | return output; | 50 | input.erase(input.begin(), input.begin() + inputi + 2); |
| 63 | } | 51 | } |
| 64 | 52 | ||
| 65 | StereoBuffer16 None(State& state, const StereoBuffer16& input, float rate_multiplier) { | 53 | void None(State& state, StereoBuffer16& input, float rate, DSP::HLE::StereoFrame16& output, |
| 66 | return StepOverSamples( | 54 | size_t& outputi) { |
| 67 | state, input, rate_multiplier, | 55 | StepOverSamples( |
| 56 | state, input, rate, output, outputi, | ||
| 68 | [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { return x0; }); | 57 | [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { return x0; }); |
| 69 | } | 58 | } |
| 70 | 59 | ||
| 71 | StereoBuffer16 Linear(State& state, const StereoBuffer16& input, float rate_multiplier) { | 60 | void Linear(State& state, StereoBuffer16& input, float rate, DSP::HLE::StereoFrame16& output, |
| 61 | size_t& outputi) { | ||
| 72 | // Note on accuracy: Some values that this produces are +/- 1 from the actual firmware. | 62 | // Note on accuracy: Some values that this produces are +/- 1 from the actual firmware. |
| 73 | return StepOverSamples(state, input, rate_multiplier, | 63 | StepOverSamples(state, input, rate, output, outputi, |
| 74 | [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { | 64 | [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { |
| 75 | // This is a saturated subtraction. (Verified by black-box fuzzing.) | 65 | // This is a saturated subtraction. (Verified by black-box fuzzing.) |
| 76 | s64 delta0 = MathUtil::Clamp<s64>(x1[0] - x0[0], -32768, 32767); | 66 | s64 delta0 = MathUtil::Clamp<s64>(x1[0] - x0[0], -32768, 32767); |
| 77 | s64 delta1 = MathUtil::Clamp<s64>(x1[1] - x0[1], -32768, 32767); | 67 | s64 delta1 = MathUtil::Clamp<s64>(x1[1] - x0[1], -32768, 32767); |
| 78 | 68 | ||
| 79 | return std::array<s16, 2>{ | 69 | return std::array<s16, 2>{ |
| 80 | static_cast<s16>(x0[0] + fraction * delta0 / scale_factor), | 70 | static_cast<s16>(x0[0] + fraction * delta0 / scale_factor), |
| 81 | static_cast<s16>(x0[1] + fraction * delta1 / scale_factor), | 71 | static_cast<s16>(x0[1] + fraction * delta1 / scale_factor), |
| 82 | }; | 72 | }; |
| 83 | }); | 73 | }); |
| 84 | } | 74 | } |
| 85 | 75 | ||
| 86 | } // namespace AudioInterp | 76 | } // namespace AudioInterp |