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.

130 lines
3.5KB

  1. // Copyright 2016 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. // Envelope for the internal LPG.
  28. #ifndef PLAITS_DSP_ENVELOPE_H_
  29. #define PLAITS_DSP_ENVELOPE_H_
  30. #include "stmlib/stmlib.h"
  31. namespace plaits {
  32. class LPGEnvelope {
  33. public:
  34. LPGEnvelope() { }
  35. ~LPGEnvelope() { }
  36. inline void Init() {
  37. vactrol_state_ = 0.0f;
  38. gain_ = 1.0f;
  39. frequency_ = 0.5f;
  40. hf_bleed_ = 0.0f;
  41. }
  42. inline void Trigger() {
  43. ramp_up_ = true;
  44. }
  45. inline void ProcessPing(
  46. float attack,
  47. float short_decay,
  48. float decay_tail,
  49. float hf) {
  50. if (ramp_up_) {
  51. vactrol_state_ += attack;
  52. if (vactrol_state_ >= 1.0f) {
  53. vactrol_state_ = 1.0f;
  54. ramp_up_ = false;
  55. }
  56. }
  57. ProcessLP(ramp_up_ ? vactrol_state_ : 0.0f, short_decay, decay_tail, hf);
  58. }
  59. inline void ProcessLP(
  60. float level,
  61. float short_decay,
  62. float decay_tail,
  63. float hf) {
  64. float vactrol_input = level;
  65. float vactrol_error = (vactrol_input - vactrol_state_);
  66. float vactrol_state_2 = vactrol_state_ * vactrol_state_;
  67. float vactrol_state_4 = vactrol_state_2 * vactrol_state_2;
  68. float tail = 1.0f - vactrol_state_;
  69. float tail_2 = tail * tail;
  70. float vactrol_coefficient = (vactrol_error > 0.0f)
  71. ? 0.6f
  72. : short_decay + (1.0f - vactrol_state_4) * decay_tail;
  73. vactrol_state_ += vactrol_coefficient * vactrol_error;
  74. gain_ = vactrol_state_;
  75. frequency_ = 0.003f + 0.3f * vactrol_state_4 + hf * 0.04f;
  76. hf_bleed_ = (tail_2 + (1.0f - tail_2) * hf) * hf * hf;
  77. }
  78. inline float gain() const { return gain_; }
  79. inline float frequency() const { return frequency_; }
  80. inline float hf_bleed() const { return hf_bleed_; }
  81. private:
  82. float vactrol_state_;
  83. float gain_;
  84. float frequency_;
  85. float hf_bleed_;
  86. bool ramp_up_;
  87. DISALLOW_COPY_AND_ASSIGN(LPGEnvelope);
  88. };
  89. class DecayEnvelope {
  90. public:
  91. DecayEnvelope() { }
  92. ~DecayEnvelope() { }
  93. inline void Init() {
  94. value_ = 0.0f;
  95. }
  96. inline void Trigger() {
  97. value_ = 1.0f;
  98. }
  99. inline void Process(float decay) {
  100. value_ *= (1.0f - decay);
  101. }
  102. inline float value() const { return value_; }
  103. private:
  104. float value_;
  105. DISALLOW_COPY_AND_ASSIGN(DecayEnvelope);
  106. };
  107. } // namespace plaits
  108. #endif // PLAITS_DSP_ENVELOPE_H_