🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
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.

132 lines
3.4 KiB

  1. #include "config.h"
  2. #include "splitter.h"
  3. #include <cmath>
  4. #include <limits>
  5. #include <algorithm>
  6. #include "math_defs.h"
  7. template<typename Real>
  8. void BandSplitterR<Real>::init(Real f0norm)
  9. {
  10. const Real w{f0norm * al::MathDefs<Real>::Tau()};
  11. const Real cw{std::cos(w)};
  12. if(cw > std::numeric_limits<float>::epsilon())
  13. coeff = (std::sin(w) - 1.0f) / cw;
  14. else
  15. coeff = cw * -0.5f;
  16. lp_z1 = 0.0f;
  17. lp_z2 = 0.0f;
  18. ap_z1 = 0.0f;
  19. }
  20. template<typename Real>
  21. void BandSplitterR<Real>::process(Real *hpout, Real *lpout, const Real *input, const int count)
  22. {
  23. ASSUME(count > 0);
  24. const Real ap_coeff{this->coeff};
  25. const Real lp_coeff{this->coeff*0.5f + 0.5f};
  26. Real lp_z1{this->lp_z1};
  27. Real lp_z2{this->lp_z2};
  28. Real ap_z1{this->ap_z1};
  29. auto proc_sample = [ap_coeff,lp_coeff,&lp_z1,&lp_z2,&ap_z1,&lpout](const Real in) noexcept -> Real
  30. {
  31. /* Low-pass sample processing. */
  32. Real d{(in - lp_z1) * lp_coeff};
  33. Real lp_y{lp_z1 + d};
  34. lp_z1 = lp_y + d;
  35. d = (lp_y - lp_z2) * lp_coeff;
  36. lp_y = lp_z2 + d;
  37. lp_z2 = lp_y + d;
  38. *(lpout++) = lp_y;
  39. /* All-pass sample processing. */
  40. Real ap_y{in*ap_coeff + ap_z1};
  41. ap_z1 = in - ap_y*ap_coeff;
  42. /* High-pass generated from removing low-passed output. */
  43. return ap_y - lp_y;
  44. };
  45. std::transform(input, input+count, hpout, proc_sample);
  46. this->lp_z1 = lp_z1;
  47. this->lp_z2 = lp_z2;
  48. this->ap_z1 = ap_z1;
  49. }
  50. template<typename Real>
  51. void BandSplitterR<Real>::applyHfScale(Real *samples, const Real hfscale, const int count)
  52. {
  53. ASSUME(count > 0);
  54. const Real ap_coeff{this->coeff};
  55. const Real lp_coeff{this->coeff*0.5f + 0.5f};
  56. Real lp_z1{this->lp_z1};
  57. Real lp_z2{this->lp_z2};
  58. Real ap_z1{this->ap_z1};
  59. auto proc_sample = [hfscale,ap_coeff,lp_coeff,&lp_z1,&lp_z2,&ap_z1](const Real in) noexcept -> Real
  60. {
  61. /* Low-pass sample processing. */
  62. Real d{(in - lp_z1) * lp_coeff};
  63. Real lp_y{lp_z1 + d};
  64. lp_z1 = lp_y + d;
  65. d = (lp_y - lp_z2) * lp_coeff;
  66. lp_y = lp_z2 + d;
  67. lp_z2 = lp_y + d;
  68. /* All-pass sample processing. */
  69. Real ap_y{in*ap_coeff + ap_z1};
  70. ap_z1 = in - ap_y*ap_coeff;
  71. /* High-pass generated from removing low-passed output. */
  72. return (ap_y-lp_y)*hfscale + lp_y;
  73. };
  74. std::transform(samples, samples+count, samples, proc_sample);
  75. this->lp_z1 = lp_z1;
  76. this->lp_z2 = lp_z2;
  77. this->ap_z1 = ap_z1;
  78. }
  79. template class BandSplitterR<float>;
  80. template class BandSplitterR<double>;
  81. template<typename Real>
  82. void SplitterAllpassR<Real>::init(Real f0norm)
  83. {
  84. const Real w{f0norm * al::MathDefs<Real>::Tau()};
  85. const Real cw{std::cos(w)};
  86. if(cw > std::numeric_limits<float>::epsilon())
  87. coeff = (std::sin(w) - 1.0f) / cw;
  88. else
  89. coeff = cw * -0.5f;
  90. z1 = 0.0f;
  91. }
  92. template<typename Real>
  93. void SplitterAllpassR<Real>::process(Real *samples, int count)
  94. {
  95. ASSUME(count > 0);
  96. const Real coeff{this->coeff};
  97. Real z1{this->z1};
  98. auto proc_sample = [coeff,&z1](const Real in) noexcept -> Real
  99. {
  100. const Real out{in*coeff + z1};
  101. z1 = in - out*coeff;
  102. return out;
  103. };
  104. std::transform(samples, samples+count, samples, proc_sample);
  105. this->z1 = z1;
  106. }
  107. template class SplitterAllpassR<float>;
  108. template class SplitterAllpassR<double>;