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.

478 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(Echo),
  124. rSubtype(Alienwah),
  125. rSubtype(Distorsion),
  126. };
  127. const rtosc::Ports &EffectMgr::ports = local_ports;
  128. EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_,
  129. const bool insertion_, const AbsTime *time_)
  130. :insertion(insertion_),
  131. efxoutl(new float[synth_.buffersize]),
  132. efxoutr(new float[synth_.buffersize]),
  133. filterpars(NULL),
  134. nefx(0),
  135. efx(NULL),
  136. time(time_),
  137. dryonly(false),
  138. memory(alloc),
  139. synth(synth_)
  140. {
  141. setpresettype("Peffect");
  142. memset(efxoutl, 0, synth.bufferbytes);
  143. memset(efxoutr, 0, synth.bufferbytes);
  144. memset(settings, 0, sizeof(settings));
  145. defaults();
  146. }
  147. EffectMgr::~EffectMgr()
  148. {
  149. memory.dealloc(efx);
  150. delete [] efxoutl;
  151. delete [] efxoutr;
  152. }
  153. void EffectMgr::defaults(void)
  154. {
  155. changeeffect(0);
  156. setdryonly(false);
  157. }
  158. //Change the effect
  159. void EffectMgr::changeeffectrt(int _nefx, bool avoidSmash)
  160. {
  161. cleanup();
  162. if(nefx == _nefx && efx != NULL)
  163. return;
  164. nefx = _nefx;
  165. memset(efxoutl, 0, synth.bufferbytes);
  166. memset(efxoutr, 0, synth.bufferbytes);
  167. memory.dealloc(efx);
  168. EffectParams pars(memory, insertion, efxoutl, efxoutr, 0,
  169. synth.samplerate, synth.buffersize);
  170. try {
  171. switch (nefx) {
  172. case 1:
  173. efx = memory.alloc<Reverb>(pars);
  174. break;
  175. case 2:
  176. efx = memory.alloc<Echo>(pars);
  177. break;
  178. case 3:
  179. efx = memory.alloc<Chorus>(pars);
  180. break;
  181. case 4:
  182. efx = memory.alloc<Phaser>(pars);
  183. break;
  184. case 5:
  185. efx = memory.alloc<Alienwah>(pars);
  186. break;
  187. case 6:
  188. efx = memory.alloc<Distorsion>(pars);
  189. break;
  190. case 7:
  191. efx = memory.alloc<EQ>(pars);
  192. break;
  193. case 8:
  194. efx = memory.alloc<DynamicFilter>(pars, time);
  195. break;
  196. //put more effect here
  197. default:
  198. efx = NULL;
  199. break; //no effect (thru)
  200. }
  201. } catch (std::bad_alloc &ba) {
  202. std::cerr << "failed to change effect " << _nefx << ": " << ba.what() << std::endl;
  203. return;
  204. }
  205. if(efx)
  206. filterpars = efx->filterpars;
  207. if(!avoidSmash)
  208. for(int i=0; i<128; ++i)
  209. settings[i] = geteffectparrt(i);
  210. }
  211. void EffectMgr::changeeffect(int _nefx)
  212. {
  213. nefx = _nefx;
  214. //preset = 0;
  215. //memset(settings, 0, sizeof(settings));
  216. }
  217. //Obtain the effect number
  218. int EffectMgr::geteffect(void)
  219. {
  220. return nefx;
  221. }
  222. // Initialize An Effect in RT context
  223. void EffectMgr::init(void)
  224. {
  225. kill();
  226. changeeffectrt(nefx, true);
  227. changepresetrt(preset, true);
  228. for(int i=0; i<128; ++i)
  229. seteffectparrt(i, settings[i]);
  230. }
  231. //Strip effect manager of it's realtime memory
  232. void EffectMgr::kill(void)
  233. {
  234. //printf("Killing Effect(%d)\n", nefx);
  235. memory.dealloc(efx);
  236. }
  237. // Cleanup the current effect
  238. void EffectMgr::cleanup(void)
  239. {
  240. if(efx)
  241. efx->cleanup();
  242. }
  243. // Get the preset of the current effect
  244. unsigned char EffectMgr::getpreset(void)
  245. {
  246. if(efx)
  247. return efx->Ppreset;
  248. else
  249. return 0;
  250. }
  251. // Change the preset of the current effect
  252. void EffectMgr::changepreset(unsigned char npreset)
  253. {
  254. preset = npreset;
  255. }
  256. // Change the preset of the current effect
  257. void EffectMgr::changepresetrt(unsigned char npreset, bool avoidSmash)
  258. {
  259. preset = npreset;
  260. if(efx)
  261. efx->setpreset(npreset);
  262. if(!avoidSmash)
  263. for(int i=0; i<128; ++i)
  264. settings[i] = geteffectparrt(i);
  265. }
  266. //Change a parameter of the current effect
  267. void EffectMgr::seteffectparrt(int npar, unsigned char value)
  268. {
  269. if(npar<128)
  270. settings[npar] = value;
  271. if(!efx)
  272. return;
  273. try {
  274. efx->changepar(npar, value);
  275. } catch (std::bad_alloc &ba) {
  276. std::cerr << "failed to change effect parameter " << npar << " to " << value << ": " << ba.what() << std::endl;
  277. }
  278. }
  279. //Change a parameter of the current effect
  280. void EffectMgr::seteffectpar(int npar, unsigned char value)
  281. {
  282. settings[npar] = value;
  283. }
  284. //Get a parameter of the current effect
  285. unsigned char EffectMgr::geteffectpar(int npar)
  286. {
  287. if(npar<128)
  288. return settings[npar];
  289. if(!efx)
  290. return 0;
  291. return efx->getpar(npar);
  292. }
  293. unsigned char EffectMgr::geteffectparrt(int npar)
  294. {
  295. if(!efx)
  296. return 0;
  297. return efx->getpar(npar);
  298. }
  299. // Apply the effect
  300. void EffectMgr::out(float *smpsl, float *smpsr)
  301. {
  302. if(!efx) {
  303. if(!insertion)
  304. for(int i = 0; i < synth.buffersize; ++i) {
  305. smpsl[i] = 0.0f;
  306. smpsr[i] = 0.0f;
  307. efxoutl[i] = 0.0f;
  308. efxoutr[i] = 0.0f;
  309. }
  310. return;
  311. }
  312. for(int i = 0; i < synth.buffersize; ++i) {
  313. smpsl[i] += synth.denormalkillbuf[i];
  314. smpsr[i] += synth.denormalkillbuf[i];
  315. efxoutl[i] = 0.0f;
  316. efxoutr[i] = 0.0f;
  317. }
  318. efx->out(smpsl, smpsr);
  319. float volume = efx->volume;
  320. if(nefx == 7) { //this is need only for the EQ effect
  321. memcpy(smpsl, efxoutl, synth.bufferbytes);
  322. memcpy(smpsr, efxoutr, synth.bufferbytes);
  323. return;
  324. }
  325. //Insertion effect
  326. if(insertion != 0) {
  327. float v1, v2;
  328. if(volume < 0.5f) {
  329. v1 = 1.0f;
  330. v2 = volume * 2.0f;
  331. }
  332. else {
  333. v1 = (1.0f - volume) * 2.0f;
  334. v2 = 1.0f;
  335. }
  336. if((nefx == 1) || (nefx == 2))
  337. v2 *= v2; //for Reverb and Echo, the wet function is not liniar
  338. if(dryonly) //this is used for instrument effect only
  339. for(int i = 0; i < synth.buffersize; ++i) {
  340. smpsl[i] *= v1;
  341. smpsr[i] *= v1;
  342. efxoutl[i] *= v2;
  343. efxoutr[i] *= v2;
  344. }
  345. else // normal instrument/insertion effect
  346. for(int i = 0; i < synth.buffersize; ++i) {
  347. smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2;
  348. smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2;
  349. }
  350. }
  351. else // System effect
  352. for(int i = 0; i < synth.buffersize; ++i) {
  353. efxoutl[i] *= 2.0f * volume;
  354. efxoutr[i] *= 2.0f * volume;
  355. smpsl[i] = efxoutl[i];
  356. smpsr[i] = efxoutr[i];
  357. }
  358. }
  359. // Get the effect volume for the system effect
  360. float EffectMgr::sysefxgetvolume(void)
  361. {
  362. return efx ? efx->outvolume : 1.0f;
  363. }
  364. // Get the EQ response
  365. float EffectMgr::getEQfreqresponse(float freq)
  366. {
  367. return (nefx == 7) ? efx->getfreqresponse(freq) : 0.0f;
  368. }
  369. void EffectMgr::setdryonly(bool value)
  370. {
  371. dryonly = value;
  372. }
  373. void EffectMgr::paste(EffectMgr &e)
  374. {
  375. changeeffectrt(e.nefx, true);
  376. changepresetrt(e.preset, true);
  377. for(int i=0;i<128;++i)
  378. seteffectparrt(i, e.settings[i]);
  379. }
  380. void EffectMgr::add2XML(XMLwrapper& xml)
  381. {
  382. xml.addpar("type", geteffect());
  383. if(!geteffect())
  384. return;
  385. xml.addpar("preset", preset);
  386. xml.beginbranch("EFFECT_PARAMETERS");
  387. for(int n = 0; n < 128; ++n) {
  388. int par = geteffectpar(n);
  389. if(par == 0)
  390. continue;
  391. xml.beginbranch("par_no", n);
  392. xml.addpar("par", par);
  393. xml.endbranch();
  394. }
  395. if(filterpars) {
  396. xml.beginbranch("FILTER");
  397. filterpars->add2XML(xml);
  398. xml.endbranch();
  399. }
  400. xml.endbranch();
  401. }
  402. void EffectMgr::getfromXML(XMLwrapper& xml)
  403. {
  404. changeeffect(xml.getpar127("type", geteffect()));
  405. if(!geteffect())
  406. return;
  407. preset = xml.getpar127("preset", preset);
  408. if(xml.enterbranch("EFFECT_PARAMETERS")) {
  409. for(int n = 0; n < 128; ++n) {
  410. seteffectpar(n, 0); //erase effect parameter
  411. if(xml.enterbranch("par_no", n) == 0)
  412. continue;
  413. int par = geteffectpar(n);
  414. seteffectpar(n, xml.getpar127("par", par));
  415. xml.exitbranch();
  416. }
  417. if(filterpars)
  418. if(xml.enterbranch("FILTER")) {
  419. filterpars->getfromXML(xml);
  420. xml.exitbranch();
  421. }
  422. xml.exitbranch();
  423. }
  424. cleanup();
  425. }