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.

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