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.

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