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.

308 lines
8.6KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Distorsion.cpp - Distorsion effect
  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 "Distorsion.h"
  12. #include "../DSP/AnalogFilter.h"
  13. #include "../Misc/WaveShapeSmps.h"
  14. #include "../Misc/Allocator.h"
  15. #include <cmath>
  16. #include <rtosc/ports.h>
  17. #include <rtosc/port-sugar.h>
  18. namespace zyncarla {
  19. #define rObject Distorsion
  20. #define rBegin [](const char *msg, rtosc::RtData &d) {
  21. #define rEnd }
  22. rtosc::Ports Distorsion::ports = {
  23. {"preset::i", rProp(parameter)
  24. rOptions(Overdrive 1, Overdrive 2, A. Exciter 1, A. Exciter 2, Guitar Amp,
  25. Quantisize)
  26. rDoc("Instrument Presets"), 0,
  27. rBegin;
  28. rObject *o = (rObject*)d.obj;
  29. if(rtosc_narguments(msg))
  30. o->setpreset(rtosc_argument(msg, 0).i);
  31. else
  32. d.reply(d.loc, "i", o->Ppreset);
  33. rEnd},
  34. rEffParVol(rDefault(127), rPresetsAt(2, 64, 64)),
  35. rEffParPan(),
  36. rEffPar(Plrcross, 2, rShort("l/r"), rDefault(35), "Left/Right Crossover"),
  37. rEffPar(Pdrive, 3, rShort("drive"), rPresets(56, 29, 75, 85, 63, 88),
  38. "Input amplification"),
  39. rEffPar(Plevel, 4, rShort("output"), rPresets(70, 75, 80, 62, 75, 75),
  40. "Output amplification"),
  41. rEffPar(Ptype, 5, rShort("type"),
  42. rOptions(Arctangent, Asymmetric, Pow, Sine, Quantisize,
  43. Zigzag, Limiter, Upper Limiter, Lower Limiter,
  44. Inverse Limiter, Clip, Asym2, Pow2, sigmoid),
  45. rPresets(Arctangent, Asymmetric, Zigzag,
  46. Asymmetric, Pow, Quantisize),
  47. "Distortion Shape"),
  48. rEffParTF(Pnegate, 6, rShort("neg"), rDefault(false), "Negate Signal"),
  49. rEffPar(Plpf, 7, rShort("lpf"),
  50. rPreset(0, 96), rPreset(4, 55), rDefault(127), "Low Pass Cutoff"),
  51. rEffPar(Phpf, 8, rShort("hpf"),
  52. rPreset(2, 105), rPreset(3, 118), rDefault(0), "High Pass Cutoff"),
  53. rEffParTF(Pstereo, 9, rShort("stereo"),
  54. rPresets(false, false, true, true, false, true), "Stereo"),
  55. rEffParTF(Pprefiltering, 10, rShort("p.filt"), rDefault(false),
  56. "Filtering before/after non-linearity"),
  57. {"waveform:", 0, 0, [](const char *, rtosc::RtData &d)
  58. {
  59. Distorsion &dd = *(Distorsion*)d.obj;
  60. float buffer[128];
  61. rtosc_arg_t args[128];
  62. char arg_str[128+1] = {0};
  63. for(int i=0; i<128; ++i)
  64. buffer[i] = 2*(i/128.0)-1;
  65. waveShapeSmps(sizeof(buffer)/sizeof(buffer[0]), buffer,
  66. dd.Ptype + 1, dd.Pdrive);
  67. for(int i=0; i<128; ++i) {
  68. arg_str[i] = 'f';
  69. args[i].f = buffer[i];
  70. }
  71. d.replyArray(d.loc, arg_str, args);
  72. }},
  73. };
  74. #undef rBegin
  75. #undef rEnd
  76. #undef rObject
  77. Distorsion::Distorsion(EffectParams pars)
  78. :Effect(pars),
  79. Pvolume(50),
  80. Pdrive(90),
  81. Plevel(64),
  82. Ptype(0),
  83. Pnegate(0),
  84. Plpf(127),
  85. Phpf(0),
  86. Pstereo(0),
  87. Pprefiltering(0)
  88. {
  89. lpfl = memory.alloc<AnalogFilter>(2, 22000, 1, 0, pars.srate, pars.bufsize);
  90. lpfr = memory.alloc<AnalogFilter>(2, 22000, 1, 0, pars.srate, pars.bufsize);
  91. hpfl = memory.alloc<AnalogFilter>(3, 20, 1, 0, pars.srate, pars.bufsize);
  92. hpfr = memory.alloc<AnalogFilter>(3, 20, 1, 0, pars.srate, pars.bufsize);
  93. setpreset(Ppreset);
  94. cleanup();
  95. }
  96. Distorsion::~Distorsion()
  97. {
  98. memory.dealloc(lpfl);
  99. memory.dealloc(lpfr);
  100. memory.dealloc(hpfl);
  101. memory.dealloc(hpfr);
  102. }
  103. //Cleanup the effect
  104. void Distorsion::cleanup(void)
  105. {
  106. lpfl->cleanup();
  107. hpfl->cleanup();
  108. lpfr->cleanup();
  109. hpfr->cleanup();
  110. }
  111. //Apply the filters
  112. void Distorsion::applyfilters(float *efxoutl, float *efxoutr)
  113. {
  114. lpfl->filterout(efxoutl);
  115. hpfl->filterout(efxoutl);
  116. if(Pstereo != 0) { //stereo
  117. lpfr->filterout(efxoutr);
  118. hpfr->filterout(efxoutr);
  119. }
  120. }
  121. //Effect output
  122. void Distorsion::out(const Stereo<float *> &smp)
  123. {
  124. float inputvol = powf(5.0f, (Pdrive - 32.0f) / 127.0f);
  125. if(Pnegate)
  126. inputvol *= -1.0f;
  127. if(Pstereo) //Stereo
  128. for(int i = 0; i < buffersize; ++i) {
  129. efxoutl[i] = smp.l[i] * inputvol * pangainL;
  130. efxoutr[i] = smp.r[i] * inputvol * pangainR;
  131. }
  132. else //Mono
  133. for(int i = 0; i < buffersize; ++i)
  134. efxoutl[i] = (smp.l[i] * pangainL + smp.r[i] * pangainR) * inputvol;
  135. if(Pprefiltering)
  136. applyfilters(efxoutl, efxoutr);
  137. waveShapeSmps(buffersize, efxoutl, Ptype + 1, Pdrive);
  138. if(Pstereo)
  139. waveShapeSmps(buffersize, efxoutr, Ptype + 1, Pdrive);
  140. if(!Pprefiltering)
  141. applyfilters(efxoutl, efxoutr);
  142. if(!Pstereo)
  143. memcpy(efxoutr, efxoutl, bufferbytes);
  144. float level = dB2rap(60.0f * Plevel / 127.0f - 40.0f);
  145. for(int i = 0; i < buffersize; ++i) {
  146. float lout = efxoutl[i];
  147. float rout = efxoutr[i];
  148. float l = lout * (1.0f - lrcross) + rout * lrcross;
  149. float r = rout * (1.0f - lrcross) + lout * lrcross;
  150. lout = l;
  151. rout = r;
  152. efxoutl[i] = lout * 2.0f * level;
  153. efxoutr[i] = rout * 2.0f * level;
  154. }
  155. }
  156. //Parameter control
  157. void Distorsion::setvolume(unsigned char _Pvolume)
  158. {
  159. Pvolume = _Pvolume;
  160. if(insertion == 0) {
  161. outvolume = powf(0.01f, (1.0f - Pvolume / 127.0f)) * 4.0f;
  162. volume = 1.0f;
  163. }
  164. else
  165. volume = outvolume = Pvolume / 127.0f;
  166. if(Pvolume == 0)
  167. cleanup();
  168. }
  169. void Distorsion::setlpf(unsigned char _Plpf)
  170. {
  171. Plpf = _Plpf;
  172. float fr = expf(sqrtf(Plpf / 127.0f) * logf(25000.0f)) + 40.0f;
  173. lpfl->setfreq(fr);
  174. lpfr->setfreq(fr);
  175. }
  176. void Distorsion::sethpf(unsigned char _Phpf)
  177. {
  178. Phpf = _Phpf;
  179. float fr = expf(sqrtf(Phpf / 127.0f) * logf(25000.0f)) + 20.0f;
  180. hpfl->setfreq(fr);
  181. hpfr->setfreq(fr);
  182. }
  183. void Distorsion::setpreset(unsigned char npreset)
  184. {
  185. const int PRESET_SIZE = 11;
  186. const int NUM_PRESETS = 6;
  187. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  188. //Overdrive 1
  189. {127, 64, 35, 56, 70, 0, 0, 96, 0, 0, 0},
  190. //Overdrive 2
  191. {127, 64, 35, 29, 75, 1, 0, 127, 0, 0, 0},
  192. //A. Exciter 1
  193. {64, 64, 35, 75, 80, 5, 0, 127, 105, 1, 0},
  194. //A. Exciter 2
  195. {64, 64, 35, 85, 62, 1, 0, 127, 118, 1, 0},
  196. //Guitar Amp
  197. {127, 64, 35, 63, 75, 2, 0, 55, 0, 0, 0},
  198. //Quantisize
  199. {127, 64, 35, 88, 75, 4, 0, 127, 0, 1, 0}
  200. };
  201. if(npreset >= NUM_PRESETS)
  202. npreset = NUM_PRESETS - 1;
  203. for(int n = 0; n < PRESET_SIZE; ++n)
  204. changepar(n, presets[npreset][n]);
  205. if(!insertion) //lower the volume if this is system effect
  206. changepar(0, (int) (presets[npreset][0] / 1.5f));
  207. Ppreset = npreset;
  208. cleanup();
  209. }
  210. void Distorsion::changepar(int npar, unsigned char value)
  211. {
  212. switch(npar) {
  213. case 0:
  214. setvolume(value);
  215. break;
  216. case 1:
  217. setpanning(value);
  218. break;
  219. case 2:
  220. setlrcross(value);
  221. break;
  222. case 3:
  223. Pdrive = value;
  224. break;
  225. case 4:
  226. Plevel = value;
  227. break;
  228. case 5:
  229. if(value > 13)
  230. Ptype = 13; //this must be increased if more distorsion types are added
  231. else
  232. Ptype = value;
  233. break;
  234. case 6:
  235. if(value > 1)
  236. Pnegate = 1;
  237. else
  238. Pnegate = value;
  239. break;
  240. case 7:
  241. setlpf(value);
  242. break;
  243. case 8:
  244. sethpf(value);
  245. break;
  246. case 9:
  247. Pstereo = (value > 1) ? 1 : value;
  248. break;
  249. case 10:
  250. Pprefiltering = value;
  251. break;
  252. }
  253. }
  254. unsigned char Distorsion::getpar(int npar) const
  255. {
  256. switch(npar) {
  257. case 0: return Pvolume;
  258. case 1: return Ppanning;
  259. case 2: return Plrcross;
  260. case 3: return Pdrive;
  261. case 4: return Plevel;
  262. case 5: return Ptype;
  263. case 6: return Pnegate;
  264. case 7: return Plpf;
  265. case 8: return Phpf;
  266. case 9: return Pstereo;
  267. case 10: return Pprefiltering;
  268. default: return 0; //in case of bogus parameter number
  269. }
  270. }
  271. }