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.

236 lines
6.0KB

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