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.

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