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.

443 lines
12KB

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