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.

430 lines
11KB

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