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.

122 lines
4.1KB

  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. // Resonator.
  28. #include "rings/dsp/resonator.h"
  29. #include "stmlib/dsp/dsp.h"
  30. #include "stmlib/dsp/cosine_oscillator.h"
  31. #include "stmlib/dsp/parameter_interpolator.h"
  32. #include "rings/resources.h"
  33. namespace rings {
  34. using namespace std;
  35. using namespace stmlib;
  36. void Resonator::Init() {
  37. for (int32_t i = 0; i < kMaxModes; ++i) {
  38. f_[i].Init();
  39. }
  40. set_frequency(220.0f / kSampleRate);
  41. set_structure(0.25f);
  42. set_brightness(0.5f);
  43. set_damping(0.3f);
  44. set_position(0.999f);
  45. set_resolution(kMaxModes);
  46. }
  47. int32_t Resonator::ComputeFilters() {
  48. float stiffness = Interpolate(lut_stiffness, structure_, 256.0f);
  49. float harmonic = frequency_;
  50. float stretch_factor = 1.0f;
  51. float q = 500.0f * Interpolate(
  52. lut_4_decades,
  53. damping_,
  54. 256.0f);
  55. float brightness_attenuation = 1.0f - structure_;
  56. // Reduces the range of brightness when structure is very low, to prevent
  57. // clipping.
  58. brightness_attenuation *= brightness_attenuation;
  59. brightness_attenuation *= brightness_attenuation;
  60. brightness_attenuation *= brightness_attenuation;
  61. float brightness = brightness_ * (1.0f - 0.2f * brightness_attenuation);
  62. float q_loss = brightness * (2.0f - brightness) * 0.85f + 0.15f;
  63. float q_loss_damping_rate = structure_ * (2.0f - structure_) * 0.1f;
  64. int32_t num_modes = 0;
  65. for (int32_t i = 0; i < min(kMaxModes, resolution_); ++i) {
  66. float partial_frequency = harmonic * stretch_factor;
  67. if (partial_frequency >= 0.49f) {
  68. partial_frequency = 0.49f;
  69. } else {
  70. num_modes = i + 1;
  71. }
  72. f_[i].set_f_q<FREQUENCY_FAST>(
  73. partial_frequency,
  74. 1.0f + partial_frequency * q);
  75. stretch_factor += stiffness;
  76. if (stiffness < 0.0f) {
  77. // Make sure that the partials do not fold back into negative frequencies.
  78. stiffness *= 0.93f;
  79. } else {
  80. // This helps adding a few extra partials in the highest frequencies.
  81. stiffness *= 0.98f;
  82. }
  83. // This prevents the highest partials from decaying too fast.
  84. q_loss += q_loss_damping_rate * (1.0f - q_loss);
  85. harmonic += frequency_;
  86. q *= q_loss;
  87. }
  88. return num_modes;
  89. }
  90. void Resonator::Process(const float* in, float* out, float* aux, size_t size) {
  91. int32_t num_modes = ComputeFilters();
  92. ParameterInterpolator position(&previous_position_, position_, size);
  93. while (size--) {
  94. CosineOscillator amplitudes;
  95. amplitudes.Init<COSINE_OSCILLATOR_APPROXIMATE>(position.Next());
  96. float input = *in++ * 0.125f;
  97. float odd = 0.0f;
  98. float even = 0.0f;
  99. amplitudes.Start();
  100. for (int32_t i = 0; i < num_modes;) {
  101. odd += amplitudes.Next() * f_[i++].Process<FILTER_MODE_BAND_PASS>(input);
  102. even += amplitudes.Next() * f_[i++].Process<FILTER_MODE_BAND_PASS>(input);
  103. }
  104. *out++ = odd;
  105. *aux++ = even;
  106. }
  107. }
  108. } // namespace rings