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.

207 lines
5.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software 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 LagrangeHelpers
  18. {
  19. template <int k>
  20. struct ResampleHelper
  21. {
  22. static forcedinline void calc (float& a, float b) { a *= b * (1.0f / k); }
  23. };
  24. template<>
  25. struct ResampleHelper <0>
  26. {
  27. static forcedinline void calc (float&, float) {}
  28. };
  29. template <int k>
  30. static forcedinline float calcCoefficient (float input, const float offset) noexcept
  31. {
  32. ResampleHelper <0 - k>::calc (input, -2.0f - offset);
  33. ResampleHelper <1 - k>::calc (input, -1.0f - offset);
  34. ResampleHelper <2 - k>::calc (input, 0.0f - offset);
  35. ResampleHelper <3 - k>::calc (input, 1.0f - offset);
  36. ResampleHelper <4 - k>::calc (input, 2.0f - offset);
  37. return input;
  38. }
  39. static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept
  40. {
  41. return calcCoefficient<0> (inputs[4], offset)
  42. + calcCoefficient<1> (inputs[3], offset)
  43. + calcCoefficient<2> (inputs[2], offset)
  44. + calcCoefficient<3> (inputs[1], offset)
  45. + calcCoefficient<4> (inputs[0], offset);
  46. }
  47. static forcedinline void push (float* inputs, const float newValue) noexcept
  48. {
  49. inputs[4] = inputs[3];
  50. inputs[3] = inputs[2];
  51. inputs[2] = inputs[1];
  52. inputs[1] = inputs[0];
  53. inputs[0] = newValue;
  54. }
  55. }
  56. //==============================================================================
  57. LagrangeInterpolator::LagrangeInterpolator() { reset(); }
  58. LagrangeInterpolator::~LagrangeInterpolator() {}
  59. void LagrangeInterpolator::reset() noexcept
  60. {
  61. subSamplePos = 1.0;
  62. for (int i = 0; i < numElementsInArray (lastInputSamples); ++i)
  63. lastInputSamples[i] = 0;
  64. }
  65. int LagrangeInterpolator::process (const double actualRatio, const float* in,
  66. float* out, const int numOut) noexcept
  67. {
  68. if (actualRatio == 1.0)
  69. {
  70. memcpy (out, in, (size_t) numOut * sizeof (float));
  71. if (numOut >= 4)
  72. {
  73. const float* end = in + numOut;
  74. for (int i = 0; i < 4; ++i)
  75. lastInputSamples[i] = *--end;
  76. }
  77. else
  78. {
  79. for (int i = 0; i < numOut; ++i)
  80. LagrangeHelpers::push (lastInputSamples, in[i]);
  81. }
  82. return numOut;
  83. }
  84. const float* const originalIn = in;
  85. double pos = subSamplePos;
  86. if (actualRatio < 1.0)
  87. {
  88. for (int i = numOut; --i >= 0;)
  89. {
  90. if (pos >= 1.0)
  91. {
  92. LagrangeHelpers::push (lastInputSamples, *in++);
  93. pos -= 1.0;
  94. }
  95. *out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
  96. pos += actualRatio;
  97. }
  98. }
  99. else
  100. {
  101. for (int i = numOut; --i >= 0;)
  102. {
  103. while (pos < actualRatio)
  104. {
  105. LagrangeHelpers::push (lastInputSamples, *in++);
  106. pos += 1.0;
  107. }
  108. pos -= actualRatio;
  109. *out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, 1.0f - (float) pos);
  110. }
  111. }
  112. subSamplePos = pos;
  113. return (int) (in - originalIn);
  114. }
  115. int LagrangeInterpolator::processAdding (const double actualRatio, const float* in,
  116. float* out, const int numOut, const float gain) noexcept
  117. {
  118. if (actualRatio == 1.0)
  119. {
  120. if (gain != 1.0f)
  121. {
  122. for (int i = 0; i < numOut; ++i)
  123. out[i] += in[i] * gain;
  124. }
  125. else
  126. {
  127. for (int i = 0; i < numOut; ++i)
  128. out[i] += in[i];
  129. }
  130. if (numOut >= 4)
  131. {
  132. const float* end = in + numOut;
  133. for (int i = 0; i < 4; ++i)
  134. lastInputSamples[i] = *--end;
  135. }
  136. else
  137. {
  138. for (int i = 0; i < numOut; ++i)
  139. LagrangeHelpers::push (lastInputSamples, in[i]);
  140. }
  141. return numOut;
  142. }
  143. const float* const originalIn = in;
  144. double pos = subSamplePos;
  145. if (actualRatio < 1.0)
  146. {
  147. for (int i = numOut; --i >= 0;)
  148. {
  149. if (pos >= 1.0)
  150. {
  151. LagrangeHelpers::push (lastInputSamples, *in++);
  152. pos -= 1.0;
  153. }
  154. *out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
  155. pos += actualRatio;
  156. }
  157. }
  158. else
  159. {
  160. for (int i = numOut; --i >= 0;)
  161. {
  162. while (pos < actualRatio)
  163. {
  164. LagrangeHelpers::push (lastInputSamples, *in++);
  165. pos += 1.0;
  166. }
  167. pos -= actualRatio;
  168. *out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
  169. }
  170. }
  171. subSamplePos = pos;
  172. return (int) (in - originalIn);
  173. }