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.

Alienwah.cpp 6.0KB

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