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.

EffectMgr.cpp 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 "EffectMgr.h"
  18. #include "Effect.h"
  19. #include "Reverb.h"
  20. #include "Echo.h"
  21. #include "Chorus.h"
  22. #include "Distorsion.h"
  23. #include "EQ.h"
  24. #include "DynamicFilter.h"
  25. #include "../Misc/XMLwrapper.h"
  26. #include "../Params/FilterParams.h"
  27. #include <iostream>
  28. using namespace std;
  29. EffectMgr::EffectMgr(const bool insertion_, pthread_mutex_t *mutex_)
  30. :insertion(insertion_),
  31. efxoutl(new float[synth->buffersize]),
  32. efxoutr(new float[synth->buffersize]),
  33. filterpars(NULL),
  34. nefx(0),
  35. efx(NULL),
  36. mutex(mutex_),
  37. dryonly(false)
  38. {
  39. setpresettype("Peffect");
  40. memset(efxoutl, 0, synth->bufferbytes);
  41. memset(efxoutr, 0, synth->bufferbytes);
  42. defaults();
  43. }
  44. EffectMgr::~EffectMgr()
  45. {
  46. delete efx;
  47. delete [] efxoutl;
  48. delete [] efxoutr;
  49. }
  50. void EffectMgr::defaults(void)
  51. {
  52. changeeffect(0);
  53. setdryonly(false);
  54. }
  55. //Change the effect
  56. void EffectMgr::changeeffect(int _nefx)
  57. {
  58. cleanup();
  59. if(nefx == _nefx)
  60. return;
  61. nefx = _nefx;
  62. memset(efxoutl, 0, synth->bufferbytes);
  63. memset(efxoutr, 0, synth->bufferbytes);
  64. delete efx;
  65. switch(nefx) {
  66. case 1:
  67. efx = new Reverb(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  68. break;
  69. case 2:
  70. efx = new Echo(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  71. break;
  72. case 3:
  73. efx = new Chorus(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  74. break;
  75. case 4:
  76. efx = new Phaser(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  77. break;
  78. case 5:
  79. efx = new Alienwah(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  80. break;
  81. case 6:
  82. efx = new Distorsion(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  83. break;
  84. case 7:
  85. efx = new EQ(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  86. break;
  87. case 8:
  88. efx = new DynamicFilter(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize);
  89. break;
  90. //put more effect here
  91. default:
  92. efx = NULL;
  93. break; //no effect (thru)
  94. }
  95. if(efx)
  96. filterpars = efx->filterpars;
  97. }
  98. //Obtain the effect number
  99. int EffectMgr::geteffect(void)
  100. {
  101. return nefx;
  102. }
  103. // Cleanup the current effect
  104. void EffectMgr::cleanup(void)
  105. {
  106. if(efx)
  107. efx->cleanup();
  108. }
  109. // Get the preset of the current effect
  110. unsigned char EffectMgr::getpreset(void)
  111. {
  112. if(efx)
  113. return efx->Ppreset;
  114. else
  115. return 0;
  116. }
  117. // Change the preset of the current effect
  118. void EffectMgr::changepreset_nolock(unsigned char npreset)
  119. {
  120. if(efx)
  121. efx->setpreset(npreset);
  122. }
  123. //Change the preset of the current effect(with thread locking)
  124. void EffectMgr::changepreset(unsigned char npreset)
  125. {
  126. pthread_mutex_lock(mutex);
  127. changepreset_nolock(npreset);
  128. pthread_mutex_unlock(mutex);
  129. }
  130. //Change a parameter of the current effect
  131. void EffectMgr::seteffectpar_nolock(int npar, unsigned char value)
  132. {
  133. if(!efx)
  134. return;
  135. efx->changepar(npar, value);
  136. }
  137. // Change a parameter of the current effect (with thread locking)
  138. void EffectMgr::seteffectpar(int npar, unsigned char value)
  139. {
  140. pthread_mutex_lock(mutex);
  141. seteffectpar_nolock(npar, value);
  142. pthread_mutex_unlock(mutex);
  143. }
  144. //Get a parameter of the current effect
  145. unsigned char EffectMgr::geteffectpar(int npar)
  146. {
  147. if(!efx)
  148. return 0;
  149. return efx->getpar(npar);
  150. }
  151. // Apply the effect
  152. void EffectMgr::out(float *smpsl, float *smpsr)
  153. {
  154. if(!efx) {
  155. if(!insertion)
  156. for(int i = 0; i < synth->buffersize; ++i) {
  157. smpsl[i] = 0.0f;
  158. smpsr[i] = 0.0f;
  159. efxoutl[i] = 0.0f;
  160. efxoutr[i] = 0.0f;
  161. }
  162. return;
  163. }
  164. for(int i = 0; i < synth->buffersize; ++i) {
  165. smpsl[i] += denormalkillbuf[i];
  166. smpsr[i] += denormalkillbuf[i];
  167. efxoutl[i] = 0.0f;
  168. efxoutr[i] = 0.0f;
  169. }
  170. efx->out(smpsl, smpsr);
  171. float volume = efx->volume;
  172. if(nefx == 7) { //this is need only for the EQ effect
  173. memcpy(smpsl, efxoutl, synth->bufferbytes);
  174. memcpy(smpsr, efxoutr, synth->bufferbytes);
  175. return;
  176. }
  177. //Insertion effect
  178. if(insertion != 0) {
  179. float v1, v2;
  180. if(volume < 0.5f) {
  181. v1 = 1.0f;
  182. v2 = volume * 2.0f;
  183. }
  184. else {
  185. v1 = (1.0f - volume) * 2.0f;
  186. v2 = 1.0f;
  187. }
  188. if((nefx == 1) || (nefx == 2))
  189. v2 *= v2; //for Reverb and Echo, the wet function is not liniar
  190. if(dryonly) //this is used for instrument effect only
  191. for(int i = 0; i < synth->buffersize; ++i) {
  192. smpsl[i] *= v1;
  193. smpsr[i] *= v1;
  194. efxoutl[i] *= v2;
  195. efxoutr[i] *= v2;
  196. }
  197. else // normal instrument/insertion effect
  198. for(int i = 0; i < synth->buffersize; ++i) {
  199. smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2;
  200. smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2;
  201. }
  202. }
  203. else // System effect
  204. for(int i = 0; i < synth->buffersize; ++i) {
  205. efxoutl[i] *= 2.0f * volume;
  206. efxoutr[i] *= 2.0f * volume;
  207. smpsl[i] = efxoutl[i];
  208. smpsr[i] = efxoutr[i];
  209. }
  210. }
  211. // Get the effect volume for the system effect
  212. float EffectMgr::sysefxgetvolume(void)
  213. {
  214. return (!efx) ? 1.0f : efx->outvolume;
  215. }
  216. // Get the EQ response
  217. float EffectMgr::getEQfreqresponse(float freq)
  218. {
  219. return (nefx == 7) ? efx->getfreqresponse(freq) : 0.0f;
  220. }
  221. void EffectMgr::setdryonly(bool value)
  222. {
  223. dryonly = value;
  224. }
  225. void EffectMgr::add2XML(XMLwrapper *xml)
  226. {
  227. xml->addpar("type", geteffect());
  228. if(!efx || !geteffect())
  229. return;
  230. xml->addpar("preset", efx->Ppreset);
  231. xml->beginbranch("EFFECT_PARAMETERS");
  232. for(int n = 0; n < 128; ++n) {
  233. int par = geteffectpar(n);
  234. if(par == 0)
  235. continue;
  236. xml->beginbranch("par_no", n);
  237. xml->addpar("par", par);
  238. xml->endbranch();
  239. }
  240. if(filterpars) {
  241. xml->beginbranch("FILTER");
  242. filterpars->add2XML(xml);
  243. xml->endbranch();
  244. }
  245. xml->endbranch();
  246. }
  247. void EffectMgr::getfromXML(XMLwrapper *xml)
  248. {
  249. changeeffect(xml->getpar127("type", geteffect()));
  250. if(!efx || !geteffect())
  251. return;
  252. efx->Ppreset = xml->getpar127("preset", efx->Ppreset);
  253. if(xml->enterbranch("EFFECT_PARAMETERS")) {
  254. for(int n = 0; n < 128; ++n) {
  255. seteffectpar_nolock(n, 0); //erase effect parameter
  256. if(xml->enterbranch("par_no", n) == 0)
  257. continue;
  258. int par = geteffectpar(n);
  259. seteffectpar_nolock(n, xml->getpar127("par", par));
  260. xml->exitbranch();
  261. }
  262. if(filterpars)
  263. if(xml->enterbranch("FILTER")) {
  264. filterpars->getfromXML(xml);
  265. xml->exitbranch();
  266. }
  267. xml->exitbranch();
  268. }
  269. cleanup();
  270. }