Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
6.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace
  18. {
  19. static forcedinline void pushInterpolationSample (float* lastInputSamples, const float newValue) noexcept
  20. {
  21. lastInputSamples[4] = lastInputSamples[3];
  22. lastInputSamples[3] = lastInputSamples[2];
  23. lastInputSamples[2] = lastInputSamples[1];
  24. lastInputSamples[1] = lastInputSamples[0];
  25. lastInputSamples[0] = newValue;
  26. }
  27. static forcedinline void pushInterpolationSamples (float* lastInputSamples, const float* input, int numOut) noexcept
  28. {
  29. if (numOut >= 5)
  30. {
  31. for (int i = 0; i < 5; ++i)
  32. lastInputSamples[i] = input[--numOut];
  33. }
  34. else
  35. {
  36. for (int i = 0; i < numOut; ++i)
  37. pushInterpolationSample (lastInputSamples, input[i]);
  38. }
  39. }
  40. template <typename InterpolatorType>
  41. static int interpolate (float* lastInputSamples, double& subSamplePos, const double actualRatio,
  42. const float* in, float* out, const int numOut) noexcept
  43. {
  44. if (actualRatio == 1.0)
  45. {
  46. memcpy (out, in, (size_t) numOut * sizeof (float));
  47. pushInterpolationSamples (lastInputSamples, in, numOut);
  48. return numOut;
  49. }
  50. const float* const originalIn = in;
  51. double pos = subSamplePos;
  52. if (actualRatio < 1.0)
  53. {
  54. for (int i = numOut; --i >= 0;)
  55. {
  56. if (pos >= 1.0)
  57. {
  58. pushInterpolationSample (lastInputSamples, *in++);
  59. pos -= 1.0;
  60. }
  61. *out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos);
  62. pos += actualRatio;
  63. }
  64. }
  65. else
  66. {
  67. for (int i = numOut; --i >= 0;)
  68. {
  69. while (pos < actualRatio)
  70. {
  71. pushInterpolationSample (lastInputSamples, *in++);
  72. pos += 1.0;
  73. }
  74. pos -= actualRatio;
  75. *out++ = InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
  76. }
  77. }
  78. subSamplePos = pos;
  79. return (int) (in - originalIn);
  80. }
  81. template <typename InterpolatorType>
  82. static int interpolateAdding (float* lastInputSamples, double& subSamplePos, const double actualRatio,
  83. const float* in, float* out, const int numOut, const float gain) noexcept
  84. {
  85. if (actualRatio == 1.0)
  86. {
  87. FloatVectorOperations::addWithMultiply (out, in, gain, numOut);
  88. pushInterpolationSamples (lastInputSamples, in, numOut);
  89. return numOut;
  90. }
  91. const float* const originalIn = in;
  92. double pos = subSamplePos;
  93. if (actualRatio < 1.0)
  94. {
  95. for (int i = numOut; --i >= 0;)
  96. {
  97. if (pos >= 1.0)
  98. {
  99. pushInterpolationSample (lastInputSamples, *in++);
  100. pos -= 1.0;
  101. }
  102. *out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos);
  103. pos += actualRatio;
  104. }
  105. }
  106. else
  107. {
  108. for (int i = numOut; --i >= 0;)
  109. {
  110. while (pos < actualRatio)
  111. {
  112. pushInterpolationSample (lastInputSamples, *in++);
  113. pos += 1.0;
  114. }
  115. pos -= actualRatio;
  116. *out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
  117. }
  118. }
  119. subSamplePos = pos;
  120. return (int) (in - originalIn);
  121. }
  122. }
  123. //==============================================================================
  124. template <int k>
  125. struct LagrangeResampleHelper
  126. {
  127. static forcedinline void calc (float& a, float b) noexcept { a *= b * (1.0f / k); }
  128. };
  129. template<>
  130. struct LagrangeResampleHelper<0>
  131. {
  132. static forcedinline void calc (float&, float) noexcept {}
  133. };
  134. struct LagrangeAlgorithm
  135. {
  136. static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept
  137. {
  138. return calcCoefficient<0> (inputs[4], offset)
  139. + calcCoefficient<1> (inputs[3], offset)
  140. + calcCoefficient<2> (inputs[2], offset)
  141. + calcCoefficient<3> (inputs[1], offset)
  142. + calcCoefficient<4> (inputs[0], offset);
  143. }
  144. template <int k>
  145. static forcedinline float calcCoefficient (float input, const float offset) noexcept
  146. {
  147. LagrangeResampleHelper<0 - k>::calc (input, -2.0f - offset);
  148. LagrangeResampleHelper<1 - k>::calc (input, -1.0f - offset);
  149. LagrangeResampleHelper<2 - k>::calc (input, 0.0f - offset);
  150. LagrangeResampleHelper<3 - k>::calc (input, 1.0f - offset);
  151. LagrangeResampleHelper<4 - k>::calc (input, 2.0f - offset);
  152. return input;
  153. }
  154. };
  155. LagrangeInterpolator::LagrangeInterpolator() noexcept { reset(); }
  156. LagrangeInterpolator::~LagrangeInterpolator() noexcept {}
  157. void LagrangeInterpolator::reset() noexcept
  158. {
  159. subSamplePos = 1.0;
  160. for (int i = 0; i < numElementsInArray (lastInputSamples); ++i)
  161. lastInputSamples[i] = 0;
  162. }
  163. int LagrangeInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept
  164. {
  165. return interpolate<LagrangeAlgorithm> (lastInputSamples, subSamplePos, actualRatio, in, out, numOut);
  166. }
  167. int LagrangeInterpolator::processAdding (double actualRatio, const float* in, float* out, int numOut, float gain) noexcept
  168. {
  169. return interpolateAdding<LagrangeAlgorithm> (lastInputSamples, subSamplePos, actualRatio, in, out, numOut, gain);
  170. }