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.

171 lines
4.6KB

  1. // Copyright 2015 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // String.
  28. #ifndef ELEMENTS_DSP_STRING_H_
  29. #define ELEMENTS_DSP_STRING_H_
  30. #include "stmlib/stmlib.h"
  31. #include <algorithm>
  32. #include "stmlib/dsp/delay_line.h"
  33. #include "stmlib/dsp/filter.h"
  34. namespace elements {
  35. const size_t kDelayLineSize = 2048;
  36. class DampingFilter {
  37. public:
  38. DampingFilter() { }
  39. ~DampingFilter() { }
  40. void Init() {
  41. x_ = 0.0f;
  42. x__ = 0.0f;
  43. brightness_ = 0.0f;
  44. brightness_increment_ = 0.0f;
  45. damping_ = 0.0f;
  46. damping_increment_ = 0.0f;
  47. }
  48. inline void Configure(float damping, float brightness, size_t size) {
  49. if (!size) {
  50. damping_ = damping;
  51. brightness_ = brightness;
  52. damping_increment_ = 0.0f;
  53. brightness_increment_ = 0.0f;
  54. } else {
  55. float step = 1.0f / static_cast<float>(size);
  56. damping_increment_ = (damping - damping_) * step;
  57. brightness_increment_ = (brightness - brightness_) * step;
  58. }
  59. }
  60. inline float Process(float x) {
  61. float h0 = (1.0f + brightness_) * 0.5f;
  62. float h1 = (1.0f - brightness_) * 0.25f;
  63. float y = damping_ * (h0 * x_ + h1 * (x + x__));
  64. x__ = x_;
  65. x_ = x;
  66. brightness_ += brightness_increment_;
  67. damping_ += damping_increment_;
  68. return y;
  69. }
  70. private:
  71. float x_;
  72. float x__;
  73. float brightness_;
  74. float brightness_increment_;
  75. float damping_;
  76. float damping_increment_;
  77. DISALLOW_COPY_AND_ASSIGN(DampingFilter);
  78. };
  79. typedef stmlib::DelayLine<float, kDelayLineSize> StringDelayLine;
  80. typedef stmlib::DelayLine<float, kDelayLineSize / 2> StiffnessDelayLine;
  81. class String {
  82. public:
  83. String() { }
  84. ~String() { }
  85. void Init(bool enable_dispersion);
  86. void Process(const float* in, float* out, float* aux, size_t size);
  87. inline void set_frequency(float frequency) {
  88. frequency_ = frequency;
  89. }
  90. inline void set_frequency(float frequency, float coefficient) {
  91. frequency_ += coefficient * (frequency - frequency_);
  92. }
  93. inline void set_dispersion(float dispersion) {
  94. dispersion = dispersion < 0.24f
  95. ? (dispersion - 0.24f) * 4.166f
  96. : (dispersion > 0.26f ? (dispersion - 0.26f) * 1.35135f : 0.0f);
  97. dispersion_ = dispersion;
  98. }
  99. inline void set_brightness(float brightness) {
  100. brightness_ = brightness;
  101. }
  102. inline void set_damping(float damping) {
  103. damping_ = damping;
  104. }
  105. inline void set_position(float position) {
  106. position_ = position;
  107. }
  108. inline StringDelayLine* mutable_string() { return &string_; }
  109. private:
  110. template<bool enable_dispersion>
  111. void ProcessInternal(const float* in, float* out, float* aux, size_t size);
  112. float frequency_;
  113. float dispersion_;
  114. float brightness_;
  115. float damping_;
  116. float position_;
  117. float delay_;
  118. float clamped_position_;
  119. float previous_dispersion_;
  120. float previous_damping_compensation_;
  121. bool enable_dispersion_;
  122. bool enable_iir_damping_;
  123. float dispersion_noise_;
  124. // Very crappy linear interpolation upsampler used for low pitches that
  125. // do not fit the delay line. Rarely used.
  126. float src_phase_;
  127. float out_sample_[2];
  128. float aux_sample_[2];
  129. float curved_bridge_;
  130. StringDelayLine string_;
  131. StiffnessDelayLine stretch_;
  132. DampingFilter fir_damping_filter_;
  133. stmlib::Svf iir_damping_filter_;
  134. stmlib::DCBlocker dc_blocker_;
  135. DISALLOW_COPY_AND_ASSIGN(String);
  136. };
  137. } // namespace elements
  138. #endif // ELEMENTS_DSP_STRING_H_