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.

170 lines
4.5KB

  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. // Comb filter / KS string.
  28. #ifndef RINGS_DSP_STRING_H_
  29. #define RINGS_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. #include "rings/dsp/dsp.h"
  35. namespace rings {
  36. const size_t kDelayLineSize = 2048;
  37. class DampingFilter {
  38. public:
  39. DampingFilter() { }
  40. ~DampingFilter() { }
  41. void Init() {
  42. x_ = 0.0f;
  43. x__ = 0.0f;
  44. brightness_ = 0.0f;
  45. brightness_increment_ = 0.0f;
  46. damping_ = 0.0f;
  47. damping_increment_ = 0.0f;
  48. }
  49. inline void Configure(float damping, float brightness, size_t size) {
  50. if (!size) {
  51. damping_ = damping;
  52. brightness_ = brightness;
  53. damping_increment_ = 0.0f;
  54. brightness_increment_ = 0.0f;
  55. } else {
  56. float step = 1.0f / static_cast<float>(size);
  57. damping_increment_ = (damping - damping_) * step;
  58. brightness_increment_ = (brightness - brightness_) * step;
  59. }
  60. }
  61. inline float Process(float x) {
  62. float h0 = (1.0f + brightness_) * 0.5f;
  63. float h1 = (1.0f - brightness_) * 0.25f;
  64. float y = damping_ * (h0 * x_ + h1 * (x + x__));
  65. x__ = x_;
  66. x_ = x;
  67. brightness_ += brightness_increment_;
  68. damping_ += damping_increment_;
  69. return y;
  70. }
  71. private:
  72. float x_;
  73. float x__;
  74. float brightness_;
  75. float brightness_increment_;
  76. float damping_;
  77. float damping_increment_;
  78. DISALLOW_COPY_AND_ASSIGN(DampingFilter);
  79. };
  80. typedef stmlib::DelayLine<float, kDelayLineSize> StringDelayLine;
  81. typedef stmlib::DelayLine<float, kDelayLineSize / 2> StiffnessDelayLine;
  82. class String {
  83. public:
  84. String() { }
  85. ~String() { }
  86. void Init(bool enable_dispersion);
  87. void Process(const float* in, float* out, float* aux, size_t size);
  88. inline void set_frequency(float frequency) {
  89. frequency_ = frequency;
  90. }
  91. inline void set_frequency(float frequency, float coefficient) {
  92. frequency_ += coefficient * (frequency - frequency_);
  93. }
  94. inline void set_dispersion(float dispersion) {
  95. dispersion_ = dispersion;
  96. }
  97. inline void set_brightness(float brightness) {
  98. brightness_ = brightness;
  99. }
  100. inline void set_damping(float damping) {
  101. damping_ = damping;
  102. }
  103. inline void set_position(float position) {
  104. position_ = position;
  105. }
  106. inline StringDelayLine* mutable_string() { return &string_; }
  107. private:
  108. template<bool enable_dispersion>
  109. void ProcessInternal(const float* in, float* out, float* aux, size_t size);
  110. float frequency_;
  111. float dispersion_;
  112. float brightness_;
  113. float damping_;
  114. float position_;
  115. float delay_;
  116. float clamped_position_;
  117. float previous_dispersion_;
  118. float previous_damping_compensation_;
  119. bool enable_dispersion_;
  120. bool enable_iir_damping_;
  121. float dispersion_noise_;
  122. // Very crappy linear interpolation upsampler used for low pitches that
  123. // do not fit the delay line. Rarely used.
  124. float src_phase_;
  125. float out_sample_[2];
  126. float aux_sample_[2];
  127. float curved_bridge_;
  128. StringDelayLine string_;
  129. StiffnessDelayLine stretch_;
  130. DampingFilter fir_damping_filter_;
  131. stmlib::Svf iir_damping_filter_;
  132. stmlib::DCBlocker dc_blocker_;
  133. DISALLOW_COPY_AND_ASSIGN(String);
  134. };
  135. } // namespace rings
  136. #endif // RINGS_DSP_STRING_H_