Audio plugin host https://kx.studio/carla
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.

225 lines
5.4KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Echo.cpp - Echo effect
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Copyright (C) 2009-2010 Mark McCurry
  6. Author: Nasca Octavian Paul
  7. Mark McCurry
  8. This program is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU General Public License
  10. as published by the Free Software Foundation; either version 2
  11. of the License, or (at your option) any later version.
  12. */
  13. #include <cmath>
  14. #include "../Misc/Allocator.h"
  15. #include "Echo.h"
  16. #define MAX_DELAY 2
  17. Echo::Echo(EffectParams pars)
  18. :Effect(pars),
  19. Pvolume(50),
  20. Pdelay(60),
  21. Plrdelay(100),
  22. Pfb(40),
  23. Phidamp(60),
  24. delayTime(1),
  25. lrdelay(0),
  26. avgDelay(0),
  27. delay(memory.valloc<float>(MAX_DELAY * pars.srate),
  28. memory.valloc<float>(MAX_DELAY * pars.srate)),
  29. old(0.0f),
  30. pos(0),
  31. delta(1),
  32. ndelta(1)
  33. {
  34. initdelays();
  35. setpreset(Ppreset);
  36. }
  37. Echo::~Echo()
  38. {
  39. memory.devalloc(delay.l);
  40. memory.devalloc(delay.r);
  41. }
  42. //Cleanup the effect
  43. void Echo::cleanup(void)
  44. {
  45. memset(delay.l, 0, MAX_DELAY * samplerate * sizeof(float));
  46. memset(delay.r, 0, MAX_DELAY * samplerate * sizeof(float));
  47. old = Stereo<float>(0.0f);
  48. }
  49. inline int max(int a, int b)
  50. {
  51. return a > b ? a : b;
  52. }
  53. //Initialize the delays
  54. void Echo::initdelays(void)
  55. {
  56. cleanup();
  57. //number of seconds to delay left chan
  58. float dl = avgDelay - lrdelay;
  59. //number of seconds to delay right chan
  60. float dr = avgDelay + lrdelay;
  61. ndelta.l = max(1, (int) (dl * samplerate));
  62. ndelta.r = max(1, (int) (dr * samplerate));
  63. delta = ndelta;
  64. }
  65. //Effect output
  66. void Echo::out(const Stereo<float *> &input)
  67. {
  68. for(int i = 0; i < buffersize; ++i) {
  69. float ldl = delay.l[pos.l];
  70. float rdl = delay.r[pos.r];
  71. ldl = ldl * (1.0f - lrcross) + rdl * lrcross;
  72. rdl = rdl * (1.0f - lrcross) + ldl * lrcross;
  73. efxoutl[i] = ldl * 2.0f;
  74. efxoutr[i] = rdl * 2.0f;
  75. ldl = input.l[i] * pangainL - ldl * fb;
  76. rdl = input.r[i] * pangainR - rdl * fb;
  77. //LowPass Filter
  78. old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * samplerate)] =
  79. ldl * hidamp + old.l * (1.0f - hidamp);
  80. old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * samplerate)] =
  81. rdl * hidamp + old.r * (1.0f - hidamp);
  82. //increment
  83. ++pos.l; // += delta.l;
  84. ++pos.r; // += delta.r;
  85. //ensure that pos is still in bounds
  86. pos.l %= MAX_DELAY * samplerate;
  87. pos.r %= MAX_DELAY * samplerate;
  88. //adjust delay if needed
  89. delta.l = (15 * delta.l + ndelta.l) / 16;
  90. delta.r = (15 * delta.r + ndelta.r) / 16;
  91. }
  92. }
  93. //Parameter control
  94. void Echo::setvolume(unsigned char _Pvolume)
  95. {
  96. Pvolume = _Pvolume;
  97. if(insertion == 0) {
  98. outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
  99. volume = 1.0f;
  100. }
  101. else
  102. volume = outvolume = Pvolume / 127.0f;
  103. if(Pvolume == 0)
  104. cleanup();
  105. }
  106. void Echo::setdelay(unsigned char _Pdelay)
  107. {
  108. Pdelay = _Pdelay;
  109. avgDelay = (Pdelay / 127.0f * 1.5f); //0 .. 1.5 sec
  110. initdelays();
  111. }
  112. void Echo::setlrdelay(unsigned char _Plrdelay)
  113. {
  114. float tmp;
  115. Plrdelay = _Plrdelay;
  116. tmp =
  117. (powf(2.0f, fabsf(Plrdelay - 64.0f) / 64.0f * 9.0f) - 1.0f) / 1000.0f;
  118. if(Plrdelay < 64.0f)
  119. tmp = -tmp;
  120. lrdelay = tmp;
  121. initdelays();
  122. }
  123. void Echo::setfb(unsigned char _Pfb)
  124. {
  125. Pfb = _Pfb;
  126. fb = Pfb / 128.0f;
  127. }
  128. void Echo::sethidamp(unsigned char _Phidamp)
  129. {
  130. Phidamp = _Phidamp;
  131. hidamp = 1.0f - Phidamp / 127.0f;
  132. }
  133. void Echo::setpreset(unsigned char npreset)
  134. {
  135. const int PRESET_SIZE = 7;
  136. const int NUM_PRESETS = 9;
  137. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  138. {67, 64, 35, 64, 30, 59, 0 }, //Echo 1
  139. {67, 64, 21, 64, 30, 59, 0 }, //Echo 2
  140. {67, 75, 60, 64, 30, 59, 10}, //Echo 3
  141. {67, 60, 44, 64, 30, 0, 0 }, //Simple Echo
  142. {67, 60, 102, 50, 30, 82, 48}, //Canyon
  143. {67, 64, 44, 17, 0, 82, 24}, //Panning Echo 1
  144. {81, 60, 46, 118, 100, 68, 18}, //Panning Echo 2
  145. {81, 60, 26, 100, 127, 67, 36}, //Panning Echo 3
  146. {62, 64, 28, 64, 100, 90, 55} //Feedback Echo
  147. };
  148. if(npreset >= NUM_PRESETS)
  149. npreset = NUM_PRESETS - 1;
  150. for(int n = 0; n < PRESET_SIZE; ++n)
  151. changepar(n, presets[npreset][n]);
  152. if(insertion)
  153. setvolume(presets[npreset][0] / 2); //lower the volume if this is insertion effect
  154. Ppreset = npreset;
  155. }
  156. void Echo::changepar(int npar, unsigned char value)
  157. {
  158. switch(npar) {
  159. case 0:
  160. setvolume(value);
  161. break;
  162. case 1:
  163. setpanning(value);
  164. break;
  165. case 2:
  166. setdelay(value);
  167. break;
  168. case 3:
  169. setlrdelay(value);
  170. break;
  171. case 4:
  172. setlrcross(value);
  173. break;
  174. case 5:
  175. setfb(value);
  176. break;
  177. case 6:
  178. sethidamp(value);
  179. break;
  180. }
  181. }
  182. unsigned char Echo::getpar(int npar) const
  183. {
  184. switch(npar) {
  185. case 0: return Pvolume;
  186. case 1: return Ppanning;
  187. case 2: return Pdelay;
  188. case 3: return Plrdelay;
  189. case 4: return Plrcross;
  190. case 5: return Pfb;
  191. case 6: return Phidamp;
  192. default: return 0; // in case of bogus parameter number
  193. }
  194. }