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.

227 lines
5.5KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Alienwah.cpp - "AlienWah" effect
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Author: Nasca Octavian Paul
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include <cmath>
  12. #include "../Misc/Allocator.h"
  13. #include "Alienwah.h"
  14. using std::complex;
  15. Alienwah::Alienwah(EffectParams pars)
  16. :Effect(pars),
  17. lfo(pars.srate, pars.bufsize),
  18. oldl(NULL),
  19. oldr(NULL)
  20. {
  21. setpreset(Ppreset);
  22. cleanup();
  23. oldclfol = complex<float>(fb, 0.0f);
  24. oldclfor = complex<float>(fb, 0.0f);
  25. }
  26. Alienwah::~Alienwah()
  27. {
  28. memory.devalloc(oldl);
  29. memory.devalloc(oldr);
  30. }
  31. //Apply the effect
  32. void Alienwah::out(const Stereo<float *> &smp)
  33. {
  34. float lfol, lfor; //Left/Right LFOs
  35. complex<float> clfol, clfor;
  36. /**\todo Rework, as optimization can be used when the new complex type is
  37. * utilized.
  38. * Before all calculations needed to be done with individual float,
  39. * but now they can be done together*/
  40. lfo.effectlfoout(&lfol, &lfor);
  41. lfol *= depth * PI * 2.0f;
  42. lfor *= depth * PI * 2.0f;
  43. clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework
  44. clfor = complex<float>(cosf(lfor + phase) * fb, sinf(lfor + phase) * fb); //rework
  45. for(int i = 0; i < buffersize; ++i) {
  46. float x = ((float) i) / buffersize_f;
  47. float x1 = 1.0f - x;
  48. //left
  49. complex<float> tmp = clfol * x + oldclfol * x1;
  50. complex<float> out = tmp * oldl[oldk];
  51. out += (1 - fabs(fb)) * smp.l[i] * pangainL;
  52. oldl[oldk] = out;
  53. float l = out.real() * 10.0f * (fb + 0.1f);
  54. //right
  55. tmp = clfor * x + oldclfor * x1;
  56. out = tmp * oldr[oldk];
  57. out += (1 - fabs(fb)) * smp.r[i] * pangainR;
  58. oldr[oldk] = out;
  59. float r = out.real() * 10.0f * (fb + 0.1f);
  60. if(++oldk >= Pdelay)
  61. oldk = 0;
  62. //LRcross
  63. efxoutl[i] = l * (1.0f - lrcross) + r * lrcross;
  64. efxoutr[i] = r * (1.0f - lrcross) + l * lrcross;
  65. }
  66. oldclfol = clfol;
  67. oldclfor = clfor;
  68. }
  69. //Cleanup the effect
  70. void Alienwah::cleanup(void)
  71. {
  72. for(int i = 0; i < Pdelay; ++i) {
  73. oldl[i] = complex<float>(0.0f, 0.0f);
  74. oldr[i] = complex<float>(0.0f, 0.0f);
  75. }
  76. oldk = 0;
  77. }
  78. //Parameter control
  79. void Alienwah::setdepth(unsigned char _Pdepth)
  80. {
  81. Pdepth = _Pdepth;
  82. depth = Pdepth / 127.0f;
  83. }
  84. void Alienwah::setfb(unsigned char _Pfb)
  85. {
  86. Pfb = _Pfb;
  87. fb = fabs((Pfb - 64.0f) / 64.1f);
  88. fb = sqrtf(fb);
  89. if(fb < 0.4f)
  90. fb = 0.4f;
  91. if(Pfb < 64)
  92. fb = -fb;
  93. }
  94. void Alienwah::setvolume(unsigned char _Pvolume)
  95. {
  96. Pvolume = _Pvolume;
  97. outvolume = Pvolume / 127.0f;
  98. if(insertion == 0)
  99. volume = 1.0f;
  100. else
  101. volume = outvolume;
  102. }
  103. void Alienwah::setphase(unsigned char _Pphase)
  104. {
  105. Pphase = _Pphase;
  106. phase = (Pphase - 64.0f) / 64.0f * PI;
  107. }
  108. void Alienwah::setdelay(unsigned char _Pdelay)
  109. {
  110. memory.devalloc(oldl);
  111. memory.devalloc(oldr);
  112. Pdelay = (_Pdelay >= MAX_ALIENWAH_DELAY) ? MAX_ALIENWAH_DELAY : _Pdelay;
  113. oldl = memory.valloc<complex<float>>(Pdelay);
  114. oldr = memory.valloc<complex<float>>(Pdelay);
  115. cleanup();
  116. }
  117. void Alienwah::setpreset(unsigned char npreset)
  118. {
  119. const int PRESET_SIZE = 11;
  120. const int NUM_PRESETS = 4;
  121. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  122. //AlienWah1
  123. {127, 64, 70, 0, 0, 62, 60, 105, 25, 0, 64},
  124. //AlienWah2
  125. {127, 64, 73, 106, 0, 101, 60, 105, 17, 0, 64},
  126. //AlienWah3
  127. {127, 64, 63, 0, 1, 100, 112, 105, 31, 0, 42},
  128. //AlienWah4
  129. {93, 64, 25, 0, 1, 66, 101, 11, 47, 0, 86}
  130. };
  131. if(npreset >= NUM_PRESETS)
  132. npreset = NUM_PRESETS - 1;
  133. for(int n = 0; n < PRESET_SIZE; ++n)
  134. changepar(n, presets[npreset][n]);
  135. if(insertion == 0)
  136. changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect
  137. Ppreset = npreset;
  138. }
  139. void Alienwah::changepar(int npar, unsigned char value)
  140. {
  141. switch(npar) {
  142. case 0:
  143. setvolume(value);
  144. break;
  145. case 1:
  146. setpanning(value);
  147. break;
  148. case 2:
  149. lfo.Pfreq = value;
  150. lfo.updateparams();
  151. break;
  152. case 3:
  153. lfo.Prandomness = value;
  154. lfo.updateparams();
  155. break;
  156. case 4:
  157. lfo.PLFOtype = value;
  158. lfo.updateparams();
  159. break;
  160. case 5:
  161. lfo.Pstereo = value;
  162. lfo.updateparams();
  163. break;
  164. case 6:
  165. setdepth(value);
  166. break;
  167. case 7:
  168. setfb(value);
  169. break;
  170. case 8:
  171. setdelay(value);
  172. break;
  173. case 9:
  174. setlrcross(value);
  175. break;
  176. case 10:
  177. setphase(value);
  178. break;
  179. }
  180. }
  181. unsigned char Alienwah::getpar(int npar) const
  182. {
  183. switch(npar) {
  184. case 0: return Pvolume;
  185. case 1: return Ppanning;
  186. case 2: return lfo.Pfreq;
  187. case 3: return lfo.Prandomness;
  188. case 4: return lfo.PLFOtype;
  189. case 5: return lfo.Pstereo;
  190. case 6: return Pdepth;
  191. case 7: return Pfb;
  192. case 8: return Pdelay;
  193. case 9: return Plrcross;
  194. case 10: return Pphase;
  195. default: return 0;
  196. }
  197. }