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.

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