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.

295 lines
8.0KB

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