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.

466 lines
12KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. EffectMgr.cpp - Effect manager, an interface betwen the program and 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 <rtosc/ports.h>
  12. #include <rtosc/port-sugar.h>
  13. #include <iostream>
  14. #include "EffectMgr.h"
  15. #include "Effect.h"
  16. #include "Alienwah.h"
  17. #include "Reverb.h"
  18. #include "Echo.h"
  19. #include "Chorus.h"
  20. #include "Distorsion.h"
  21. #include "EQ.h"
  22. #include "DynamicFilter.h"
  23. #include "Phaser.h"
  24. #include "../Misc/XMLwrapper.h"
  25. #include "../Misc/Util.h"
  26. #include "../Params/FilterParams.h"
  27. #include "../Misc/Allocator.h"
  28. #define rObject EffectMgr
  29. static const rtosc::Ports local_ports = {
  30. rSelf(EffectMgr),
  31. rPaste,
  32. rRecurp(filterpars, "Filter Parameter for Dynamic Filter"),
  33. {"parameter#128::i:T:F", rProp(parameter) rProp(alias) rLinear(0,127) rDoc("Parameter Accessor"),
  34. NULL,
  35. [](const char *msg, rtosc::RtData &d)
  36. {
  37. EffectMgr *eff = (EffectMgr*)d.obj;
  38. const char *mm = msg;
  39. while(!isdigit(*mm))++mm;
  40. if(!rtosc_narguments(msg))
  41. d.reply(d.loc, "i", eff->geteffectparrt(atoi(mm)));
  42. else if(rtosc_type(msg, 0) == 'i'){
  43. eff->seteffectparrt(atoi(mm), rtosc_argument(msg, 0).i);
  44. d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
  45. } else if(rtosc_type(msg, 0) == 'T'){
  46. eff->seteffectparrt(atoi(mm), 127);
  47. d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
  48. } else if(rtosc_type(msg, 0) == 'F'){
  49. eff->seteffectparrt(atoi(mm), 0);
  50. d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
  51. }
  52. }},
  53. {"preset::i", rProp(parameter) rProp(alias) rDoc("Effect Preset Selector"), NULL,
  54. [](const char *msg, rtosc::RtData &d)
  55. {
  56. char loc[1024];
  57. EffectMgr *eff = (EffectMgr*)d.obj;
  58. if(!rtosc_narguments(msg))
  59. d.reply(d.loc, "i", eff->getpreset());
  60. else {
  61. eff->changepresetrt(rtosc_argument(msg, 0).i);
  62. d.broadcast(d.loc, "i", eff->getpreset());
  63. //update parameters as well
  64. strncpy(loc, d.loc, 1024);
  65. char *tail = rindex(loc, '/');
  66. if(!tail)
  67. return;
  68. for(int i=0;i<128;++i) {
  69. sprintf(tail+1, "parameter%d", i);
  70. d.broadcast(loc, "i", eff->geteffectparrt(i));
  71. }
  72. }
  73. }},
  74. {"eq-coeffs:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL,
  75. [](const char *, rtosc::RtData &d)
  76. {
  77. EffectMgr *eff = (EffectMgr*)d.obj;
  78. if(eff->nefx != 7)
  79. return;
  80. EQ *eq = (EQ*)eff->efx;
  81. float a[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
  82. float b[MAX_EQ_BANDS*MAX_FILTER_STAGES*3];
  83. memset(a, 0, sizeof(a));
  84. memset(b, 0, sizeof(b));
  85. eq->getFilter(a,b);
  86. d.reply(d.loc, "bb", sizeof(a), a, sizeof(b), b);
  87. }},
  88. {"efftype::i", rProp(parameter) rDoc("Get Effect Type"), NULL,
  89. [](const char *m, rtosc::RtData &d)
  90. {
  91. EffectMgr *eff = (EffectMgr*)d.obj;
  92. if(rtosc_narguments(m)) {
  93. eff->changeeffectrt(rtosc_argument(m,0).i);
  94. d.broadcast(d.loc, "i", eff->nefx);
  95. } else
  96. d.reply(d.loc, "i", eff->nefx);
  97. }},
  98. {"efftype:b", rProp(internal) rDoc("Pointer swap EffectMgr"), NULL,
  99. [](const char *msg, rtosc::RtData &d)
  100. {
  101. printf("OBSOLETE METHOD CALLED\n");
  102. EffectMgr *eff = (EffectMgr*)d.obj;
  103. EffectMgr *eff_ = *(EffectMgr**)rtosc_argument(msg,0).b.data;
  104. //Lets trade data
  105. std::swap(eff->nefx,eff_->nefx);
  106. std::swap(eff->efx,eff_->efx);
  107. std::swap(eff->filterpars,eff_->filterpars);
  108. std::swap(eff->efxoutl, eff_->efxoutl);
  109. std::swap(eff->efxoutr, eff_->efxoutr);
  110. //Return the old data for distruction
  111. d.reply("/free", "sb", "EffectMgr", sizeof(EffectMgr*), &eff_);
  112. }},
  113. };
  114. const rtosc::Ports &EffectMgr::ports = local_ports;
  115. EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_,
  116. const bool insertion_, const AbsTime *time_)
  117. :insertion(insertion_),
  118. efxoutl(new float[synth_.buffersize]),
  119. efxoutr(new float[synth_.buffersize]),
  120. filterpars(NULL),
  121. nefx(0),
  122. efx(NULL),
  123. time(time_),
  124. dryonly(false),
  125. memory(alloc),
  126. synth(synth_)
  127. {
  128. setpresettype("Peffect");
  129. memset(efxoutl, 0, synth.bufferbytes);
  130. memset(efxoutr, 0, synth.bufferbytes);
  131. memset(settings, 0, sizeof(settings));
  132. defaults();
  133. }
  134. EffectMgr::~EffectMgr()
  135. {
  136. memory.dealloc(efx);
  137. delete [] efxoutl;
  138. delete [] efxoutr;
  139. }
  140. void EffectMgr::defaults(void)
  141. {
  142. changeeffect(0);
  143. setdryonly(false);
  144. }
  145. //Change the effect
  146. void EffectMgr::changeeffectrt(int _nefx, bool avoidSmash)
  147. {
  148. cleanup();
  149. if(nefx == _nefx && efx != NULL)
  150. return;
  151. nefx = _nefx;
  152. memset(efxoutl, 0, synth.bufferbytes);
  153. memset(efxoutr, 0, synth.bufferbytes);
  154. memory.dealloc(efx);
  155. EffectParams pars(memory, insertion, efxoutl, efxoutr, 0,
  156. synth.samplerate, synth.buffersize);
  157. try {
  158. switch (nefx) {
  159. case 1:
  160. efx = memory.alloc<Reverb>(pars);
  161. break;
  162. case 2:
  163. efx = memory.alloc<Echo>(pars);
  164. break;
  165. case 3:
  166. efx = memory.alloc<Chorus>(pars);
  167. break;
  168. case 4:
  169. efx = memory.alloc<Phaser>(pars);
  170. break;
  171. case 5:
  172. efx = memory.alloc<Alienwah>(pars);
  173. break;
  174. case 6:
  175. efx = memory.alloc<Distorsion>(pars);
  176. break;
  177. case 7:
  178. efx = memory.alloc<EQ>(pars);
  179. break;
  180. case 8:
  181. efx = memory.alloc<DynamicFilter>(pars, time);
  182. break;
  183. //put more effect here
  184. default:
  185. efx = NULL;
  186. break; //no effect (thru)
  187. }
  188. } catch (std::bad_alloc &ba) {
  189. std::cerr << "failed to change effect " << _nefx << ": " << ba.what() << std::endl;
  190. return;
  191. }
  192. if(efx)
  193. filterpars = efx->filterpars;
  194. if(!avoidSmash)
  195. for(int i=0; i<128; ++i)
  196. settings[i] = geteffectparrt(i);
  197. }
  198. void EffectMgr::changeeffect(int _nefx)
  199. {
  200. nefx = _nefx;
  201. //preset = 0;
  202. //memset(settings, 0, sizeof(settings));
  203. }
  204. //Obtain the effect number
  205. int EffectMgr::geteffect(void)
  206. {
  207. return nefx;
  208. }
  209. // Initialize An Effect in RT context
  210. void EffectMgr::init(void)
  211. {
  212. kill();
  213. changeeffectrt(nefx, true);
  214. changepresetrt(preset, true);
  215. for(int i=0; i<128; ++i)
  216. seteffectparrt(i, settings[i]);
  217. }
  218. //Strip effect manager of it's realtime memory
  219. void EffectMgr::kill(void)
  220. {
  221. //printf("Killing Effect(%d)\n", nefx);
  222. memory.dealloc(efx);
  223. }
  224. // Cleanup the current effect
  225. void EffectMgr::cleanup(void)
  226. {
  227. if(efx)
  228. efx->cleanup();
  229. }
  230. // Get the preset of the current effect
  231. unsigned char EffectMgr::getpreset(void)
  232. {
  233. if(efx)
  234. return efx->Ppreset;
  235. else
  236. return 0;
  237. }
  238. // Change the preset of the current effect
  239. void EffectMgr::changepreset(unsigned char npreset)
  240. {
  241. preset = npreset;
  242. }
  243. // Change the preset of the current effect
  244. void EffectMgr::changepresetrt(unsigned char npreset, bool avoidSmash)
  245. {
  246. preset = npreset;
  247. if(efx)
  248. efx->setpreset(npreset);
  249. if(!avoidSmash)
  250. for(int i=0; i<128; ++i)
  251. settings[i] = geteffectparrt(i);
  252. }
  253. //Change a parameter of the current effect
  254. void EffectMgr::seteffectparrt(int npar, unsigned char value)
  255. {
  256. if(npar<128)
  257. settings[npar] = value;
  258. if(!efx)
  259. return;
  260. try {
  261. efx->changepar(npar, value);
  262. } catch (std::bad_alloc &ba) {
  263. std::cerr << "failed to change effect parameter " << npar << " to " << value << ": " << ba.what() << std::endl;
  264. }
  265. }
  266. //Change a parameter of the current effect
  267. void EffectMgr::seteffectpar(int npar, unsigned char value)
  268. {
  269. settings[npar] = value;
  270. }
  271. //Get a parameter of the current effect
  272. unsigned char EffectMgr::geteffectpar(int npar)
  273. {
  274. if(npar<128)
  275. return settings[npar];
  276. if(!efx)
  277. return 0;
  278. return efx->getpar(npar);
  279. }
  280. unsigned char EffectMgr::geteffectparrt(int npar)
  281. {
  282. if(!efx)
  283. return 0;
  284. return efx->getpar(npar);
  285. }
  286. // Apply the effect
  287. void EffectMgr::out(float *smpsl, float *smpsr)
  288. {
  289. if(!efx) {
  290. if(!insertion)
  291. for(int i = 0; i < synth.buffersize; ++i) {
  292. smpsl[i] = 0.0f;
  293. smpsr[i] = 0.0f;
  294. efxoutl[i] = 0.0f;
  295. efxoutr[i] = 0.0f;
  296. }
  297. return;
  298. }
  299. for(int i = 0; i < synth.buffersize; ++i) {
  300. smpsl[i] += synth.denormalkillbuf[i];
  301. smpsr[i] += synth.denormalkillbuf[i];
  302. efxoutl[i] = 0.0f;
  303. efxoutr[i] = 0.0f;
  304. }
  305. efx->out(smpsl, smpsr);
  306. float volume = efx->volume;
  307. if(nefx == 7) { //this is need only for the EQ effect
  308. memcpy(smpsl, efxoutl, synth.bufferbytes);
  309. memcpy(smpsr, efxoutr, synth.bufferbytes);
  310. return;
  311. }
  312. //Insertion effect
  313. if(insertion != 0) {
  314. float v1, v2;
  315. if(volume < 0.5f) {
  316. v1 = 1.0f;
  317. v2 = volume * 2.0f;
  318. }
  319. else {
  320. v1 = (1.0f - volume) * 2.0f;
  321. v2 = 1.0f;
  322. }
  323. if((nefx == 1) || (nefx == 2))
  324. v2 *= v2; //for Reverb and Echo, the wet function is not liniar
  325. if(dryonly) //this is used for instrument effect only
  326. for(int i = 0; i < synth.buffersize; ++i) {
  327. smpsl[i] *= v1;
  328. smpsr[i] *= v1;
  329. efxoutl[i] *= v2;
  330. efxoutr[i] *= v2;
  331. }
  332. else // normal instrument/insertion effect
  333. for(int i = 0; i < synth.buffersize; ++i) {
  334. smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2;
  335. smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2;
  336. }
  337. }
  338. else // System effect
  339. for(int i = 0; i < synth.buffersize; ++i) {
  340. efxoutl[i] *= 2.0f * volume;
  341. efxoutr[i] *= 2.0f * volume;
  342. smpsl[i] = efxoutl[i];
  343. smpsr[i] = efxoutr[i];
  344. }
  345. }
  346. // Get the effect volume for the system effect
  347. float EffectMgr::sysefxgetvolume(void)
  348. {
  349. return efx ? efx->outvolume : 1.0f;
  350. }
  351. // Get the EQ response
  352. float EffectMgr::getEQfreqresponse(float freq)
  353. {
  354. return (nefx == 7) ? efx->getfreqresponse(freq) : 0.0f;
  355. }
  356. void EffectMgr::setdryonly(bool value)
  357. {
  358. dryonly = value;
  359. }
  360. void EffectMgr::paste(EffectMgr &e)
  361. {
  362. changeeffectrt(e.nefx, true);
  363. changepresetrt(e.preset, true);
  364. for(int i=0;i<128;++i)
  365. seteffectparrt(i, e.settings[i]);
  366. }
  367. void EffectMgr::add2XML(XMLwrapper& xml)
  368. {
  369. xml.addpar("type", geteffect());
  370. if(!geteffect())
  371. return;
  372. xml.addpar("preset", preset);
  373. xml.beginbranch("EFFECT_PARAMETERS");
  374. for(int n = 0; n < 128; ++n) {
  375. int par = geteffectpar(n);
  376. if(par == 0)
  377. continue;
  378. xml.beginbranch("par_no", n);
  379. xml.addpar("par", par);
  380. xml.endbranch();
  381. }
  382. if(filterpars) {
  383. xml.beginbranch("FILTER");
  384. filterpars->add2XML(xml);
  385. xml.endbranch();
  386. }
  387. xml.endbranch();
  388. }
  389. void EffectMgr::getfromXML(XMLwrapper& xml)
  390. {
  391. changeeffect(xml.getpar127("type", geteffect()));
  392. if(!geteffect())
  393. return;
  394. preset = xml.getpar127("preset", preset);
  395. if(xml.enterbranch("EFFECT_PARAMETERS")) {
  396. for(int n = 0; n < 128; ++n) {
  397. seteffectpar(n, 0); //erase effect parameter
  398. if(xml.enterbranch("par_no", n) == 0)
  399. continue;
  400. int par = geteffectpar(n);
  401. seteffectpar(n, xml.getpar127("par", par));
  402. xml.exitbranch();
  403. }
  404. if(filterpars)
  405. if(xml.enterbranch("FILTER")) {
  406. filterpars->getfromXML(xml);
  407. xml.exitbranch();
  408. }
  409. xml.exitbranch();
  410. }
  411. cleanup();
  412. }