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.

270 lines
7.4KB

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