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.

182 lines
4.9KB

  1. // Copyright 2014 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. // Reverb.
  28. #ifndef ELEMENTS_DSP_FX_REVERB_H_
  29. #define ELEMENTS_DSP_FX_REVERB_H_
  30. #include "stmlib/stmlib.h"
  31. #include "elements/dsp/fx/fx_engine.h"
  32. namespace elements {
  33. class Reverb {
  34. public:
  35. Reverb() { }
  36. ~Reverb() { }
  37. void Init(uint16_t* buffer) {
  38. engine_.Init(buffer);
  39. engine_.SetLFOFrequency(LFO_1, 0.5f / 32000.0f);
  40. engine_.SetLFOFrequency(LFO_2, 0.3f / 32000.0f);
  41. lp_ = 0.7f;
  42. diffusion_ = 0.625f;
  43. }
  44. void Process(float* left, float* right, size_t size) {
  45. // This is the Griesinger topology described in the Dattorro paper
  46. // (4 AP diffusers on the input, then a loop of 2x 2AP+1Delay).
  47. // Modulation is applied in the loop of the first diffuser AP for additional
  48. // smearing; and to the two long delays for a slow shimmer/chorus effect.
  49. typedef E::Reserve<150,
  50. E::Reserve<214,
  51. E::Reserve<319,
  52. E::Reserve<527,
  53. E::Reserve<2182,
  54. E::Reserve<2690,
  55. E::Reserve<4501,
  56. E::Reserve<2525,
  57. E::Reserve<2197,
  58. E::Reserve<6312> > > > > > > > > > Memory;
  59. E::DelayLine<Memory, 0> ap1;
  60. E::DelayLine<Memory, 1> ap2;
  61. E::DelayLine<Memory, 2> ap3;
  62. E::DelayLine<Memory, 3> ap4;
  63. E::DelayLine<Memory, 4> dap1a;
  64. E::DelayLine<Memory, 5> dap1b;
  65. E::DelayLine<Memory, 6> del1;
  66. E::DelayLine<Memory, 7> dap2a;
  67. E::DelayLine<Memory, 8> dap2b;
  68. E::DelayLine<Memory, 9> del2;
  69. E::Context c;
  70. const float kap = diffusion_;
  71. const float klp = lp_;
  72. const float krt = reverb_time_;
  73. const float amount = amount_;
  74. const float gain = input_gain_;
  75. float lp_1 = lp_decay_1_;
  76. float lp_2 = lp_decay_2_;
  77. while (size--) {
  78. float wet;
  79. float apout = 0.0f;
  80. engine_.Start(&c);
  81. // Smear AP1 inside the loop.
  82. c.Interpolate(ap1, 10.0f, LFO_1, 80.0f, 1.0f);
  83. c.Write(ap1, 100, 0.0f);
  84. c.Read(*left + *right, gain);
  85. // Diffuse through 4 allpasses.
  86. c.Read(ap1 TAIL, kap);
  87. c.WriteAllPass(ap1, -kap);
  88. c.Read(ap2 TAIL, kap);
  89. c.WriteAllPass(ap2, -kap);
  90. c.Read(ap3 TAIL, kap);
  91. c.WriteAllPass(ap3, -kap);
  92. c.Read(ap4 TAIL, kap);
  93. c.WriteAllPass(ap4, -kap);
  94. c.Write(apout);
  95. // Main reverb loop.
  96. c.Load(apout);
  97. c.Interpolate(del2, 6211.0f, LFO_2, 100.0f, krt);
  98. c.Lp(lp_1, klp);
  99. c.Read(dap1a TAIL, -kap);
  100. c.WriteAllPass(dap1a, kap);
  101. c.Read(dap1b TAIL, kap);
  102. c.WriteAllPass(dap1b, -kap);
  103. c.Write(del1, 2.0f);
  104. c.Write(wet, 0.0f);
  105. *left += (wet - *left) * amount;
  106. c.Load(apout);
  107. // c.Interpolate(del1, 4450.0f, LFO_1, 50.0f, krt);
  108. c.Read(del1 TAIL, krt);
  109. c.Lp(lp_2, klp);
  110. c.Read(dap2a TAIL, kap);
  111. c.WriteAllPass(dap2a, -kap);
  112. c.Read(dap2b TAIL, -kap);
  113. c.WriteAllPass(dap2b, kap);
  114. c.Write(del2, 2.0f);
  115. c.Write(wet, 0.0f);
  116. *right += (wet - *right) * amount;
  117. ++left;
  118. ++right;
  119. }
  120. lp_decay_1_ = lp_1;
  121. lp_decay_2_ = lp_2;
  122. }
  123. inline void set_amount(float amount) {
  124. amount_ = amount;
  125. }
  126. inline void set_input_gain(float input_gain) {
  127. input_gain_ = input_gain;
  128. }
  129. inline void set_time(float reverb_time) {
  130. reverb_time_ = reverb_time;
  131. }
  132. inline void set_diffusion(float diffusion) {
  133. diffusion_ = diffusion;
  134. }
  135. inline void set_lp(float lp) {
  136. lp_ = lp;
  137. }
  138. private:
  139. typedef FxEngine<32768, FORMAT_16_BIT> E;
  140. E engine_;
  141. float amount_;
  142. float input_gain_;
  143. float reverb_time_;
  144. float diffusion_;
  145. float lp_;
  146. float lp_decay_1_;
  147. float lp_decay_2_;
  148. DISALLOW_COPY_AND_ASSIGN(Reverb);
  149. };
  150. } // namespace elements
  151. #endif // ELEMENTS_DSP_FX_REVERB_H_