interpolate.cpp 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2016 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "audio_core/interpolate.h"
  5. #include "common/assert.h"
  6. #include "common/math_util.h"
  7. namespace AudioInterp {
  8. // Calculations are done in fixed point with 24 fractional bits.
  9. // (This is not verified. This was chosen for minimal error.)
  10. constexpr u64 scale_factor = 1 << 24;
  11. constexpr u64 scale_mask = scale_factor - 1;
  12. /// Here we step over the input in steps of rate_multiplier, until we consume all of the input.
  13. /// Three adjacent samples are passed to fn each step.
  14. template <typename Function>
  15. static StereoBuffer16 StepOverSamples(State& state, const StereoBuffer16& input,
  16. float rate_multiplier, Function fn) {
  17. ASSERT(rate_multiplier > 0);
  18. if (input.size() < 2)
  19. return {};
  20. StereoBuffer16 output;
  21. output.reserve(static_cast<size_t>(input.size() / rate_multiplier));
  22. u64 step_size = static_cast<u64>(rate_multiplier * scale_factor);
  23. u64 fposition = 0;
  24. const u64 max_fposition = input.size() * scale_factor;
  25. while (fposition < 1 * scale_factor) {
  26. u64 fraction = fposition & scale_mask;
  27. output.push_back(fn(fraction, state.xn2, state.xn1, input[0]));
  28. fposition += step_size;
  29. }
  30. while (fposition < 2 * scale_factor) {
  31. u64 fraction = fposition & scale_mask;
  32. output.push_back(fn(fraction, state.xn1, input[0], input[1]));
  33. fposition += step_size;
  34. }
  35. while (fposition < max_fposition) {
  36. u64 fraction = fposition & scale_mask;
  37. size_t index = static_cast<size_t>(fposition / scale_factor);
  38. output.push_back(fn(fraction, input[index - 2], input[index - 1], input[index]));
  39. fposition += step_size;
  40. }
  41. state.xn2 = input[input.size() - 2];
  42. state.xn1 = input[input.size() - 1];
  43. return output;
  44. }
  45. StereoBuffer16 None(State& state, const StereoBuffer16& input, float rate_multiplier) {
  46. return StepOverSamples(
  47. state, input, rate_multiplier,
  48. [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) { return x0; });
  49. }
  50. StereoBuffer16 Linear(State& state, const StereoBuffer16& input, float rate_multiplier) {
  51. // Note on accuracy: Some values that this produces are +/- 1 from the actual firmware.
  52. return StepOverSamples(state, input, rate_multiplier,
  53. [](u64 fraction, const auto& x0, const auto& x1, const auto& x2) {
  54. // This is a saturated subtraction. (Verified by black-box fuzzing.)
  55. s64 delta0 = MathUtil::Clamp<s64>(x1[0] - x0[0], -32768, 32767);
  56. s64 delta1 = MathUtil::Clamp<s64>(x1[1] - x0[1], -32768, 32767);
  57. return std::array<s16, 2>{
  58. static_cast<s16>(x0[0] + fraction * delta0 / scale_factor),
  59. static_cast<s16>(x0[1] + fraction * delta1 / scale_factor),
  60. };
  61. });
  62. }
  63. } // namespace AudioInterp