External plugins for 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.

366 lines
11KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. DynamicFilter.cpp - "WahWah" effect and others
  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
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include <cassert>
  12. #include <cmath>
  13. #include <iostream>
  14. #include "DynamicFilter.h"
  15. #include "../DSP/Filter.h"
  16. #include "../Misc/Allocator.h"
  17. #include <rtosc/ports.h>
  18. #include <rtosc/port-sugar.h>
  19. namespace zyncarla {
  20. #define rObject DynamicFilter
  21. #define rBegin [](const char *msg, rtosc::RtData &d) {
  22. #define rEnd }
  23. rtosc::Ports DynamicFilter::ports = {
  24. {"preset::i", rOptions(WahWah, AutoWah, Sweep, VocalMorph1, VocalMorph1)
  25. rDoc("Instrument Presets"), 0,
  26. rBegin;
  27. rObject *o = (rObject*)d.obj;
  28. if(rtosc_narguments(msg))
  29. o->setpreset(rtosc_argument(msg, 0).i);
  30. else
  31. d.reply(d.loc, "i", o->Ppreset);
  32. rEnd},
  33. rEffParVol(rDefault(110), rPreset(2, 110), rPreset(4, 127)),
  34. rEffParPan(),
  35. rEffPar(Pfreq, 2, rShort("freq"), rPresets(80, 70, 30, 80, 50),
  36. "Effect Frequency"),
  37. rEffPar(Pfreqrnd, 3, rShort("rand"), rDefault(0),
  38. "Frequency Randomness"),
  39. rEffPar(PLFOtype, 4, rShort("shape"), rOptions(sin, tri), rDefault(sin),
  40. "LFO Shape"),
  41. rEffPar(PStereo, 5, rShort("stereo"), rPresets(64, 80, 50, 64, 96),
  42. "Stereo Mode"),
  43. rEffPar(Pdepth, 6, rShort("depth"), rPresets(0, 70, 80, 0, 64),
  44. "LFO Depth"),
  45. rEffPar(Pampsns, 7, rShort("sense"),
  46. rPreset(0, 90) rPreset(3, 64) rDefault(0),
  47. "how the filter varies according to the input amplitude"),
  48. rEffPar(Pampsnsinv, 8, rShort("sns.inv"), rDefault(0), "Sense Inversion"),
  49. rEffPar(Pampsmooth, 9, rShort("smooth"), rDefault(60),
  50. "how smooth the input amplitude changes the filter"),
  51. };
  52. #undef rBegin
  53. #undef rEnd
  54. #undef rObject
  55. DynamicFilter::DynamicFilter(EffectParams pars, const AbsTime *time)
  56. :Effect(pars),
  57. lfo(pars.srate, pars.bufsize),
  58. Pvolume(110),
  59. Pdepth(0),
  60. Pampsns(90),
  61. Pampsnsinv(0),
  62. Pampsmooth(60),
  63. filterl(NULL),
  64. filterr(NULL)
  65. {
  66. filterpars = pars.filterpars;
  67. setpreset(Ppreset, pars.filterprotect);
  68. cleanup();
  69. }
  70. DynamicFilter::~DynamicFilter()
  71. {
  72. memory.dealloc(filterl);
  73. memory.dealloc(filterr);
  74. }
  75. // Apply the effect
  76. void DynamicFilter::out(const Stereo<float *> &smp)
  77. {
  78. if(filterpars->changed) {
  79. filterpars->changed = false;
  80. cleanup();
  81. }
  82. float lfol, lfor;
  83. lfo.effectlfoout(&lfol, &lfor);
  84. lfol *= depth * 5.0f;
  85. lfor *= depth * 5.0f;
  86. const float freq = filterpars->getfreq();
  87. const float q = filterpars->getq();
  88. for(int i = 0; i < buffersize; ++i) {
  89. efxoutl[i] = smp.l[i];
  90. efxoutr[i] = smp.r[i];
  91. const float x = (fabsf(smp.l[i]) + fabsf(smp.r[i])) * 0.5f;
  92. ms1 = ms1 * (1.0f - ampsmooth) + x * ampsmooth + 1e-10;
  93. }
  94. const float ampsmooth2 = powf(ampsmooth, 0.2f) * 0.3f;
  95. ms2 = ms2 * (1.0f - ampsmooth2) + ms1 * ampsmooth2;
  96. ms3 = ms3 * (1.0f - ampsmooth2) + ms2 * ampsmooth2;
  97. ms4 = ms4 * (1.0f - ampsmooth2) + ms3 * ampsmooth2;
  98. const float rms = (sqrtf(ms4)) * ampsns;
  99. const float frl = Filter::getrealfreq(freq + lfol + rms);
  100. const float frr = Filter::getrealfreq(freq + lfor + rms);
  101. filterl->setfreq_and_q(frl, q);
  102. filterr->setfreq_and_q(frr, q);
  103. filterl->filterout(efxoutl);
  104. filterr->filterout(efxoutr);
  105. //panning
  106. for(int i = 0; i < buffersize; ++i) {
  107. efxoutl[i] *= pangainL;
  108. efxoutr[i] *= pangainR;
  109. }
  110. }
  111. // Cleanup the effect
  112. void DynamicFilter::cleanup(void)
  113. {
  114. reinitfilter();
  115. ms1 = ms2 = ms3 = ms4 = 0.0f;
  116. }
  117. //Parameter control
  118. void DynamicFilter::setdepth(unsigned char _Pdepth)
  119. {
  120. Pdepth = _Pdepth;
  121. depth = powf(Pdepth / 127.0f, 2.0f);
  122. }
  123. void DynamicFilter::setvolume(unsigned char _Pvolume)
  124. {
  125. Pvolume = _Pvolume;
  126. outvolume = Pvolume / 127.0f;
  127. if(!insertion)
  128. volume = 1.0f;
  129. else
  130. volume = outvolume;
  131. }
  132. void DynamicFilter::setampsns(unsigned char _Pampsns)
  133. {
  134. Pampsns = _Pampsns;
  135. ampsns = powf(Pampsns / 127.0f, 2.5f) * 10.0f;
  136. if(Pampsnsinv)
  137. ampsns = -ampsns;
  138. ampsmooth = expf(-Pampsmooth / 127.0f * 10.0f) * 0.99f;
  139. }
  140. void DynamicFilter::reinitfilter(void)
  141. {
  142. memory.dealloc(filterl);
  143. memory.dealloc(filterr);
  144. try {
  145. filterl = Filter::generate(memory, filterpars, samplerate, buffersize);
  146. } catch(std::bad_alloc& ba) {
  147. std::cerr << "failed to generate left filter for dynamic filter: " << ba.what() << std::endl;
  148. }
  149. try {
  150. filterr = Filter::generate(memory, filterpars, samplerate, buffersize);
  151. } catch(std::bad_alloc& ba) {
  152. std::cerr << "failed to generate right filter for dynamic filter: " << ba.what() << std::endl;
  153. }
  154. }
  155. void DynamicFilter::setfilterpreset(unsigned char npreset)
  156. {
  157. filterpars->defaults();
  158. switch(npreset) {
  159. case 0:
  160. filterpars->Pcategory = 0;
  161. filterpars->Ptype = 2;
  162. filterpars->Pfreq = 45;
  163. filterpars->Pq = 64;
  164. filterpars->Pstages = 1;
  165. filterpars->Pgain = 64;
  166. break;
  167. case 1:
  168. filterpars->Pcategory = 2;
  169. filterpars->Ptype = 0;
  170. filterpars->Pfreq = 72;
  171. filterpars->Pq = 64;
  172. filterpars->Pstages = 0;
  173. filterpars->Pgain = 64;
  174. break;
  175. case 2:
  176. filterpars->Pcategory = 0;
  177. filterpars->Ptype = 4;
  178. filterpars->Pfreq = 64;
  179. filterpars->Pq = 64;
  180. filterpars->Pstages = 2;
  181. filterpars->Pgain = 64;
  182. break;
  183. case 3:
  184. filterpars->Pcategory = 1;
  185. filterpars->Ptype = 0;
  186. filterpars->Pfreq = 50;
  187. filterpars->Pq = 70;
  188. filterpars->Pstages = 1;
  189. filterpars->Pgain = 64;
  190. filterpars->Psequencesize = 2;
  191. // "I"
  192. filterpars->Pvowels[0].formants[0].freq = 34;
  193. filterpars->Pvowels[0].formants[0].amp = 127;
  194. filterpars->Pvowels[0].formants[0].q = 64;
  195. filterpars->Pvowels[0].formants[1].freq = 99;
  196. filterpars->Pvowels[0].formants[1].amp = 122;
  197. filterpars->Pvowels[0].formants[1].q = 64;
  198. filterpars->Pvowels[0].formants[2].freq = 108;
  199. filterpars->Pvowels[0].formants[2].amp = 112;
  200. filterpars->Pvowels[0].formants[2].q = 64;
  201. // "A"
  202. filterpars->Pvowels[1].formants[0].freq = 61;
  203. filterpars->Pvowels[1].formants[0].amp = 127;
  204. filterpars->Pvowels[1].formants[0].q = 64;
  205. filterpars->Pvowels[1].formants[1].freq = 71;
  206. filterpars->Pvowels[1].formants[1].amp = 121;
  207. filterpars->Pvowels[1].formants[1].q = 64;
  208. filterpars->Pvowels[1].formants[2].freq = 99;
  209. filterpars->Pvowels[1].formants[2].amp = 117;
  210. filterpars->Pvowels[1].formants[2].q = 64;
  211. break;
  212. case 4:
  213. filterpars->Pcategory = 1;
  214. filterpars->Ptype = 0;
  215. filterpars->Pfreq = 64;
  216. filterpars->Pq = 70;
  217. filterpars->Pstages = 1;
  218. filterpars->Pgain = 64;
  219. filterpars->Psequencesize = 2;
  220. filterpars->Pnumformants = 2;
  221. filterpars->Pvowelclearness = 0;
  222. filterpars->Pvowels[0].formants[0].freq = 70;
  223. filterpars->Pvowels[0].formants[0].amp = 127;
  224. filterpars->Pvowels[0].formants[0].q = 64;
  225. filterpars->Pvowels[0].formants[1].freq = 80;
  226. filterpars->Pvowels[0].formants[1].amp = 122;
  227. filterpars->Pvowels[0].formants[1].q = 64;
  228. filterpars->Pvowels[1].formants[0].freq = 20;
  229. filterpars->Pvowels[1].formants[0].amp = 127;
  230. filterpars->Pvowels[1].formants[0].q = 64;
  231. filterpars->Pvowels[1].formants[1].freq = 100;
  232. filterpars->Pvowels[1].formants[1].amp = 121;
  233. filterpars->Pvowels[1].formants[1].q = 64;
  234. break;
  235. }
  236. // for (int i=0;i<5;i++){
  237. // printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q);
  238. // };
  239. reinitfilter();
  240. }
  241. void DynamicFilter::setpreset(unsigned char npreset, bool protect)
  242. {
  243. const int PRESET_SIZE = 10;
  244. const int NUM_PRESETS = 5;
  245. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  246. //WahWah
  247. {110, 64, 80, 0, 0, 64, 0, 90, 0, 60},
  248. //AutoWah
  249. {110, 64, 70, 0, 0, 80, 70, 0, 0, 60},
  250. //Sweep
  251. {100, 64, 30, 0, 0, 50, 80, 0, 0, 60},
  252. //VocalMorph1
  253. {110, 64, 80, 0, 0, 64, 0, 64, 0, 60},
  254. //VocalMorph1
  255. {127, 64, 50, 0, 0, 96, 64, 0, 0, 60}
  256. };
  257. if(npreset >= NUM_PRESETS)
  258. npreset = NUM_PRESETS - 1;
  259. for(int n = 0; n < PRESET_SIZE; ++n)
  260. changepar(n, presets[npreset][n]);
  261. if(insertion == 0) //lower the volume if this is system effect
  262. changepar(0, presets[npreset][0] * 0.5f);
  263. Ppreset = npreset;
  264. if(!protect)
  265. setfilterpreset(npreset);
  266. }
  267. void DynamicFilter::changepar(int npar, unsigned char value)
  268. {
  269. switch(npar) {
  270. case 0:
  271. setvolume(value);
  272. break;
  273. case 1:
  274. setpanning(value);
  275. break;
  276. case 2:
  277. lfo.Pfreq = value;
  278. lfo.updateparams();
  279. break;
  280. case 3:
  281. lfo.Prandomness = value;
  282. lfo.updateparams();
  283. break;
  284. case 4:
  285. lfo.PLFOtype = value;
  286. lfo.updateparams();
  287. break;
  288. case 5:
  289. lfo.Pstereo = value;
  290. lfo.updateparams();
  291. break;
  292. case 6:
  293. setdepth(value);
  294. break;
  295. case 7:
  296. setampsns(value);
  297. break;
  298. case 8:
  299. Pampsnsinv = value;
  300. setampsns(Pampsns);
  301. break;
  302. case 9:
  303. Pampsmooth = value;
  304. setampsns(Pampsns);
  305. break;
  306. }
  307. }
  308. unsigned char DynamicFilter::getpar(int npar) const
  309. {
  310. switch(npar) {
  311. case 0: return Pvolume;
  312. case 1: return Ppanning;
  313. case 2: return lfo.Pfreq;
  314. case 3: return lfo.Prandomness;
  315. case 4: return lfo.PLFOtype;
  316. case 5: return lfo.Pstereo;
  317. case 6: return Pdepth;
  318. case 7: return Pampsns;
  319. case 8: return Pampsnsinv;
  320. case 9: return Pampsmooth;
  321. default: return 0;
  322. }
  323. }
  324. }