| |
| |
| |
|
|
| #include <algorithm> |
| #include "audio_core/interpolate.h" |
| #include "common/assert.h" |
|
|
| namespace AudioCore::AudioInterp { |
|
|
| |
| |
| constexpr u64 scale_factor = 1 << 24; |
| constexpr u64 scale_mask = scale_factor - 1; |
|
|
| |
| |
| template <typename Function> |
| static void StepOverSamples(State& state, StereoBuffer16& input, float rate, StereoFrame16& output, |
| std::size_t& outputi, Function fn) { |
| ASSERT(rate > 0); |
|
|
| if (input.empty()) |
| return; |
|
|
| input.insert(input.begin(), {state.xn2, state.xn1}); |
|
|
| const u64 step_size = static_cast<u64>(rate * scale_factor); |
| u64 fposition = state.fposition; |
| std::size_t inputi = 0; |
|
|
| while (outputi < output.size()) { |
| inputi = static_cast<std::size_t>(fposition / scale_factor); |
|
|
| if (inputi + 2 >= input.size()) { |
| inputi = input.size() - 2; |
| break; |
| } |
|
|
| u64 fraction = fposition & scale_mask; |
| output[outputi++] = fn(fraction, input[inputi], input[inputi + 1], input[inputi + 2]); |
|
|
| fposition += step_size; |
| } |
|
|
| state.xn2 = input[inputi]; |
| state.xn1 = input[inputi + 1]; |
| state.fposition = fposition - inputi * scale_factor; |
|
|
| input.erase(input.begin(), std::next(input.begin(), inputi + 2)); |
| } |
|
|
| void None(State& state, StereoBuffer16& input, float rate, StereoFrame16& output, |
| std::size_t& outputi) { |
| StepOverSamples( |
| state, input, rate, output, outputi, |
| [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { return x0; }); |
| } |
|
|
| void Linear(State& state, StereoBuffer16& input, float rate, StereoFrame16& output, |
| std::size_t& outputi) { |
| |
| StepOverSamples(state, input, rate, output, outputi, |
| [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { |
| |
| s64 delta0 = std::clamp<s64>(x1[0] - x0[0], -32768, 32767); |
| s64 delta1 = std::clamp<s64>(x1[1] - x0[1], -32768, 32767); |
|
|
| return std::array<s16, 2>{ |
| static_cast<s16>(x0[0] + fraction * delta0 / scale_factor), |
| static_cast<s16>(x0[1] + fraction * delta1 / scale_factor), |
| }; |
| }); |
| } |
|
|
| } |
|
|