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.

447 lines
12KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Phaser.cpp - Phasing and Approximate digital model of an analog JFET phaser.
  4. Analog modeling implemented by Ryan Billing aka Transmogrifox.
  5. DSP analog modeling theory & practice largely influenced by
  6. various CCRMA publications, particularly works by Julius O. Smith.
  7. Copyright (C) 2002-2005 Nasca Octavian Paul
  8. Copyright (C) 2009-2010 Ryan Billing
  9. Copyright (C) 2010-2010 Mark McCurry
  10. This program is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU General Public License
  12. as published by the Free Software Foundation; either version 2
  13. of the License, or (at your option) any later version.
  14. */
  15. #include <cmath>
  16. #include <algorithm>
  17. #include "../Misc/Allocator.h"
  18. #include "Phaser.h"
  19. using namespace std;
  20. #define PHASER_LFO_SHAPE 2
  21. #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes
  22. #define ZERO_ 0.00001f // Same idea as above.
  23. Phaser::Phaser(EffectParams pars)
  24. :Effect(pars), lfo(pars.srate, pars.bufsize), old(NULL), xn1(NULL),
  25. yn1(NULL), diff(0.0f), oldgain(0.0f), fb(0.0f)
  26. {
  27. analog_setup();
  28. setpreset(Ppreset);
  29. cleanup();
  30. }
  31. void Phaser::analog_setup()
  32. {
  33. //model mismatch between JFET devices
  34. offset[0] = -0.2509303f;
  35. offset[1] = 0.9408924f;
  36. offset[2] = 0.998f;
  37. offset[3] = -0.3486182f;
  38. offset[4] = -0.2762545f;
  39. offset[5] = -0.5215785f;
  40. offset[6] = 0.2509303f;
  41. offset[7] = -0.9408924f;
  42. offset[8] = -0.998f;
  43. offset[9] = 0.3486182f;
  44. offset[10] = 0.2762545f;
  45. offset[11] = 0.5215785f;
  46. barber = 0; //Deactivate barber pole phasing by default
  47. mis = 1.0f;
  48. Rmin = 625.0f; // 2N5457 typical on resistance at Vgs = 0
  49. Rmax = 22000.0f; // Resistor parallel to FET
  50. Rmx = Rmin / Rmax;
  51. Rconst = 1.0f + Rmx; // Handle parallel resistor relationship
  52. C = 0.00000005f; // 50 nF
  53. CFs = 2.0f * samplerate_f * C;
  54. invperiod = 1.0f / buffersize_f;
  55. }
  56. Phaser::~Phaser()
  57. {
  58. memory.devalloc(old.l);
  59. memory.devalloc(old.r);
  60. memory.devalloc(xn1.l);
  61. memory.devalloc(xn1.r);
  62. memory.devalloc(yn1.l);
  63. memory.devalloc(yn1.r);
  64. }
  65. /*
  66. * Effect output
  67. */
  68. void Phaser::out(const Stereo<float *> &input)
  69. {
  70. if(Panalog)
  71. AnalogPhase(input);
  72. else
  73. normalPhase(input);
  74. }
  75. void Phaser::AnalogPhase(const Stereo<float *> &input)
  76. {
  77. Stereo<float> gain(0.0f), lfoVal(0.0f), mod(0.0f), g(0.0f), b(0.0f), hpf(
  78. 0.0f);
  79. lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
  80. mod.l = lfoVal.l * width + (depth - 0.5f);
  81. mod.r = lfoVal.r * width + (depth - 0.5f);
  82. mod.l = limit(mod.l, ZERO_, ONE_);
  83. mod.r = limit(mod.r, ZERO_, ONE_);
  84. if(Phyper) {
  85. //Triangle wave squared is approximately sin on bottom, tri on top
  86. //Result is exponential sweep more akin to filter in synth with
  87. //exponential generator circuitry.
  88. mod.l *= mod.l;
  89. mod.r *= mod.r;
  90. }
  91. //g.l,g.r is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)]
  92. mod.l = sqrtf(1.0f - mod.l);
  93. mod.r = sqrtf(1.0f - mod.r);
  94. diff.r = (mod.r - oldgain.r) * invperiod;
  95. diff.l = (mod.l - oldgain.l) * invperiod;
  96. g = oldgain;
  97. oldgain = mod;
  98. for(int i = 0; i < buffersize; ++i) {
  99. g.l += diff.l; // Linear interpolation between LFO samples
  100. g.r += diff.r;
  101. Stereo<float> xn(input.l[i] * pangainL, input.r[i] * pangainR);
  102. if(barber) {
  103. g.l += 0.25;
  104. g.l -= floorf(g.l);
  105. g.r += 0.25;
  106. g.r -= floorf(g.r);
  107. }
  108. xn.l = applyPhase(xn.l, g.l, fb.l, hpf.l, yn1.l, xn1.l);
  109. xn.r = applyPhase(xn.r, g.r, fb.r, hpf.r, yn1.r, xn1.r);
  110. fb.l = xn.l * feedback;
  111. fb.r = xn.r * feedback;
  112. efxoutl[i] = xn.l;
  113. efxoutr[i] = xn.r;
  114. }
  115. if(Poutsub) {
  116. invSignal(efxoutl, buffersize);
  117. invSignal(efxoutr, buffersize);
  118. }
  119. }
  120. float Phaser::applyPhase(float x, float g, float fb,
  121. float &hpf, float *yn1, float *xn1)
  122. {
  123. for(int j = 0; j < Pstages; ++j) { //Phasing routine
  124. mis = 1.0f + offsetpct * offset[j];
  125. //This is symmetrical.
  126. //FET is not, so this deviates slightly, however sym dist. is
  127. //better sounding than a real FET.
  128. float d = (1.0f + 2.0f * (0.25f + g) * hpf * hpf * distortion) * mis;
  129. Rconst = 1.0f + mis * Rmx;
  130. // This is 1/R. R is being modulated to control filter fc.
  131. float b = (Rconst - g) / (d * Rmin);
  132. float gain = (CFs - b) / (CFs + b);
  133. yn1[j] = gain * (x + yn1[j]) - xn1[j];
  134. //high pass filter:
  135. //Distortion depends on the high-pass part of the AP stage.
  136. hpf = yn1[j] + (1.0f - gain) * xn1[j];
  137. xn1[j] = x;
  138. x = yn1[j];
  139. if(j == 1)
  140. x += fb; //Insert feedback after first phase stage
  141. }
  142. return x;
  143. }
  144. void Phaser::normalPhase(const Stereo<float *> &input)
  145. {
  146. Stereo<float> gain(0.0f), lfoVal(0.0f);
  147. lfo.effectlfoout(&lfoVal.l, &lfoVal.r);
  148. gain.l =
  149. (expf(lfoVal.l
  150. * PHASER_LFO_SHAPE) - 1) / (expf(PHASER_LFO_SHAPE) - 1.0f);
  151. gain.r =
  152. (expf(lfoVal.r
  153. * PHASER_LFO_SHAPE) - 1) / (expf(PHASER_LFO_SHAPE) - 1.0f);
  154. gain.l = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * gain.l * depth;
  155. gain.r = 1.0f - phase * (1.0f - depth) - (1.0f - phase) * gain.r * depth;
  156. gain.l = limit(gain.l, ZERO_, ONE_);
  157. gain.r = limit(gain.r, ZERO_, ONE_);
  158. for(int i = 0; i < buffersize; ++i) {
  159. float x = (float) i / buffersize_f;
  160. float x1 = 1.0f - x;
  161. //TODO think about making panning an external feature
  162. Stereo<float> xn(input.l[i] * pangainL + fb.l,
  163. input.r[i] * pangainR + fb.r);
  164. Stereo<float> g(gain.l * x + oldgain.l * x1,
  165. gain.r * x + oldgain.r * x1);
  166. xn.l = applyPhase(xn.l, g.l, old.l);
  167. xn.r = applyPhase(xn.r, g.r, old.r);
  168. //Left/Right crossing
  169. crossover(xn.l, xn.r, lrcross);
  170. fb.l = xn.l * feedback;
  171. fb.r = xn.r * feedback;
  172. efxoutl[i] = xn.l;
  173. efxoutr[i] = xn.r;
  174. }
  175. oldgain = gain;
  176. if(Poutsub) {
  177. invSignal(efxoutl, buffersize);
  178. invSignal(efxoutr, buffersize);
  179. }
  180. }
  181. float Phaser::applyPhase(float x, float g, float *old)
  182. {
  183. for(int j = 0; j < Pstages * 2; ++j) { //Phasing routine
  184. float tmp = old[j];
  185. old[j] = g * tmp + x;
  186. x = tmp - g * old[j];
  187. }
  188. return x;
  189. }
  190. /*
  191. * Cleanup the effect
  192. */
  193. void Phaser::cleanup()
  194. {
  195. fb = oldgain = Stereo<float>(0.0f);
  196. for(int i = 0; i < Pstages * 2; ++i) {
  197. old.l[i] = 0.0f;
  198. old.r[i] = 0.0f;
  199. }
  200. for(int i = 0; i < Pstages; ++i) {
  201. xn1.l[i] = 0.0f;
  202. yn1.l[i] = 0.0f;
  203. xn1.r[i] = 0.0f;
  204. yn1.r[i] = 0.0f;
  205. }
  206. }
  207. /*
  208. * Parameter control
  209. */
  210. void Phaser::setwidth(unsigned char Pwidth)
  211. {
  212. this->Pwidth = Pwidth;
  213. width = ((float)Pwidth / 127.0f);
  214. }
  215. void Phaser::setfb(unsigned char Pfb)
  216. {
  217. this->Pfb = Pfb;
  218. feedback = (float) (Pfb - 64) / 64.2f;
  219. }
  220. void Phaser::setvolume(unsigned char Pvolume)
  221. {
  222. this->Pvolume = Pvolume;
  223. outvolume = Pvolume / 127.0f;
  224. if(insertion == 0)
  225. volume = 1.0f;
  226. else
  227. volume = outvolume;
  228. }
  229. void Phaser::setdistortion(unsigned char Pdistortion)
  230. {
  231. this->Pdistortion = Pdistortion;
  232. distortion = (float)Pdistortion / 127.0f;
  233. }
  234. void Phaser::setoffset(unsigned char Poffset)
  235. {
  236. this->Poffset = Poffset;
  237. offsetpct = (float)Poffset / 127.0f;
  238. }
  239. void Phaser::setstages(unsigned char Pstages)
  240. {
  241. memory.devalloc(old.l);
  242. memory.devalloc(old.r);
  243. memory.devalloc(xn1.l);
  244. memory.devalloc(xn1.r);
  245. memory.devalloc(yn1.l);
  246. memory.devalloc(yn1.r);
  247. this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages);
  248. old = Stereo<float *>(memory.valloc<float>(Pstages * 2),
  249. memory.valloc<float>(Pstages * 2));
  250. xn1 = Stereo<float *>(memory.valloc<float>(Pstages),
  251. memory.valloc<float>(Pstages));
  252. yn1 = Stereo<float *>(memory.valloc<float>(Pstages),
  253. memory.valloc<float>(Pstages));
  254. cleanup();
  255. }
  256. void Phaser::setphase(unsigned char Pphase)
  257. {
  258. this->Pphase = Pphase;
  259. phase = (Pphase / 127.0f);
  260. }
  261. void Phaser::setdepth(unsigned char Pdepth)
  262. {
  263. this->Pdepth = Pdepth;
  264. depth = (float)(Pdepth) / 127.0f;
  265. }
  266. void Phaser::setpreset(unsigned char npreset)
  267. {
  268. const int PRESET_SIZE = 15;
  269. const int NUM_PRESETS = 12;
  270. unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
  271. //Phaser
  272. //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  273. {64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20,
  274. 0, 0,
  275. 0 },
  276. {64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20, 0, 0,
  277. 0 },
  278. {64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0,
  279. 0 },
  280. {39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0,
  281. 0 },
  282. {64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0,
  283. 0 },
  284. {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0,
  285. 0 },
  286. //APhaser
  287. //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  288. {64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110,1, 20,
  289. 1 },
  290. {64, 64, 14, 5, 1, 64, 70, 40, 6, 10, 0, 110,1, 20,
  291. 1 },
  292. {64, 64, 9, 0, 0, 64, 60, 40, 8, 10, 0, 40, 0, 20,
  293. 1 },
  294. {64, 64, 14, 10, 0, 64, 45, 80, 7, 10, 1, 110,1, 20,
  295. 1 },
  296. {25, 64, 127, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0, 20,
  297. 1 },
  298. {64, 64, 1, 10, 1, 64, 70, 40, 12, 10, 0, 110,1, 20,
  299. 1 }
  300. };
  301. if(npreset >= NUM_PRESETS)
  302. npreset = NUM_PRESETS - 1;
  303. for(int n = 0; n < PRESET_SIZE; ++n)
  304. changepar(n, presets[npreset][n]);
  305. Ppreset = npreset;
  306. }
  307. void Phaser::changepar(int npar, unsigned char value)
  308. {
  309. switch(npar) {
  310. case 0:
  311. setvolume(value);
  312. break;
  313. case 1:
  314. setpanning(value);
  315. break;
  316. case 2:
  317. lfo.Pfreq = value;
  318. lfo.updateparams();
  319. break;
  320. case 3:
  321. lfo.Prandomness = value;
  322. lfo.updateparams();
  323. break;
  324. case 4:
  325. lfo.PLFOtype = value;
  326. lfo.updateparams();
  327. barber = (2 == value);
  328. break;
  329. case 5:
  330. lfo.Pstereo = value;
  331. lfo.updateparams();
  332. break;
  333. case 6:
  334. setdepth(value);
  335. break;
  336. case 7:
  337. setfb(value);
  338. break;
  339. case 8:
  340. setstages(value);
  341. break;
  342. case 9:
  343. setlrcross(value);
  344. setoffset(value);
  345. break;
  346. case 10:
  347. Poutsub = min((int)value, 1);
  348. break;
  349. case 11:
  350. setphase(value);
  351. setwidth(value);
  352. break;
  353. case 12:
  354. Phyper = min((int)value, 1);
  355. break;
  356. case 13:
  357. setdistortion(value);
  358. break;
  359. case 14:
  360. Panalog = value;
  361. break;
  362. }
  363. }
  364. unsigned char Phaser::getpar(int npar) const
  365. {
  366. switch(npar) {
  367. case 0: return Pvolume;
  368. case 1: return Ppanning;
  369. case 2: return lfo.Pfreq;
  370. case 3: return lfo.Prandomness;
  371. case 4: return lfo.PLFOtype;
  372. case 5: return lfo.Pstereo;
  373. case 6: return Pdepth;
  374. case 7: return Pfb;
  375. case 8: return Pstages;
  376. case 9: return Plrcross;
  377. return Poffset; //same
  378. case 10: return Poutsub;
  379. case 11: return Pphase;
  380. return Pwidth; //same
  381. case 12: return Phyper;
  382. case 13: return Pdistortion;
  383. case 14: return Panalog;
  384. default: return 0;
  385. }
  386. }