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.

481 lines
13KB

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