The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

202 lines
6.0KB

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