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.

518 lines
14KB

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