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.

261 lines
7.0KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Chorus.cpp - Chorus and Flange effects
  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 "Chorus.h"
  14. #include <iostream>
  15. using namespace std;
  16. Chorus::Chorus(EffectParams pars)
  17. :Effect(pars),
  18. lfo(pars.srate, pars.bufsize),
  19. maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * samplerate_f)),
  20. delaySample(memory.valloc<float>(maxdelay), memory.valloc<float>(maxdelay))
  21. {
  22. dlk = 0;
  23. drk = 0;
  24. setpreset(Ppreset);
  25. changepar(1, 64);
  26. lfo.effectlfoout(&lfol, &lfor);
  27. dl2 = getdelay(lfol);
  28. dr2 = getdelay(lfor);
  29. cleanup();
  30. }
  31. Chorus::~Chorus()
  32. {
  33. memory.devalloc(delaySample.l);
  34. memory.devalloc(delaySample.r);
  35. }
  36. //get the delay value in samples; xlfo is the current lfo value
  37. float Chorus::getdelay(float xlfo)
  38. {
  39. float result =
  40. (Pflangemode) ? 0 : (delay + xlfo * depth) * samplerate_f;
  41. //check if delay is too big (caused by bad setdelay() and setdepth()
  42. if((result + 0.5f) >= maxdelay) {
  43. cerr
  44. <<
  45. "WARNING: Chorus.cpp::getdelay(..) too big delay (see setdelay and setdepth funcs.)"
  46. << endl;
  47. result = maxdelay - 1.0f;
  48. }
  49. return result;
  50. }
  51. //Apply the effect
  52. void Chorus::out(const Stereo<float *> &input)
  53. {
  54. dl1 = dl2;
  55. dr1 = dr2;
  56. lfo.effectlfoout(&lfol, &lfor);
  57. dl2 = getdelay(lfol);
  58. dr2 = getdelay(lfor);
  59. for(int i = 0; i < buffersize; ++i) {
  60. float inL = input.l[i];
  61. float inR = input.r[i];
  62. //LRcross
  63. Stereo<float> tmpc(inL, inR);
  64. inL = tmpc.l * (1.0f - lrcross) + tmpc.r * lrcross;
  65. inR = tmpc.r * (1.0f - lrcross) + tmpc.l * lrcross;
  66. //Left channel
  67. //compute the delay in samples using linear interpolation between the lfo delays
  68. float mdel =
  69. (dl1 * (buffersize - i) + dl2 * i) / buffersize_f;
  70. if(++dlk >= maxdelay)
  71. dlk = 0;
  72. float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from
  73. dlhi = (int) tmp;
  74. dlhi %= maxdelay;
  75. float dlhi2 = (dlhi - 1 + maxdelay) % maxdelay;
  76. float dllo = 1.0f + floorf(tmp) - tmp;
  77. efxoutl[i] = cinterpolate(delaySample.l, maxdelay, dlhi2) * dllo
  78. + cinterpolate(delaySample.l, maxdelay,
  79. dlhi) * (1.0f - dllo);
  80. delaySample.l[dlk] = inL + efxoutl[i] * fb;
  81. //Right channel
  82. //compute the delay in samples using linear interpolation between the lfo delays
  83. mdel = (dr1 * (buffersize - i) + dr2 * i) / buffersize_f;
  84. if(++drk >= maxdelay)
  85. drk = 0;
  86. tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from
  87. dlhi = (int) tmp;
  88. dlhi %= maxdelay;
  89. dlhi2 = (dlhi - 1 + maxdelay) % maxdelay;
  90. dllo = 1.0f + floorf(tmp) - tmp;
  91. efxoutr[i] = cinterpolate(delaySample.r, maxdelay, dlhi2) * dllo
  92. + cinterpolate(delaySample.r, maxdelay,
  93. dlhi) * (1.0f - dllo);
  94. delaySample.r[dlk] = inR + efxoutr[i] * fb;
  95. }
  96. if(Poutsub)
  97. for(int i = 0; i < buffersize; ++i) {
  98. efxoutl[i] *= -1.0f;
  99. efxoutr[i] *= -1.0f;
  100. }
  101. for(int i = 0; i < buffersize; ++i) {
  102. efxoutl[i] *= pangainL;
  103. efxoutr[i] *= pangainR;
  104. }
  105. }
  106. //Cleanup the effect
  107. void Chorus::cleanup(void)
  108. {
  109. memset(delaySample.l, 0, maxdelay * sizeof(float));
  110. memset(delaySample.r, 0, maxdelay * sizeof(float));
  111. }
  112. //Parameter control
  113. void Chorus::setdepth(unsigned char _Pdepth)
  114. {
  115. Pdepth = _Pdepth;
  116. depth = (powf(8.0f, (Pdepth / 127.0f) * 2.0f) - 1.0f) / 1000.0f; //seconds
  117. }
  118. void Chorus::setdelay(unsigned char _Pdelay)
  119. {
  120. Pdelay = _Pdelay;
  121. delay = (powf(10.0f, (Pdelay / 127.0f) * 2.0f) - 1.0f) / 1000.0f; //seconds
  122. }
  123. void Chorus::setfb(unsigned char _Pfb)
  124. {
  125. Pfb = _Pfb;
  126. fb = (Pfb - 64.0f) / 64.1f;
  127. }
  128. void Chorus::setvolume(unsigned char _Pvolume)
  129. {
  130. Pvolume = _Pvolume;
  131. outvolume = Pvolume / 127.0f;
  132. volume = (!insertion) ? 1.0f : outvolume;
  133. }
  134. void Chorus::setpreset(unsigned char npreset)
  135. {
  136. const int PRESET_SIZE = 12;
  137. const int NUM_PRESETS = 10;
  138. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  139. //Chorus1
  140. {64, 64, 50, 0, 0, 90, 40, 85, 64, 119, 0, 0},
  141. //Chorus2
  142. {64, 64, 45, 0, 0, 98, 56, 90, 64, 19, 0, 0},
  143. //Chorus3
  144. {64, 64, 29, 0, 1, 42, 97, 95, 90, 127, 0, 0},
  145. //Celeste1
  146. {64, 64, 26, 0, 0, 42, 115, 18, 90, 127, 0, 0},
  147. //Celeste2
  148. {64, 64, 29, 117, 0, 50, 115, 9, 31, 127, 0, 1},
  149. //Flange1
  150. {64, 64, 57, 0, 0, 60, 23, 3, 62, 0, 0, 0},
  151. //Flange2
  152. {64, 64, 33, 34, 1, 40, 35, 3, 109, 0, 0, 0},
  153. //Flange3
  154. {64, 64, 53, 34, 1, 94, 35, 3, 54, 0, 0, 1},
  155. //Flange4
  156. {64, 64, 40, 0, 1, 62, 12, 19, 97, 0, 0, 0},
  157. //Flange5
  158. {64, 64, 55, 105, 0, 24, 39, 19, 17, 0, 0, 1}
  159. };
  160. if(npreset >= NUM_PRESETS)
  161. npreset = NUM_PRESETS - 1;
  162. for(int n = 0; n < PRESET_SIZE; ++n)
  163. changepar(n, presets[npreset][n]);
  164. Ppreset = npreset;
  165. }
  166. void Chorus::changepar(int npar, unsigned char value)
  167. {
  168. switch(npar) {
  169. case 0:
  170. setvolume(value);
  171. break;
  172. case 1:
  173. setpanning(value);
  174. break;
  175. case 2:
  176. lfo.Pfreq = value;
  177. lfo.updateparams();
  178. break;
  179. case 3:
  180. lfo.Prandomness = value;
  181. lfo.updateparams();
  182. break;
  183. case 4:
  184. lfo.PLFOtype = value;
  185. lfo.updateparams();
  186. break;
  187. case 5:
  188. lfo.Pstereo = value;
  189. lfo.updateparams();
  190. break;
  191. case 6:
  192. setdepth(value);
  193. break;
  194. case 7:
  195. setdelay(value);
  196. break;
  197. case 8:
  198. setfb(value);
  199. break;
  200. case 9:
  201. setlrcross(value);
  202. break;
  203. case 10:
  204. Pflangemode = (value > 1) ? 1 : value;
  205. break;
  206. case 11:
  207. Poutsub = (value > 1) ? 1 : value;
  208. break;
  209. }
  210. }
  211. unsigned char Chorus::getpar(int npar) const
  212. {
  213. switch(npar) {
  214. case 0: return Pvolume;
  215. case 1: return Ppanning;
  216. case 2: return lfo.Pfreq;
  217. case 3: return lfo.Prandomness;
  218. case 4: return lfo.PLFOtype;
  219. case 5: return lfo.Pstereo;
  220. case 6: return Pdepth;
  221. case 7: return Pdelay;
  222. case 8: return Pfb;
  223. case 9: return Plrcross;
  224. case 10: return Pflangemode;
  225. case 11: return Poutsub;
  226. default: return 0;
  227. }
  228. }