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.

248 lines
6.3KB

  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 <rtosc/ports.h>
  15. #include <rtosc/port-sugar.h>
  16. #include "../Misc/Allocator.h"
  17. #include "Echo.h"
  18. #define MAX_DELAY 2
  19. #define rObject Echo
  20. #define rBegin [](const char *, rtosc::RtData &) {
  21. #define rEnd }
  22. rtosc::Ports Echo::ports = {
  23. {"preset::i", rOptions(Echo 1, Echo 2, Echo 3, Simple Echo, Canyon, Panning Echo 1, Panning Echo 2, Panning Echo 3, Feedback Echo)
  24. rProp(parameter)
  25. rDoc("Instrument Presets"), 0,
  26. rBegin;
  27. rEnd},
  28. //Pvolume/Ppanning are common
  29. rEffPar(Pdelay, 2, rShort("delay"), "Length of Echo"),
  30. rEffPar(Plrdelay, 3, rShort("lr delay"), "Difference In Left/Right Delay"),
  31. rEffPar(Plrcross, 4, rShort("cross"), "Left/Right Crossover"),
  32. rEffPar(Pfb, 5, rShort("feedback"), "Echo Feedback"),
  33. rEffPar(Phidamp, 6, rShort("damp"), "Dampen High Frequencies"),
  34. };
  35. #undef rBegin
  36. #undef rEnd
  37. #undef rObject
  38. Echo::Echo(EffectParams pars)
  39. :Effect(pars),
  40. Pvolume(50),
  41. Pdelay(60),
  42. Plrdelay(100),
  43. Pfb(40),
  44. Phidamp(60),
  45. delayTime(1),
  46. lrdelay(0),
  47. avgDelay(0),
  48. delay(memory.valloc<float>(MAX_DELAY * pars.srate),
  49. memory.valloc<float>(MAX_DELAY * pars.srate)),
  50. old(0.0f),
  51. pos(0),
  52. delta(1),
  53. ndelta(1)
  54. {
  55. initdelays();
  56. setpreset(Ppreset);
  57. }
  58. Echo::~Echo()
  59. {
  60. memory.devalloc(delay.l);
  61. memory.devalloc(delay.r);
  62. }
  63. //Cleanup the effect
  64. void Echo::cleanup(void)
  65. {
  66. memset(delay.l, 0, MAX_DELAY * samplerate * sizeof(float));
  67. memset(delay.r, 0, MAX_DELAY * samplerate * sizeof(float));
  68. old = Stereo<float>(0.0f);
  69. }
  70. inline int max(int a, int b)
  71. {
  72. return a > b ? a : b;
  73. }
  74. //Initialize the delays
  75. void Echo::initdelays(void)
  76. {
  77. cleanup();
  78. //number of seconds to delay left chan
  79. float dl = avgDelay - lrdelay;
  80. //number of seconds to delay right chan
  81. float dr = avgDelay + lrdelay;
  82. ndelta.l = max(1, (int) (dl * samplerate));
  83. ndelta.r = max(1, (int) (dr * samplerate));
  84. delta = ndelta;
  85. }
  86. //Effect output
  87. void Echo::out(const Stereo<float *> &input)
  88. {
  89. for(int i = 0; i < buffersize; ++i) {
  90. float ldl = delay.l[pos.l];
  91. float rdl = delay.r[pos.r];
  92. ldl = ldl * (1.0f - lrcross) + rdl * lrcross;
  93. rdl = rdl * (1.0f - lrcross) + ldl * lrcross;
  94. efxoutl[i] = ldl * 2.0f;
  95. efxoutr[i] = rdl * 2.0f;
  96. ldl = input.l[i] * pangainL - ldl * fb;
  97. rdl = input.r[i] * pangainR - rdl * fb;
  98. //LowPass Filter
  99. old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * samplerate)] =
  100. ldl * hidamp + old.l * (1.0f - hidamp);
  101. old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * samplerate)] =
  102. rdl * hidamp + old.r * (1.0f - hidamp);
  103. //increment
  104. ++pos.l; // += delta.l;
  105. ++pos.r; // += delta.r;
  106. //ensure that pos is still in bounds
  107. pos.l %= MAX_DELAY * samplerate;
  108. pos.r %= MAX_DELAY * samplerate;
  109. //adjust delay if needed
  110. delta.l = (15 * delta.l + ndelta.l) / 16;
  111. delta.r = (15 * delta.r + ndelta.r) / 16;
  112. }
  113. }
  114. //Parameter control
  115. void Echo::setvolume(unsigned char _Pvolume)
  116. {
  117. Pvolume = _Pvolume;
  118. if(insertion == 0) {
  119. outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
  120. volume = 1.0f;
  121. }
  122. else
  123. volume = outvolume = Pvolume / 127.0f;
  124. if(Pvolume == 0)
  125. cleanup();
  126. }
  127. void Echo::setdelay(unsigned char _Pdelay)
  128. {
  129. Pdelay = _Pdelay;
  130. avgDelay = (Pdelay / 127.0f * 1.5f); //0 .. 1.5 sec
  131. initdelays();
  132. }
  133. void Echo::setlrdelay(unsigned char _Plrdelay)
  134. {
  135. float tmp;
  136. Plrdelay = _Plrdelay;
  137. tmp =
  138. (powf(2.0f, fabsf(Plrdelay - 64.0f) / 64.0f * 9.0f) - 1.0f) / 1000.0f;
  139. if(Plrdelay < 64.0f)
  140. tmp = -tmp;
  141. lrdelay = tmp;
  142. initdelays();
  143. }
  144. void Echo::setfb(unsigned char _Pfb)
  145. {
  146. Pfb = _Pfb;
  147. fb = Pfb / 128.0f;
  148. }
  149. void Echo::sethidamp(unsigned char _Phidamp)
  150. {
  151. Phidamp = _Phidamp;
  152. hidamp = 1.0f - Phidamp / 127.0f;
  153. }
  154. void Echo::setpreset(unsigned char npreset)
  155. {
  156. const int PRESET_SIZE = 7;
  157. const int NUM_PRESETS = 9;
  158. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  159. {67, 64, 35, 64, 30, 59, 0 }, //Echo 1
  160. {67, 64, 21, 64, 30, 59, 0 }, //Echo 2
  161. {67, 75, 60, 64, 30, 59, 10}, //Echo 3
  162. {67, 60, 44, 64, 30, 0, 0 }, //Simple Echo
  163. {67, 60, 102, 50, 30, 82, 48}, //Canyon
  164. {67, 64, 44, 17, 0, 82, 24}, //Panning Echo 1
  165. {81, 60, 46, 118, 100, 68, 18}, //Panning Echo 2
  166. {81, 60, 26, 100, 127, 67, 36}, //Panning Echo 3
  167. {62, 64, 28, 64, 100, 90, 55} //Feedback Echo
  168. };
  169. if(npreset >= NUM_PRESETS)
  170. npreset = NUM_PRESETS - 1;
  171. for(int n = 0; n < PRESET_SIZE; ++n)
  172. changepar(n, presets[npreset][n]);
  173. if(insertion)
  174. setvolume(presets[npreset][0] / 2); //lower the volume if this is insertion effect
  175. Ppreset = npreset;
  176. }
  177. void Echo::changepar(int npar, unsigned char value)
  178. {
  179. switch(npar) {
  180. case 0:
  181. setvolume(value);
  182. break;
  183. case 1:
  184. setpanning(value);
  185. break;
  186. case 2:
  187. setdelay(value);
  188. break;
  189. case 3:
  190. setlrdelay(value);
  191. break;
  192. case 4:
  193. setlrcross(value);
  194. break;
  195. case 5:
  196. setfb(value);
  197. break;
  198. case 6:
  199. sethidamp(value);
  200. break;
  201. }
  202. }
  203. unsigned char Echo::getpar(int npar) const
  204. {
  205. switch(npar) {
  206. case 0: return Pvolume;
  207. case 1: return Ppanning;
  208. case 2: return Pdelay;
  209. case 3: return Plrdelay;
  210. case 4: return Plrcross;
  211. case 5: return Pfb;
  212. case 6: return Phidamp;
  213. default: return 0; // in case of bogus parameter number
  214. }
  215. }